Merge "sdm: Use monotonic clock in HAL" into display.lnx.5.0
diff --git a/Android.mk b/Android.mk
index 44393b0..a4d5687 100644
--- a/Android.mk
+++ b/Android.mk
@@ -1,3 +1,4 @@
+ifneq ($(TARGET_DISABLE_DISPLAY),true)
sdm-libs := sdm/libs
display-hals := include libqservice libqdutils $(sdm-libs)/utils $(sdm-libs)/core
@@ -15,3 +16,4 @@
include $(call all-named-subdir-makefiles,$(display-hals))
endif
endif
+endif #TARGET_DISABLE_DISPLAY
diff --git a/gpu_tonemapper/EGLImageWrapper.cpp b/gpu_tonemapper/EGLImageWrapper.cpp
index dfc16d8..19bf093 100644
--- a/gpu_tonemapper/EGLImageWrapper.cpp
+++ b/gpu_tonemapper/EGLImageWrapper.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2016-2017, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2016-2018, The Linux Foundation. All rights reserved.
* Not a Contribution.
*
* Copyright 2015 The Android Open Source Project
@@ -22,10 +22,19 @@
#include <gralloc_priv.h>
#include <ui/GraphicBuffer.h>
#include <fcntl.h>
-#include <linux/msm_ion.h>
+#include <string>
+#include <map>
+#include <utility>
+using std::string;
+using std::map;
+using std::pair;
+
+static string pidString = std::to_string(getpid());
+
+#ifndef TARGET_ION_ABI_VERSION
//-----------------------------------------------------------------------------
-void free_ion_cookie(int ion_fd, int cookie)
+static void free_ion_cookie(int ion_fd, int cookie)
//-----------------------------------------------------------------------------
{
if (ion_fd && !ioctl(ion_fd, ION_IOC_FREE, &cookie)) {
@@ -35,120 +44,169 @@
}
//-----------------------------------------------------------------------------
-int get_ion_cookie(int ion_fd, int fd)
+static int get_ion_cookie(int ion_fd, int fd)
//-----------------------------------------------------------------------------
{
- int cookie = fd;
+ int cookie = fd;
- struct ion_fd_data fdData;
- memset(&fdData, 0, sizeof(fdData));
- fdData.fd = fd;
+ struct ion_fd_data fdData;
+ memset(&fdData, 0, sizeof(fdData));
+ fdData.fd = fd;
- if (ion_fd && !ioctl(ion_fd, ION_IOC_IMPORT, &fdData)) {
- cookie = fdData.handle;
- } else {
- ALOGE("ION_IOC_IMPORT failed: ion_fd = %d, fd = %d", ion_fd, fd);
- }
+ if (ion_fd && !ioctl(ion_fd, ION_IOC_IMPORT, &fdData)) {
+ cookie = fdData.handle;
+ } else {
+ ALOGE("ION_IOC_IMPORT failed: ion_fd = %d, fd = %d", ion_fd, fd);
+ }
- return cookie;
+ return cookie;
}
-
+#else
//-----------------------------------------------------------------------------
-EGLImageWrapper::DeleteEGLImageCallback::DeleteEGLImageCallback(int fd)
+static string get_ion_buff_str(int buff_fd)
//-----------------------------------------------------------------------------
{
- ion_fd = fd;
-}
-
-//-----------------------------------------------------------------------------
-void EGLImageWrapper::DeleteEGLImageCallback::operator()(int& k, EGLImageBuffer*& eglImage)
-//-----------------------------------------------------------------------------
-{
- free_ion_cookie(ion_fd, k);
- if( eglImage != 0 )
- {
- delete eglImage;
+ string retStr = {};
+ if (buff_fd >= 0) {
+ string fdString = std::to_string(buff_fd);
+ string symlinkPath = "/proc/"+pidString+"/fd/"+fdString;
+ char buffer[1024] = {};
+ ssize_t ret = ::readlink(symlinkPath.c_str(), buffer, sizeof(buffer) - 1);
+ if (ret != -1) {
+ buffer[ret] = '\0';
+ retStr = buffer;
}
+ }
+
+ return retStr;
+}
+#endif
+
+//-----------------------------------------------------------------------------
+void EGLImageWrapper::DeleteEGLImageCallback::operator()(int& buffInt, EGLImageBuffer*& eglImage)
+//-----------------------------------------------------------------------------
+{
+ if (eglImage != 0) {
+ delete eglImage;
+ }
+
+#ifndef TARGET_ION_ABI_VERSION
+ free_ion_cookie(ion_fd, buffInt /* cookie */);
+#else
+ if (!mapClearPending) {
+ for (auto it = buffStrbuffIntMapPtr->begin(); it != buffStrbuffIntMapPtr->end(); it++) {
+ if (it->second == buffInt /* counter */) {
+ buffStrbuffIntMapPtr->erase(it);
+ return;
+ }
+ }
+ }
+#endif
}
//-----------------------------------------------------------------------------
EGLImageWrapper::EGLImageWrapper()
//-----------------------------------------------------------------------------
{
- eglImageBufferMap = new android::LruCache<int, EGLImageBuffer*>(32);
- ion_fd = open("/dev/ion", O_RDONLY);
- callback = new DeleteEGLImageCallback(ion_fd);
- eglImageBufferMap->setOnEntryRemovedListener(callback);
+ eglImageBufferCache = new android::LruCache<int, EGLImageBuffer*>(32);
+ callback = new DeleteEGLImageCallback(&buffStrbuffIntMap);
+ eglImageBufferCache->setOnEntryRemovedListener(callback);
+
+#ifndef TARGET_ION_ABI_VERSION
+ ion_fd = open("/dev/ion", O_RDONLY);
+ callback->ion_fd = ion_fd;
+#endif
}
//-----------------------------------------------------------------------------
EGLImageWrapper::~EGLImageWrapper()
//-----------------------------------------------------------------------------
{
- if( eglImageBufferMap != 0 )
- {
- eglImageBufferMap->clear();
- delete eglImageBufferMap;
- eglImageBufferMap = 0;
+ if (eglImageBufferCache != 0) {
+ if (callback != 0) {
+ callback->mapClearPending = true;
}
+ eglImageBufferCache->clear();
+ delete eglImageBufferCache;
+ eglImageBufferCache = 0;
+ buffStrbuffIntMap.clear();
+ }
- if( callback != 0 )
- {
- delete callback;
- callback = 0;
- }
+ if (callback != 0) {
+ delete callback;
+ callback = 0;
+ }
- if( ion_fd > 0 )
- {
- close(ion_fd);
- }
+#ifndef TARGET_ION_ABI_VERSION
+ if (ion_fd > 0) {
+ close(ion_fd);
ion_fd = -1;
+ }
+#endif
}
+
//-----------------------------------------------------------------------------
static EGLImageBuffer* L_wrap(const private_handle_t *src)
//-----------------------------------------------------------------------------
{
- EGLImageBuffer* result = 0;
+ EGLImageBuffer* result = 0;
- native_handle_t *native_handle = const_cast<private_handle_t *>(src);
+ native_handle_t *native_handle = const_cast<private_handle_t *>(src);
- int flags = android::GraphicBuffer::USAGE_HW_TEXTURE |
- android::GraphicBuffer::USAGE_SW_READ_NEVER |
- android::GraphicBuffer::USAGE_SW_WRITE_NEVER;
+ int flags = android::GraphicBuffer::USAGE_HW_TEXTURE |
+ android::GraphicBuffer::USAGE_SW_READ_NEVER |
+ android::GraphicBuffer::USAGE_SW_WRITE_NEVER;
- if (src->flags & private_handle_t::PRIV_FLAGS_SECURE_BUFFER) {
- flags |= android::GraphicBuffer::USAGE_PROTECTED;
- }
+ if (src->flags & private_handle_t::PRIV_FLAGS_SECURE_BUFFER) {
+ flags |= android::GraphicBuffer::USAGE_PROTECTED;
+ }
- android::sp<android::GraphicBuffer> graphicBuffer =
- new android::GraphicBuffer(src->unaligned_width, src->unaligned_height, src->format,
+ android::sp<android::GraphicBuffer> graphicBuffer =
+ new android::GraphicBuffer(src->unaligned_width, src->unaligned_height, src->format,
#ifndef __NOUGAT__
- 1, // Layer count
+ 1, // Layer count
#endif
- flags, src->width /*src->stride*/,
- native_handle, false);
+ flags, src->width /*src->stride*/,
+ native_handle, false);
- result = new EGLImageBuffer(graphicBuffer);
+ result = new EGLImageBuffer(graphicBuffer);
- return result;
+ return result;
}
//-----------------------------------------------------------------------------
EGLImageBuffer *EGLImageWrapper::wrap(const void *pvt_handle)
//-----------------------------------------------------------------------------
{
- const private_handle_t *src = static_cast<const private_handle_t *>(pvt_handle);
+ const private_handle_t *src = static_cast<const private_handle_t *>(pvt_handle);
- int ion_cookie = get_ion_cookie(ion_fd, src->fd);
- EGLImageBuffer* eglImage = eglImageBufferMap->get(ion_cookie);
- if( eglImage == 0 )
- {
+#ifndef TARGET_ION_ABI_VERSION
+ int ion_cookie = get_ion_cookie(ion_fd, src->fd);
+ EGLImageBuffer* eglImage = nullptr;
+ eglImage = eglImageBufferCache->get(ion_cookie);
+ if (eglImage == 0) {
+ eglImage = L_wrap(src);
+ eglImageBufferCache->put(ion_cookie, eglImage);
+ } else {
+ free_ion_cookie(ion_fd, ion_cookie);
+ }
+#else
+ string buffStr = get_ion_buff_str(src->fd);
+ EGLImageBuffer* eglImage = nullptr;
+ if (!buffStr.empty()) {
+ auto it = buffStrbuffIntMap.find(buffStr);
+ if (it != buffStrbuffIntMap.end()) {
+ eglImage = eglImageBufferCache->get(it->second);
+ } else {
eglImage = L_wrap(src);
- eglImageBufferMap->put(ion_cookie, eglImage);
+ buffStrbuffIntMap.insert(pair<string, int>(buffStr, buffInt));
+ eglImageBufferCache->put(buffInt, eglImage);
+ buffInt++;
}
- else {
- free_ion_cookie(ion_fd, ion_cookie);
- }
+ } else {
+ ALOGE("Could not provide an eglImage for fd = %d, EGLImageWrapper = %p", src->fd, this);
+ }
+#endif
- return eglImage;
+ return eglImage;
}
diff --git a/gpu_tonemapper/EGLImageWrapper.h b/gpu_tonemapper/EGLImageWrapper.h
index e9a4d68..296aa66 100644
--- a/gpu_tonemapper/EGLImageWrapper.h
+++ b/gpu_tonemapper/EGLImageWrapper.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2016-2017, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2016-2018, The Linux Foundation. All rights reserved.
* Not a Contribution.
*
* Copyright 2015 The Android Open Source Project
@@ -21,27 +21,40 @@
#define __TONEMAPPER_EGLIMAGEWRAPPER_H__
#include <utils/LruCache.h>
+#include <linux/msm_ion.h>
+#include <string>
+#include <map>
#include "EGLImageBuffer.h"
+using std::string;
+using std::map;
+
class EGLImageWrapper {
- private:
- class DeleteEGLImageCallback : public android::OnEntryRemoved<int, EGLImageBuffer*>
- {
- private:
- int ion_fd;
- public:
- DeleteEGLImageCallback(int ion_fd);
- void operator()(int& ion_cookie, EGLImageBuffer*& eglImage);
- };
+ private:
+ class DeleteEGLImageCallback : public android::OnEntryRemoved<int, EGLImageBuffer*> {
+ public:
+ explicit DeleteEGLImageCallback(map<string, int>* mapPtr) { buffStrbuffIntMapPtr = mapPtr; }
+ void operator()(int& buffInt, EGLImageBuffer*& eglImage);
+ map<string, int>* buffStrbuffIntMapPtr = nullptr;
+ bool mapClearPending = false;
+ #ifndef TARGET_ION_ABI_VERSION
+ int ion_fd = -1;
+ #endif
+ };
- android::LruCache<int, EGLImageBuffer *>* eglImageBufferMap;
- DeleteEGLImageCallback* callback;
- int ion_fd;
+ android::LruCache<int, EGLImageBuffer *>* eglImageBufferCache;
+ map<string, int> buffStrbuffIntMap = {};
+ DeleteEGLImageCallback* callback = 0;
+ #ifndef TARGET_ION_ABI_VERSION
+ int ion_fd = -1;
+ #else
+ uint64_t buffInt = 0;
+ #endif
- public:
- EGLImageWrapper();
- ~EGLImageWrapper();
- EGLImageBuffer* wrap(const void *pvt_handle);
+ public:
+ EGLImageWrapper();
+ ~EGLImageWrapper();
+ EGLImageBuffer* wrap(const void *pvt_handle);
};
-#endif //__TONEMAPPER_EGLIMAGEWRAPPER_H__
+#endif // __TONEMAPPER_EGLIMAGEWRAPPER_H__
diff --git a/gpu_tonemapper/Tonemapper.cpp b/gpu_tonemapper/Tonemapper.cpp
index 811e091..2605c7f 100644
--- a/gpu_tonemapper/Tonemapper.cpp
+++ b/gpu_tonemapper/Tonemapper.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2016-2017, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2016-2018, The Linux Foundation. All rights reserved.
* Not a Contribution.
*
* Copyright 2015 The Android Open Source Project
@@ -137,10 +137,14 @@
}
// set destination
- engine_setDestination(dst_buffer->getFramebuffer(), 0, 0, dst_buffer->getWidth(),
- dst_buffer->getHeight());
+ if (dst_buffer) {
+ engine_setDestination(dst_buffer->getFramebuffer(), 0, 0, dst_buffer->getWidth(),
+ dst_buffer->getHeight());
+ }
// set source
- engine_setExternalInputBuffer(0, src_buffer->getTexture());
+ if (src_buffer) {
+ engine_setExternalInputBuffer(0, src_buffer->getTexture());
+ }
// set 3d lut
engine_set3DInputBuffer(1, tonemapTexture);
// set non-uniform xform
diff --git a/libdrmutils/drm_interface.h b/libdrmutils/drm_interface.h
index 97660ea..fc40b2e 100644
--- a/libdrmutils/drm_interface.h
+++ b/libdrmutils/drm_interface.h
@@ -1,5 +1,5 @@
/*
-* Copyright (c) 2017, The Linux Foundation. All rights reserved.
+* Copyright (c) 2017-2018, 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
@@ -60,6 +60,12 @@
*/
PLANE_SET_DST_RECT,
/*
+ * Op: Sets plane exclusion rect
+ * Arg: uint32_t - Plane ID
+ * drm_clip_rect - Exclusion Rectangle
+ */
+ PLANE_SET_EXCL_RECT,
+ /*
* Op: Sets plane zorder
* Arg: uint32_t - Plane ID
* uint32_t - zorder
@@ -150,6 +156,12 @@
*/
PLANE_SET_MULTIRECT_MODE,
/*
+ * Op: Sets rotator output frame buffer ID for plane.
+ * Arg: uint32_t - Plane ID
+ * uint32_t - Framebuffer ID
+ */
+ PLANE_SET_ROT_FB_ID,
+ /*
* Op: Activate or deactivate a CRTC
* Arg: uint32_t - CRTC ID
* uint32_t - 1 to enable, 0 to disable
@@ -211,6 +223,12 @@
*/
CRTC_SET_DRAM_IB,
/*
+ * Op: Sets Rotator BW for inline rotation
+ * Arg: uint32_t - CRTC ID
+ * uint32_t - rot_bw
+ */
+ CRTC_SET_ROT_PREFILL_BW,
+ /*
* Op: Sets rotator clock for inline rotation
* Arg: uint32_t - CRTC ID
* uint32_t - rot_clk
@@ -377,6 +395,14 @@
enum struct SmartDMARevision {
V1,
V2,
+ V2p5
+};
+
+/* Inline Rotation version */
+enum struct InlineRotationVersion {
+ UNKNOWN,
+ V1,
+ V1p1, // Rotator FB ID needs to be set
};
/* Per CRTC Resource Info*/
@@ -428,14 +454,17 @@
// FourCC format enum and modifier
std::vector<std::pair<uint32_t, uint64_t>> formats_supported;
uint32_t max_linewidth;
+ uint32_t max_scaler_linewidth;
uint32_t max_upscale;
uint32_t max_downscale;
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.
+ bool has_excl_rect = false;
QSEEDStepVersion qseed3_version;
bool multirect_prop_present = false;
+ InlineRotationVersion inrot_version; // inline rotation version
};
// All DRM Planes as map<Plane_id , plane_type_info> listed from highest to lowest priority
@@ -592,11 +621,12 @@
/* Perform request operation.
*
* [input]: opcode: operation code from DRMOps list.
+ * obj_id: Relevant crtc, connector, plane id
* var_arg: arguments for DRMOps's can differ in number and
* data type. Refer above DRMOps to details.
* [return]: Error code if the API fails, 0 on success.
*/
- virtual int Perform(DRMOps opcode, ...) = 0;
+ virtual int Perform(DRMOps opcode, uint32_t obj_id, ...) = 0;
/*
* Commit the params set via Perform(). Also resets the properties after commit. Needs to be
diff --git a/libgralloc1/Android.mk b/libgralloc1/Android.mk
index cdb651c..49ceae5 100644
--- a/libgralloc1/Android.mk
+++ b/libgralloc1/Android.mk
@@ -8,12 +8,14 @@
LOCAL_MODULE_RELATIVE_PATH := hw
LOCAL_MODULE_TAGS := optional
LOCAL_C_INCLUDES := $(common_includes) \
- external/libcxx/include/
+ external/libcxx/include/ \
+ system/core/libion/include/ \
+ system/core/libion/kernel-headers/ \
+ $(TARGET_OUT_INTERMEDIATES)/KERNEL_OBJ/usr/include
LOCAL_HEADER_LIBRARIES := display_headers
-LOCAL_SHARED_LIBRARIES := $(common_libs) libqdMetaData libsync libgrallocutils
+LOCAL_SHARED_LIBRARIES := $(common_libs) libqdMetaData libsync libgrallocutils libion
LOCAL_CFLAGS := $(common_flags) -DLOG_TAG=\"qdgralloc\" -Wall -std=c++11 -Werror
-LOCAL_CFLAGS += -isystem $(kernel_includes)
LOCAL_CLANG := true
LOCAL_ADDITIONAL_DEPENDENCIES := $(common_deps) $(kernel_deps)
LOCAL_SRC_FILES := gr_ion_alloc.cpp \
diff --git a/libgralloc1/gr_allocator.cpp b/libgralloc1/gr_allocator.cpp
index 066ac34..7a54187 100644
--- a/libgralloc1/gr_allocator.cpp
+++ b/libgralloc1/gr_allocator.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2011-2017, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2011-2018, The Linux Foundation. All rights reserved.
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
@@ -49,6 +49,10 @@
#define ION_FLAG_CP_CAMERA_PREVIEW 0
#endif
+#ifndef ION_SECURE
+#define ION_SECURE ION_FLAG_SECURE
+#endif
+
#ifdef MASTER_SIDE_CP
#define CP_HEAP_ID ION_SECURE_HEAP_ID
#define SD_HEAP_ID ION_SECURE_DISPLAY_HEAP_ID
@@ -137,9 +141,10 @@
return -EINVAL;
}
-int Allocator::CleanBuffer(void *base, unsigned int size, unsigned int offset, int handle, int op) {
+int Allocator::CleanBuffer(void *base, unsigned int size, unsigned int offset, int handle, int op,
+ int fd) {
if (ion_allocator_) {
- return ion_allocator_->CleanBuffer(base, size, offset, handle, op);
+ return ion_allocator_->CleanBuffer(base, size, offset, handle, op, fd);
}
return -EINVAL;
@@ -207,7 +212,11 @@
} else if (prod_usage & GRALLOC1_PRODUCER_USAGE_PRIVATE_10BIT) {
gr_format = HAL_PIXEL_FORMAT_YCbCr_420_P010_VENUS;
} else if (cons_usage & GRALLOC1_CONSUMER_USAGE_VIDEO_ENCODER) {
- gr_format = HAL_PIXEL_FORMAT_NV12_ENCODEABLE; // NV12
+ if (prod_usage & GRALLOC1_PRODUCER_USAGE_PRIVATE_VIDEO_NV21_ENCODER) {
+ gr_format = HAL_PIXEL_FORMAT_NV21_ENCODEABLE; // NV21
+ } else {
+ gr_format = HAL_PIXEL_FORMAT_NV12_ENCODEABLE; // NV12
+ }
} else if (cons_usage & GRALLOC1_CONSUMER_USAGE_CAMERA) {
if (prod_usage & GRALLOC1_PRODUCER_USAGE_CAMERA) {
// Assumed ZSL if both producer and consumer camera flags set
diff --git a/libgralloc1/gr_allocator.h b/libgralloc1/gr_allocator.h
index d57f50e..c059ba6 100644
--- a/libgralloc1/gr_allocator.h
+++ b/libgralloc1/gr_allocator.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2011-2017, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2011-2018, 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
@@ -52,7 +52,7 @@
int MapBuffer(void **base, unsigned int size, unsigned int offset, int fd);
int ImportBuffer(int fd);
int FreeBuffer(void *base, unsigned int size, unsigned int offset, int fd, int handle);
- int CleanBuffer(void *base, unsigned int size, unsigned int offset, int handle, int op);
+ int CleanBuffer(void *base, unsigned int size, unsigned int offset, int handle, int op, int fd);
int AllocateMem(AllocData *data, gralloc1_producer_usage_t prod_usage,
gralloc1_consumer_usage_t cons_usage);
// @return : index of the descriptor with maximum buffer size req
diff --git a/libgralloc1/gr_buf_mgr.cpp b/libgralloc1/gr_buf_mgr.cpp
index 815f2b0..8a1403a 100644
--- a/libgralloc1/gr_buf_mgr.cpp
+++ b/libgralloc1/gr_buf_mgr.cpp
@@ -329,7 +329,7 @@
if (!err && (hnd->flags & private_handle_t::PRIV_FLAGS_USES_ION) &&
(hnd->flags & private_handle_t::PRIV_FLAGS_CACHED)) {
if (allocator_->CleanBuffer(reinterpret_cast<void *>(hnd->base), hnd->size, hnd->offset,
- buf->ion_handle_main, CACHE_INVALIDATE)) {
+ buf->ion_handle_main, CACHE_INVALIDATE, hnd->fd)) {
return GRALLOC1_ERROR_BAD_HANDLE;
}
}
@@ -355,7 +355,7 @@
if (hnd->flags & private_handle_t::PRIV_FLAGS_NEEDS_FLUSH) {
if (allocator_->CleanBuffer(reinterpret_cast<void *>(hnd->base), hnd->size, hnd->offset,
- buf->ion_handle_main, CACHE_CLEAN) != 0) {
+ buf->ion_handle_main, CACHE_CLEAN, hnd->fd) != 0) {
status = GRALLOC1_ERROR_BAD_HANDLE;
}
hnd->flags &= ~private_handle_t::PRIV_FLAGS_NEEDS_FLUSH;
@@ -517,8 +517,11 @@
hnd->base_metadata = 0;
hnd->layer_count = layer_count;
- ColorSpace_t colorSpace = ITU_R_601;
- setMetaData(hnd, UPDATE_COLOR_SPACE, reinterpret_cast<void *>(&colorSpace));
+ if (buffer_type == BUFFER_TYPE_VIDEO) {
+ // set default csc to 601L for only video buffers
+ ColorSpace_t colorSpace = ITU_R_601;
+ setMetaData(hnd, UPDATE_COLOR_SPACE, reinterpret_cast<void *>(&colorSpace));
+ }
*handle = hnd;
RegisterHandleLocked(hnd, data.ion_handle, e_data.ion_handle);
ALOGD_IF(DEBUG, "Allocated buffer handle: %p id: %" PRIu64, hnd, hnd->id);
diff --git a/libgralloc1/gr_ion_alloc.cpp b/libgralloc1/gr_ion_alloc.cpp
index c8300ab..4fc67f4 100644
--- a/libgralloc1/gr_ion_alloc.cpp
+++ b/libgralloc1/gr_ion_alloc.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2011-2017, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2011-2018, 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,11 @@
#define ATRACE_TAG (ATRACE_TAG_GRAPHICS | ATRACE_TAG_HAL)
#include <sys/ioctl.h>
#include <sys/mman.h>
+#include <linux/msm_ion.h>
+#if TARGET_ION_ABI_VERSION >= 2
+#include <ion/ion.h>
+#include <linux/dma-buf.h>
+#endif
#include <stdlib.h>
#include <fcntl.h>
#include <cutils/log.h>
@@ -47,7 +52,7 @@
bool IonAlloc::Init() {
if (ion_dev_fd_ == FD_INIT) {
- ion_dev_fd_ = open(kIonDevice, O_RDONLY);
+ ion_dev_fd_ = OpenIonDevice();
}
if (ion_dev_fd_ < 0) {
@@ -59,6 +64,103 @@
return true;
}
+#if TARGET_ION_ABI_VERSION >= 2 // Use libion APIs for new ion
+
+int IonAlloc::OpenIonDevice() {
+ return ion_open();
+}
+
+void IonAlloc::CloseIonDevice() {
+ if (ion_dev_fd_ > FD_INIT) {
+ ion_close(ion_dev_fd_);
+ }
+
+ ion_dev_fd_ = FD_INIT;
+}
+
+int IonAlloc::AllocBuffer(AllocData *data) {
+ ATRACE_CALL();
+ int err = 0;
+ int fd = -1;
+ unsigned int flags = data->flags;
+
+ flags |= data->uncached ? 0 : ION_FLAG_CACHED;
+
+ std::string tag_name{};
+ if (ATRACE_ENABLED()) {
+ tag_name = "libion alloc size: " + std::to_string(data->size);
+ }
+
+ ATRACE_BEGIN(tag_name.c_str());
+ err = ion_alloc_fd(ion_dev_fd_, data->size, data->align, data->heap_id, flags, &fd);
+ ATRACE_END();
+ if (err) {
+ ALOGE("libion alloc failed");
+ return err;
+ }
+
+ data->fd = fd;
+ data->ion_handle = fd; // For new ion api ion_handle does not exists so reusing fd for now
+ ALOGD_IF(DEBUG, "libion: Allocated buffer size:%u fd:%d", data->size, data->fd);
+
+ return 0;
+}
+
+int IonAlloc::FreeBuffer(void *base, unsigned int size, unsigned int offset, int fd,
+ int /*ion_handle*/) {
+ ATRACE_CALL();
+ int err = 0;
+ ALOGD_IF(DEBUG, "libion: Freeing buffer base:%p size:%u fd:%d", base, size, fd);
+
+ if (base) {
+ err = UnmapBuffer(base, size, offset);
+ }
+
+ close(fd);
+ return err;
+}
+
+int IonAlloc::ImportBuffer(int fd) {
+ // For new ion api ion_handle does not exists so reusing fd for now
+ return fd;
+}
+
+int IonAlloc::CleanBuffer(void */*base*/, unsigned int /*size*/, unsigned int /*offset*/,
+ int /*handle*/, int op, int dma_buf_fd) {
+ ATRACE_CALL();
+ ATRACE_INT("operation id", op);
+
+ struct dma_buf_sync sync;
+ int err = 0;
+
+ switch (op) {
+ case CACHE_CLEAN:
+ sync.flags = DMA_BUF_SYNC_END | DMA_BUF_SYNC_RW;
+ break;
+ case CACHE_INVALIDATE:
+ sync.flags = DMA_BUF_SYNC_START | DMA_BUF_SYNC_RW;
+ break;
+ default:
+ ALOGE("%s: Invalid operation %d", __FUNCTION__, op);
+ return -1;
+ }
+
+ if (ioctl(dma_buf_fd, INT(DMA_BUF_IOCTL_SYNC), &sync)) {
+ err = -errno;
+ ALOGE("%s: DMA_BUF_IOCTL_SYNC failed with error - %s", __FUNCTION__, strerror(errno));
+ return err;
+ }
+
+ return 0;
+}
+
+#else
+#ifndef TARGET_ION_ABI_VERSION // Use old ion apis directly
+
+int IonAlloc::OpenIonDevice() {
+ return open(kIonDevice, O_RDONLY);
+}
+
void IonAlloc::CloseIonDevice() {
if (ion_dev_fd_ > FD_INIT) {
close(ion_dev_fd_);
@@ -131,25 +233,6 @@
return err;
}
-int IonAlloc::MapBuffer(void **base, unsigned int size, unsigned int offset, int fd) {
- ATRACE_CALL();
- int err = 0;
- void *addr = 0;
-
- // It is a (quirky) requirement of ION to have opened the
- // ion fd in the process that is doing the mapping
- addr = mmap(0, size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
- *base = addr;
- if (addr == MAP_FAILED) {
- err = -errno;
- ALOGE("ion: Failed to map memory in the client: %s", strerror(errno));
- } else {
- ALOGD_IF(DEBUG, "ion: Mapped buffer base:%p size:%u offset:%u fd:%d", addr, size, offset, fd);
- }
-
- return err;
-}
-
int IonAlloc::ImportBuffer(int fd) {
struct ion_fd_data fd_data;
int err = 0;
@@ -162,20 +245,8 @@
return fd_data.handle;
}
-int IonAlloc::UnmapBuffer(void *base, unsigned int size, unsigned int /*offset*/) {
- ATRACE_CALL();
- ALOGD_IF(DEBUG, "ion: Unmapping buffer base:%p size:%u", base, size);
-
- int err = 0;
- if (munmap(base, size)) {
- err = -errno;
- ALOGE("ion: Failed to unmap memory at %p : %s", base, strerror(errno));
- }
-
- return err;
-}
-
-int IonAlloc::CleanBuffer(void *base, unsigned int size, unsigned int offset, int handle, int op) {
+int IonAlloc::CleanBuffer(void *base, unsigned int size, unsigned int offset, int handle, int op,
+ int /*fd*/) {
ATRACE_CALL();
ATRACE_INT("operation id", op);
struct ion_flush_data flush_data;
@@ -210,4 +281,65 @@
return 0;
}
+#else // This ion version is not supported
+
+int IonAlloc::OpenIonDevice() {
+ return -EINVAL;
+}
+
+void IonAlloc::CloseIonDevice() {
+}
+
+int IonAlloc::AllocBuffer(AllocData * /*data*/) {
+ return -EINVAL;
+}
+
+int IonAlloc::FreeBuffer(void * /*base*/, unsigned int /*size*/, unsigned int /*offset*/,
+ int /*fd*/, int /*ion_handle*/) {
+ return -EINVAL;
+}
+
+int IonAlloc::ImportBuffer(int /*fd*/) {
+ return -EINVAL;
+}
+
+int IonAlloc::CleanBuffer(void * /*base*/, unsigned int /*size*/, unsigned int /*offset*/,
+ int /*handle*/, int /*op*/, int /*fd*/) {
+ return -EINVAL;
+}
+
+#endif
+#endif // TARGET_ION_ABI_VERSION
+
+
+int IonAlloc::MapBuffer(void **base, unsigned int size, unsigned int offset, int fd) {
+ ATRACE_CALL();
+ int err = 0;
+ void *addr = 0;
+
+ addr = mmap(0, size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
+ *base = addr;
+ if (addr == MAP_FAILED) {
+ err = -errno;
+ ALOGE("ion: Failed to map memory in the client: %s", strerror(errno));
+ } else {
+ ALOGD_IF(DEBUG, "ion: Mapped buffer base:%p size:%u offset:%u fd:%d", addr, size, offset, fd);
+ }
+
+ return err;
+}
+
+int IonAlloc::UnmapBuffer(void *base, unsigned int size, unsigned int /*offset*/) {
+ ATRACE_CALL();
+ ALOGD_IF(DEBUG, "ion: Unmapping buffer base:%p size:%u", base, size);
+
+ int err = 0;
+ if (munmap(base, size)) {
+ err = -errno;
+ ALOGE("ion: Failed to unmap memory at %p : %s", base, strerror(errno));
+ }
+
+ return err;
+}
+
} // namespace gralloc1
diff --git a/libgralloc1/gr_ion_alloc.h b/libgralloc1/gr_ion_alloc.h
index b25f509..b41f5f1 100644
--- a/libgralloc1/gr_ion_alloc.h
+++ b/libgralloc1/gr_ion_alloc.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2011-2017, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2011-2018, 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
@@ -68,10 +68,12 @@
int MapBuffer(void **base, unsigned int size, unsigned int offset, int fd);
int ImportBuffer(int fd);
int UnmapBuffer(void *base, unsigned int size, unsigned int offset);
- int CleanBuffer(void *base, unsigned int size, unsigned int offset, int handle, int op);
+ int CleanBuffer(void *base, unsigned int size, unsigned int offset, int handle, int op, int fd);
private:
+#ifndef TARGET_ION_ABI_VERSION
const char *kIonDevice = "/dev/ion";
+#endif
int OpenIonDevice();
void CloseIonDevice();
diff --git a/libgralloc1/gr_utils.cpp b/libgralloc1/gr_utils.cpp
index 480ad98..2eb0b11 100644
--- a/libgralloc1/gr_utils.cpp
+++ b/libgralloc1/gr_utils.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2011-2017, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2011-2018, 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
@@ -287,6 +287,7 @@
size = VENUS_BUFFER_SIZE(COLOR_FMT_NV12, width, height);
break;
case HAL_PIXEL_FORMAT_YCrCb_420_SP_VENUS:
+ case HAL_PIXEL_FORMAT_NV21_ENCODEABLE:
size = VENUS_BUFFER_SIZE(COLOR_FMT_NV21, width, height);
break;
case HAL_PIXEL_FORMAT_BLOB:
diff --git a/libgralloc1/gralloc_priv.h b/libgralloc1/gralloc_priv.h
index 7553017..07cc285 100644
--- a/libgralloc1/gralloc_priv.h
+++ b/libgralloc1/gralloc_priv.h
@@ -20,6 +20,7 @@
#ifndef __GRALLOC_PRIV_H__
#define __GRALLOC_PRIV_H__
+#include <errno.h>
#include <unistd.h>
#include "gr_priv_handle.h"
@@ -59,6 +60,8 @@
#define GRALLOC1_PRODUCER_USAGE_PRIVATE_10BIT_TP 0x08000000
#define GRALLOC1_CONSUMER_USAGE_PRIVATE_10BIT_TP 0x08000000
+/* This flag is used to indicate video NV21 format */
+#define GRALLOC1_PRODUCER_USAGE_PRIVATE_VIDEO_NV21_ENCODER (1ULL << 24)
/* Consumer flags */
/* TODO(user): Fix when producer and consumer flags are actually separated */
@@ -107,6 +110,7 @@
#define HAL_PIXEL_FORMAT_RGBA_5551 6
#define HAL_PIXEL_FORMAT_RGBA_4444 7
#define HAL_PIXEL_FORMAT_NV12_ENCODEABLE 0x102
+#define HAL_PIXEL_FORMAT_NV21_ENCODEABLE 0x7FA30C00
#define HAL_PIXEL_FORMAT_YCbCr_420_SP_VENUS 0x7FA30C04
#define HAL_PIXEL_FORMAT_YCbCr_420_SP_TILED 0x7FA30C03
#define HAL_PIXEL_FORMAT_YCbCr_420_SP 0x109
diff --git a/sdm/include/core/display_interface.h b/sdm/include/core/display_interface.h
index 303c89b..1f813ac 100644
--- a/sdm/include/core/display_interface.h
+++ b/sdm/include/core/display_interface.h
@@ -1,5 +1,5 @@
/*
-* Copyright (c) 2014 - 2017, The Linux Foundation. All rights reserved.
+* Copyright (c) 2014 - 2018, 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:
@@ -388,12 +388,13 @@
/*! @brief Method to set current state of the display device.
@param[in] state \link DisplayState \endlink
+ @param[in] pointer to release fence
@return \link DisplayError \endlink
@sa SetDisplayState
*/
- virtual DisplayError SetDisplayState(DisplayState state) = 0;
+ virtual DisplayError SetDisplayState(DisplayState state, int *release_fence) = 0;
/*! @brief Method to set active configuration for variable properties of the display device.
diff --git a/sdm/include/core/layer_buffer.h b/sdm/include/core/layer_buffer.h
index 649dda4..8f7f6fe 100644
--- a/sdm/include/core/layer_buffer.h
+++ b/sdm/include/core/layer_buffer.h
@@ -1,5 +1,5 @@
/*
-* Copyright (c) 2014, 2016-2017, The Linux Foundation. All rights reserved.
+* Copyright (c) 2014, 2016-2018, 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:
@@ -149,6 +149,10 @@
kFormatYCbCr420P010Ubwc, //!< UBWC aligned YCbCr420P010 format.
kFormatYCbCr420P010Venus, //!< Venus aligned YCbCr420P010 format.
+ //!
+ kFormatYCbCr420SPVenusTile, //!< Tiled & uncompressed YCbCr420SemiPlanarVenus format
+ kFormatYCbCr420TP10Tile, //!< Tiled & uncompressed YCbCr420TP10 format.
+ kFormatYCbCr420P010Tile, //!< Tiled & uncompressed YCbCr420P010 format.
/* All YUV-Packed formats, Any new format will be added towards end of this group to maintain
backward compatibility.
@@ -278,6 +282,10 @@
UbwcCrStatsVector ubwc_crstats[NUM_UBWC_CR_STATS_LAYERS] = {};
//! < UBWC Compression ratio,stats. Stored as a vector of pair of
//! of (tile size, #of tiles)
+ LayerBuffer() {
+ color_metadata.colorPrimaries = ColorPrimaries_BT709_5;
+ color_metadata.transfer = Transfer_sRGB;
+ }
};
// This enum represents buffer layout types.
diff --git a/sdm/include/core/layer_stack.h b/sdm/include/core/layer_stack.h
index 867bc05..afa120e 100644
--- a/sdm/include/core/layer_stack.h
+++ b/sdm/include/core/layer_stack.h
@@ -1,5 +1,5 @@
/*
-* Copyright (c) 2014 - 2017, The Linux Foundation. All rights reserved.
+* Copyright (c) 2014 - 2018, 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:
@@ -35,6 +35,7 @@
#include <utils/constants.h>
#include <vector>
+#include <utility>
#include "layer_buffer.h"
#include "sdm_types.h"
@@ -190,6 +191,8 @@
uint32_t tone_map : 1; //!< This flag will be set by SDM when the layer needs tone map
uint32_t secure: 1; //!< This flag will be set by SDM when the layer must be secure
uint32_t flip_buffer: 1; //!< This flag will be set by SDM when the layer needs FBT flip
+ uint32_t dest_tone_map : 1; //!< This flag will be set by SDM when the layer needs
+ //!< destination tone map
};
uint32_t request_flags = 0; //!< For initialization purpose only.
//!< Shall not be refered directly.
@@ -377,12 +380,28 @@
LayerSolidFill solid_fill_info = {}; //!< solid fill info along with depth.
};
+/*! @brief This structure defines the color space + transfer of a given layer.
+
+ @sa PrimariesTransfer
+*/
+
+struct PrimariesTransfer {
+ ColorPrimaries primaries = ColorPrimaries_BT709_5;
+ GammaTransfer transfer = Transfer_sRGB;
+
+ bool operator==(const PrimariesTransfer& blend_cs) const {
+ return ((primaries == blend_cs.primaries) && (transfer == blend_cs.transfer));
+ }
+};
+
+
/*! @brief This structure defines a layer stack that contains layers which need to be composed and
rendered onto the target.
@sa DisplayInterface::Prepare
@sa DisplayInterface::Commit
*/
+
struct LayerStack {
std::vector<Layer *> layers = {}; //!< Vector of layer pointers.
@@ -400,7 +419,8 @@
LayerStackFlags flags; //!< Flags associated with this layer set.
- ColorPrimaries blend_cs = ColorPrimaries_BT709_5; //!< o/p - Blending color space updated by SDM
+
+ PrimariesTransfer blend_cs = {}; //!< o/p - Blending color space of the frame, updated by SDM
};
} // namespace sdm
diff --git a/sdm/include/private/hw_info_types.h b/sdm/include/private/hw_info_types.h
index 52bc73e..bd598e0 100644
--- a/sdm/include/private/hw_info_types.h
+++ b/sdm/include/private/hw_info_types.h
@@ -176,6 +176,13 @@
enum SmartDMARevision {
V1,
V2,
+ V2p5
+};
+
+enum InlineRotationVersion {
+ kInlineRotationNone,
+ kInlineRotationV1,
+ kInlineRotationV1p1,
};
struct HWResourceInfo {
@@ -198,6 +205,7 @@
uint64_t max_bandwidth_high = 0;
uint32_t max_mixer_width = 2048;
uint32_t max_pipe_width = 2048;
+ uint32_t max_scaler_pipe_width = 2560;
uint32_t max_cursor_size = 0;
uint64_t max_pipe_bw = 0;
uint32_t max_sde_clk = 0;
@@ -220,6 +228,7 @@
bool has_qseed3 = false;
bool has_concurrent_writeback = false;
bool has_ppp = false;
+ bool has_excl_rect = false;
uint32_t writeback_index = kHWBlockMax;
HWDynBwLimitInfo dyn_bw_info;
std::vector<HWPipeCaps> hw_pipes;
@@ -236,6 +245,7 @@
uint32_t cache_size = 0; // cache size in bytes
HWQseedStepVersion pipe_qseed3_version = kQseed3v2; // only valid when has_qseed3=true
uint32_t min_prefill_lines = 0;
+ InlineRotationVersion inrot_version = kInlineRotationNone;
void Reset() { *this = HWResourceInfo(); }
};
@@ -486,6 +496,7 @@
HWSubBlockType sub_block_type = kHWSubBlockMax;
LayerRect src_roi;
LayerRect dst_roi;
+ LayerRect excl_rect; // exclusion rectangle per pipe rectangle
uint8_t horizontal_decimation = 0;
uint8_t vertical_decimation = 0;
HWScaleData scale_data;
@@ -528,12 +539,18 @@
HDROperation operation = kNoOp;
};
+struct LayerExt {
+ std::vector<LayerRect> excl_rects = {}; // list of exclusion rects
+};
+
struct HWLayersInfo {
LayerStack *stack = NULL; // Input layer stack. Set by the caller.
uint32_t app_layer_count = 0; // Total number of app layers. Must not be 0.
uint32_t gpu_target_index = 0; // GPU target layer index. 0 if not present.
std::vector<Layer> hw_layers = {}; // Layers which need to be programmed on the HW
+ std::vector<LayerExt> layer_exts = {}; // Extention layer having list of
+ // exclusion rectangles for each layer
std::vector<uint32_t> index; // Indexes of the layers from the layer stack which need to
// be programmed on hardware.
@@ -560,6 +577,7 @@
uint64_t llcc_ib_bps = 0;
uint64_t dram_ab_bps = 0;
uint64_t dram_ib_bps = 0;
+ uint64_t rot_prefill_bw_bps = 0;
uint32_t clock_hz = 0;
uint32_t rot_clock_hz = 0;
};
diff --git a/sdm/include/utils/formats.h b/sdm/include/utils/formats.h
index 2d43850..f5a7a25 100644
--- a/sdm/include/utils/formats.h
+++ b/sdm/include/utils/formats.h
@@ -1,5 +1,5 @@
/*
-* Copyright (c) 2016 - 2017, The Linux Foundation. All rights reserved.
+* Copyright (c) 2016 - 2018, 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
@@ -56,6 +56,7 @@
BufferLayout GetBufferLayout(LayerBufferFormat format);
DisplayError GetBufferFormatTileSize(LayerBufferFormat format, FormatTileSize *tile_size);
float GetBufferFormatBpp(LayerBufferFormat format);
+bool HasAlphaChannel(LayerBufferFormat format);
} // namespace sdm
diff --git a/sdm/include/utils/rect.h b/sdm/include/utils/rect.h
index b25f76e..c3fd492 100644
--- a/sdm/include/utils/rect.h
+++ b/sdm/include/utils/rect.h
@@ -1,5 +1,5 @@
/*
-* Copyright (c) 2015-2017, The Linux Foundation. All rights reserved.
+* Copyright (c) 2015-2018, 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
@@ -51,6 +51,8 @@
LayerRect Union(const LayerRect &rect1, const LayerRect &rect2);
LayerRect Intersection(const LayerRect &rect1, const LayerRect &rect2);
LayerRect Subtract(const LayerRect &rect1, const LayerRect &rect2);
+ void Subtract(const LayerRect &rect1, const LayerRect &rect2, LayerRect *res);
+ bool Contains(const LayerRect &rect1, const LayerRect &rect2);
LayerRect Reposition(const LayerRect &rect1, const int &x_offset, const int &y_offset);
void SplitLeftRight(const LayerRect &in_rect, uint32_t split_count, uint32_t align_x,
bool flip_horizontal, LayerRect *out_rects);
diff --git a/sdm/libs/core/display_base.cpp b/sdm/libs/core/display_base.cpp
index 383bdba..18241d9 100644
--- a/sdm/libs/core/display_base.cpp
+++ b/sdm/libs/core/display_base.cpp
@@ -1,5 +1,5 @@
/*
-* Copyright (c) 2014 - 2017, The Linux Foundation. All rights reserved.
+* Copyright (c) 2014 - 2018, 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:
@@ -430,7 +430,7 @@
return last_power_mode_;
}
-DisplayError DisplayBase::SetDisplayState(DisplayState state) {
+DisplayError DisplayBase::SetDisplayState(DisplayState state, int *release_fence) {
lock_guard<recursive_mutex> obj(recursive_mutex_);
DisplayError error = kErrorNone;
bool active = false;
@@ -452,7 +452,7 @@
break;
case kStateOn:
- error = hw_intf_->PowerOn();
+ error = hw_intf_->PowerOn(release_fence);
if (error != kErrorNone) {
return error;
}
@@ -468,13 +468,13 @@
break;
case kStateDoze:
- error = hw_intf_->Doze();
+ error = hw_intf_->Doze(release_fence);
active = true;
last_power_mode_ = kStateDoze;
break;
case kStateDozeSuspend:
- error = hw_intf_->DozeSuspend();
+ error = hw_intf_->DozeSuspend(release_fence);
if (display_type_ != kPrimary) {
active = true;
}
@@ -1525,7 +1525,7 @@
// HDR color mode is set when hdr layer is present in layer_stack.
// If client flags HDR layer as skipped, then blending happens
// in SDR color space. Hence, need to restore the SDR color mode.
- if (layer_stack->blend_cs != ColorPrimaries_BT2020) {
+ if (layer_stack->blend_cs.primaries != ColorPrimaries_BT2020) {
error = SetHDRMode(false);
if (error != kErrorNone) {
DLOGW("Failed to restore SDR mode");
diff --git a/sdm/libs/core/display_base.h b/sdm/libs/core/display_base.h
index 014ea11..bd597c9 100644
--- a/sdm/libs/core/display_base.h
+++ b/sdm/libs/core/display_base.h
@@ -1,5 +1,5 @@
/*
-* Copyright (c) 2014-2017, The Linux Foundation. All rights reserved.
+* Copyright (c) 2014-2018, 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:
@@ -62,7 +62,7 @@
virtual DisplayError GetConfig(DisplayConfigFixedInfo *variable_info);
virtual DisplayError GetActiveConfig(uint32_t *index);
virtual DisplayError GetVSyncState(bool *enabled);
- virtual DisplayError SetDisplayState(DisplayState state);
+ virtual DisplayError SetDisplayState(DisplayState state, int *release_fence);
virtual DisplayError SetActiveConfig(uint32_t index);
virtual DisplayError SetActiveConfig(DisplayConfigVariableInfo *variable_info) {
return kErrorNotSupported;
diff --git a/sdm/libs/core/display_hdmi.cpp b/sdm/libs/core/display_hdmi.cpp
index 1f1a051..2076fe5 100644
--- a/sdm/libs/core/display_hdmi.cpp
+++ b/sdm/libs/core/display_hdmi.cpp
@@ -170,7 +170,6 @@
uint32_t DisplayHDMI::GetBestConfig(HWS3DMode s3d_mode) {
uint32_t best_index = 0, index;
uint32_t num_modes = 0;
- HWDisplayAttributes best_attrib;
hw_intf_->GetNumDisplayAttributes(&num_modes);
diff --git a/sdm/libs/core/display_primary.cpp b/sdm/libs/core/display_primary.cpp
index 8466f8b..d9fef33 100644
--- a/sdm/libs/core/display_primary.cpp
+++ b/sdm/libs/core/display_primary.cpp
@@ -1,5 +1,5 @@
/*
-* Copyright (c) 2014 - 2017, The Linux Foundation. All rights reserved.
+* Copyright (c) 2014 - 2018, 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:
@@ -166,10 +166,10 @@
return error;
}
-DisplayError DisplayPrimary::SetDisplayState(DisplayState state) {
+DisplayError DisplayPrimary::SetDisplayState(DisplayState state, int *release_fence) {
lock_guard<recursive_mutex> obj(recursive_mutex_);
DisplayError error = kErrorNone;
- error = DisplayBase::SetDisplayState(state);
+ error = DisplayBase::SetDisplayState(state, release_fence);
if (error != kErrorNone) {
return error;
}
@@ -391,19 +391,26 @@
void DisplayPrimary::ResetPanel() {
DisplayError status = kErrorNone;
+ int release_fence = -1;
DLOGI("Powering off primary");
- status = SetDisplayState(kStateOff);
+ status = SetDisplayState(kStateOff, &release_fence);
if (status != kErrorNone) {
DLOGE("power-off on primary failed with error = %d", status);
}
+ if (release_fence >= 0) {
+ ::close(release_fence);
+ }
DLOGI("Restoring power mode on primary");
DisplayState mode = GetLastPowerMode();
- status = SetDisplayState(mode);
+ status = SetDisplayState(mode, &release_fence);
if (status != kErrorNone) {
DLOGE("Setting power mode = %d on primary failed with error = %d", mode, status);
}
+ if (release_fence >= 0) {
+ ::close(release_fence);
+ }
DLOGI("Enabling HWVsync");
status = SetVSyncState(true);
diff --git a/sdm/libs/core/display_primary.h b/sdm/libs/core/display_primary.h
index a4dd4b8..e14c6d7 100644
--- a/sdm/libs/core/display_primary.h
+++ b/sdm/libs/core/display_primary.h
@@ -1,5 +1,5 @@
/*
-* Copyright (c) 2014 - 2017, The Linux Foundation. All rights reserved.
+* Copyright (c) 2014 - 2018, 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:
@@ -44,7 +44,7 @@
virtual DisplayError Commit(LayerStack *layer_stack);
virtual DisplayError ControlPartialUpdate(bool enable, uint32_t *pending);
virtual DisplayError DisablePartialUpdateOneFrame();
- virtual DisplayError SetDisplayState(DisplayState state);
+ virtual DisplayError SetDisplayState(DisplayState state, int *release_fence);
virtual void SetIdleTimeoutMs(uint32_t active_ms);
virtual DisplayError SetDisplayMode(uint32_t mode);
virtual DisplayError GetRefreshRateRange(uint32_t *min_refresh_rate, uint32_t *max_refresh_rate);
diff --git a/sdm/libs/core/drm/hw_device_drm.cpp b/sdm/libs/core/drm/hw_device_drm.cpp
index c734f4c..91f89a2 100644
--- a/sdm/libs/core/drm/hw_device_drm.cpp
+++ b/sdm/libs/core/drm/hw_device_drm.cpp
@@ -1,5 +1,5 @@
/*
-* Copyright (c) 2017, The Linux Foundation. All rights reserved.
+* Copyright (c) 2017-2018, 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
@@ -186,6 +186,10 @@
*drm_format = DRM_FORMAT_NV12;
*drm_format_modifier = DRM_FORMAT_MOD_QCOM_COMPRESSED;
break;
+ case kFormatYCbCr420SPVenusTile:
+ *drm_format = DRM_FORMAT_NV12;
+ *drm_format_modifier = DRM_FORMAT_MOD_QCOM_TILE;
+ break;
case kFormatYCrCb420SemiPlanar:
*drm_format = DRM_FORMAT_NV21;
break;
@@ -202,11 +206,21 @@
*drm_format_modifier = DRM_FORMAT_MOD_QCOM_COMPRESSED |
DRM_FORMAT_MOD_QCOM_DX;
break;
+ case kFormatYCbCr420P010Tile:
+ *drm_format = DRM_FORMAT_NV12;
+ *drm_format_modifier = DRM_FORMAT_MOD_QCOM_TILE |
+ DRM_FORMAT_MOD_QCOM_DX;
+ break;
case kFormatYCbCr420TP10Ubwc:
*drm_format = DRM_FORMAT_NV12;
*drm_format_modifier = DRM_FORMAT_MOD_QCOM_COMPRESSED |
DRM_FORMAT_MOD_QCOM_DX | DRM_FORMAT_MOD_QCOM_TIGHT;
break;
+ case kFormatYCbCr420TP10Tile:
+ *drm_format = DRM_FORMAT_NV12;
+ *drm_format_modifier = DRM_FORMAT_MOD_QCOM_TILE |
+ DRM_FORMAT_MOD_QCOM_DX | DRM_FORMAT_MOD_QCOM_TIGHT;
+ break;
case kFormatYCbCr422H2V1SemiPlanar:
*drm_format = DRM_FORMAT_NV16;
break;
@@ -257,6 +271,11 @@
}
MapBufferToFbId(input_buffer);
+
+ if (hw_rotator_session->mode == kRotatorInline && hw_rotate_info->valid &&
+ hw_rotator_session->output_buffer.planes[0].fd >= 0) {
+ MapBufferToFbId(&hw_rotator_session->output_buffer);
+ }
}
}
@@ -708,7 +727,7 @@
return kErrorNone;
}
-DisplayError HWDeviceDRM::PowerOn() {
+DisplayError HWDeviceDRM::PowerOn(int *release_fence) {
DTRACE_SCOPED();
if (!drm_atomic_intf_) {
DLOGE("DRM Atomic Interface is null!");
@@ -726,6 +745,7 @@
DLOGE("Failed with error: %d", ret);
return kErrorHardware;
}
+ drm_atomic_intf_->Perform(DRMOps::CRTC_GET_RELEASE_FENCE, token_.crtc_id, release_fence);
return kErrorNone;
}
@@ -748,7 +768,7 @@
return kErrorNone;
}
-DisplayError HWDeviceDRM::Doze() {
+DisplayError HWDeviceDRM::Doze(int *release_fence) {
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::DOZE);
@@ -758,10 +778,12 @@
return kErrorHardware;
}
+ drm_atomic_intf_->Perform(DRMOps::CRTC_GET_RELEASE_FENCE, token_.crtc_id, release_fence);
+
return kErrorNone;
}
-DisplayError HWDeviceDRM::DozeSuspend() {
+DisplayError HWDeviceDRM::DozeSuspend(int *release_fence) {
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,
@@ -772,6 +794,8 @@
return kErrorHardware;
}
+ drm_atomic_intf_->Perform(DRMOps::CRTC_GET_RELEASE_FENCE, token_.crtc_id, release_fence);
+
return kErrorNone;
}
@@ -859,11 +883,19 @@
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);
+ if (hw_rotator_session->output_buffer.planes[0].fd >= 0) {
+ uint32_t rot_fb_id = registry_.GetFbId(hw_rotator_session->output_buffer.planes[0].fd);
+ if (rot_fb_id) {
+ drm_atomic_intf_->Perform(DRMOps::PLANE_SET_ROT_FB_ID, pipe_id, rot_fb_id);
+ }
+ }
}
DRMRect dst = {};
SetRect(pipe_info->dst_roi, &dst);
drm_atomic_intf_->Perform(DRMOps::PLANE_SET_DST_RECT, pipe_id, dst);
-
+ DRMRect excl = {};
+ SetRect(pipe_info->excl_rect, &excl);
+ drm_atomic_intf_->Perform(DRMOps::PLANE_SET_EXCL_RECT, pipe_id, excl);
uint32_t rot_bit_mask = 0;
SetRotation(layer.transform, hw_rotator_session->mode, &rot_bit_mask);
drm_atomic_intf_->Perform(DRMOps::PLANE_SET_ROTATION, pipe_id, rot_bit_mask);
@@ -918,14 +950,17 @@
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_PREFILL_BW, token_.crtc_id,
+ qos_data.rot_prefill_bw_bps);
drm_atomic_intf_->Perform(DRMOps::CRTC_SET_ROT_CLK, token_.crtc_id, qos_data.rot_clock_hz);
drm_atomic_intf_->Perform(DRMOps::CRTC_SET_SECURITY_LEVEL, token_.crtc_id, crtc_security_level);
- 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",
+ DLOGI_IF(kTagDriverConfig, "%s::%s 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: Bw=%llu Bps, Clock=%d Hz", validate ? "Validate" : "Commit", device_name_,
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);
+ qos_data.rot_prefill_bw_bps, qos_data.rot_clock_hz);
// Set refresh rate
if (vrefresh_) {
@@ -1248,8 +1283,8 @@
info.id = HWColorManagerDrm::ToDrmFeatureId(i);
if (info.id >= sde_drm::kPPFeaturesMax)
continue;
- // use crtc_id_ = 0 since PP features are same across all CRTCs
- drm_mgr_intf_->GetCrtcPPInfo(0, &info);
+
+ drm_mgr_intf_->GetCrtcPPInfo(token_.crtc_id, &info);
vers->version[i] = HWColorManagerDrm::GetFeatureVersion(info);
}
return kErrorNone;
diff --git a/sdm/libs/core/drm/hw_device_drm.h b/sdm/libs/core/drm/hw_device_drm.h
index b08c0e6..3ecc9a0 100644
--- a/sdm/libs/core/drm/hw_device_drm.h
+++ b/sdm/libs/core/drm/hw_device_drm.h
@@ -1,5 +1,5 @@
/*
-* Copyright (c) 2017, The Linux Foundation. All rights reserved.
+* Copyright (c) 2017-2018, 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
@@ -67,10 +67,10 @@
virtual DisplayError SetDisplayAttributes(uint32_t index);
virtual DisplayError SetDisplayAttributes(const HWDisplayAttributes &display_attributes);
virtual DisplayError GetConfigIndex(char *mode, uint32_t *index);
- virtual DisplayError PowerOn();
+ virtual DisplayError PowerOn(int *release_fence);
virtual DisplayError PowerOff();
- virtual DisplayError Doze();
- virtual DisplayError DozeSuspend();
+ virtual DisplayError Doze(int *release_fence);
+ virtual DisplayError DozeSuspend(int *release_fence);
virtual DisplayError Standby();
virtual DisplayError Validate(HWLayers *hw_layers);
virtual DisplayError Commit(HWLayers *hw_layers);
diff --git a/sdm/libs/core/drm/hw_info_drm.cpp b/sdm/libs/core/drm/hw_info_drm.cpp
index 5c69ed7..ae3c424 100644
--- a/sdm/libs/core/drm/hw_info_drm.cpp
+++ b/sdm/libs/core/drm/hw_info_drm.cpp
@@ -1,5 +1,5 @@
/*
-* Copyright (c) 2017, The Linux Foundation. All rights reserved.
+* Copyright (c) 2017-2018, 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
@@ -119,6 +119,17 @@
return sdm_version;
}
+static InlineRotationVersion GetInRotVersion(sde_drm::InlineRotationVersion drm_version) {
+ switch (drm_version) {
+ case sde_drm::InlineRotationVersion::V1:
+ return InlineRotationVersion::kInlineRotationV1;
+ case sde_drm::InlineRotationVersion::V1p1:
+ return InlineRotationVersion::kInlineRotationV1p1;
+ default:
+ return kInlineRotationNone;
+ }
+}
+
HWResourceInfo *HWInfoDRM::hw_resource_ = nullptr;
HWInfoDRM::HWInfoDRM() {
@@ -283,8 +294,9 @@
hw_resource->has_qseed3 = (info.qseed_version == sde_drm::QSEEDVersion::V3);
hw_resource->num_blending_stages = info.max_blend_stages;
hw_resource->num_solidfill_stages = info.max_solidfill_stages;
- hw_resource->smart_dma_rev = (info.smart_dma_rev == sde_drm::SmartDMARevision::V2) ?
- SmartDMARevision::V2 : SmartDMARevision::V1;
+ hw_resource->smart_dma_rev = (info.smart_dma_rev == sde_drm::SmartDMARevision::V2p5) ?
+ SmartDMARevision::V2p5 : ((info.smart_dma_rev == sde_drm::SmartDMARevision::V2) ?
+ SmartDMARevision::V2 : SmartDMARevision::V1);
hw_resource->ib_fudge_factor = info.ib_fudge_factor;
hw_resource->hw_dest_scalar_info.prefill_lines = info.dest_scale_prefill_lines;
hw_resource->undersized_prefill_lines = info.undersized_prefill_lines;
@@ -403,17 +415,20 @@
name.c_str(), pipe_obj.first, pipe_obj.second.master_plane_id);
hw_resource->hw_pipes.push_back(std::move(pipe_caps));
}
+ hw_resource->has_excl_rect = planes[0].second.has_excl_rect;
}
void HWInfoDRM::PopulatePipeCaps(const sde_drm::DRMPlaneTypeInfo &info,
HWResourceInfo *hw_resource) {
hw_resource->max_pipe_width = info.max_linewidth;
+ hw_resource->max_scaler_pipe_width = info.max_scaler_linewidth;
hw_resource->max_scale_down = info.max_downscale;
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;
hw_resource->pipe_qseed3_version = GetQseedStepVersion(info.qseed3_version);
+ hw_resource->inrot_version = GetInRotVersion(info.inrot_version);
}
void HWInfoDRM::PopulateSupportedFmts(HWSubBlockType sub_blk_type,
diff --git a/sdm/libs/core/drm/hw_tv_drm.cpp b/sdm/libs/core/drm/hw_tv_drm.cpp
index f1d0d80..a43ac2c 100644
--- a/sdm/libs/core/drm/hw_tv_drm.cpp
+++ b/sdm/libs/core/drm/hw_tv_drm.cpp
@@ -1,5 +1,5 @@
/*
-* Copyright (c) 2017, The Linux Foundation. All rights reserved.
+* Copyright (c) 2017-2018, 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
@@ -164,11 +164,11 @@
return kErrorNone;
}
-DisplayError HWTVDRM::Doze() {
+DisplayError HWTVDRM::Doze(int *release_fence) {
return kErrorNone;
}
-DisplayError HWTVDRM::DozeSuspend() {
+DisplayError HWTVDRM::DozeSuspend(int *release_fence) {
return kErrorNone;
}
diff --git a/sdm/libs/core/drm/hw_tv_drm.h b/sdm/libs/core/drm/hw_tv_drm.h
index 5661bc2..a87f33d 100644
--- a/sdm/libs/core/drm/hw_tv_drm.h
+++ b/sdm/libs/core/drm/hw_tv_drm.h
@@ -1,5 +1,5 @@
/*
-* Copyright (c) 2017, The Linux Foundation. All rights reserved.
+* Copyright (c) 2017-2018, 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:
@@ -43,8 +43,8 @@
virtual DisplayError SetDisplayAttributes(uint32_t index);
virtual DisplayError GetConfigIndex(char *mode, uint32_t *index);
virtual DisplayError PowerOff();
- virtual DisplayError Doze();
- virtual DisplayError DozeSuspend();
+ virtual DisplayError Doze(int *release_fence);
+ virtual DisplayError DozeSuspend(int *release_fence);
virtual DisplayError Standby();
virtual DisplayError Commit(HWLayers *hw_layers);
virtual void PopulateHWPanelInfo();
diff --git a/sdm/libs/core/fb/hw_device.cpp b/sdm/libs/core/fb/hw_device.cpp
index 2c529ae..8dddc51 100644
--- a/sdm/libs/core/fb/hw_device.cpp
+++ b/sdm/libs/core/fb/hw_device.cpp
@@ -1,5 +1,5 @@
/*
-* Copyright (c) 2014 - 2017, The Linux Foundation. All rights reserved.
+* Copyright (c) 2014 - 2018, 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
@@ -62,6 +62,13 @@
namespace sdm {
+#ifndef MDP_CSC_ITU_R_2020
+#define MDP_CSC_ITU_R_2020 (MDP_CSC_ITU_R_709 + 1)
+#endif
+#ifndef MDP_CSC_ITU_R_2020_FR
+#define MDP_CSC_ITU_R_2020_FR (MDP_CSC_ITU_R_2020 + 1)
+#endif
+
HWDevice::HWDevice(BufferSyncHandler *buffer_sync_handler)
: fb_node_index_(-1), fb_path_("/sys/devices/virtual/graphics/fb"),
buffer_sync_handler_(buffer_sync_handler), synchronous_commit_(false) {
@@ -155,7 +162,7 @@
return kErrorNone;
}
-DisplayError HWDevice::PowerOn() {
+DisplayError HWDevice::PowerOn(int *release_fence) {
DTRACE_SCOPED();
if (Sys::ioctl_(device_fd_, FBIOBLANK, FB_BLANK_UNBLANK) < 0) {
@@ -174,11 +181,11 @@
return kErrorNone;
}
-DisplayError HWDevice::Doze() {
+DisplayError HWDevice::Doze(int *release_fence) {
return kErrorNone;
}
-DisplayError HWDevice::DozeSuspend() {
+DisplayError HWDevice::DozeSuspend(int *release_fence) {
return kErrorNone;
}
@@ -1100,12 +1107,10 @@
case ColorPrimaries_BT709_5:
*color_space = MDP_CSC_ITU_R_709;
break;
-#if defined MDP_CSC_ITU_R_2020 && defined MDP_CSC_ITU_R_2020_FR
case ColorPrimaries_BT2020:
*color_space = static_cast<mdp_color_space>((color_metadata.range == Range_Full) ?
MDP_CSC_ITU_R_2020_FR : MDP_CSC_ITU_R_2020);
break;
-#endif
default:
break;
}
diff --git a/sdm/libs/core/fb/hw_device.h b/sdm/libs/core/fb/hw_device.h
index f32c5bd..353cce5 100644
--- a/sdm/libs/core/fb/hw_device.h
+++ b/sdm/libs/core/fb/hw_device.h
@@ -1,5 +1,5 @@
/*
-* Copyright (c) 2014 - 2017, The Linux Foundation. All rights reserved.
+* Copyright (c) 2014 - 2018, The Linux Foundation. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification, are permitted
* provided that the following conditions are met:
@@ -70,10 +70,10 @@
virtual DisplayError SetDisplayAttributes(uint32_t index);
virtual DisplayError SetDisplayAttributes(const HWDisplayAttributes &display_attributes);
virtual DisplayError GetConfigIndex(char *mode, uint32_t *index);
- virtual DisplayError PowerOn();
+ virtual DisplayError PowerOn(int *release_fence);
virtual DisplayError PowerOff();
- virtual DisplayError Doze();
- virtual DisplayError DozeSuspend();
+ virtual DisplayError Doze(int *release_fence);
+ virtual DisplayError DozeSuspend(int *release_fence);
virtual DisplayError Standby();
virtual DisplayError Validate(HWLayers *hw_layers);
virtual DisplayError Commit(HWLayers *hw_layers);
diff --git a/sdm/libs/core/fb/hw_primary.cpp b/sdm/libs/core/fb/hw_primary.cpp
index 5ee8121..3f3c28e 100644
--- a/sdm/libs/core/fb/hw_primary.cpp
+++ b/sdm/libs/core/fb/hw_primary.cpp
@@ -1,5 +1,5 @@
/*
-* Copyright (c) 2015 - 2017, The Linux Foundation. All rights reserved.
+* Copyright (c) 2015 - 2018, 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
@@ -344,7 +344,7 @@
return kErrorNone;
}
-DisplayError HWPrimary::Doze() {
+DisplayError HWPrimary::Doze(int *release_fence) {
if (Sys::ioctl_(device_fd_, FBIOBLANK, FB_BLANK_NORMAL) < 0) {
IOCTL_LOGE(FB_BLANK_NORMAL, device_type_);
return kErrorHardware;
@@ -353,7 +353,7 @@
return kErrorNone;
}
-DisplayError HWPrimary::DozeSuspend() {
+DisplayError HWPrimary::DozeSuspend(int *release_fence) {
if (Sys::ioctl_(device_fd_, FBIOBLANK, FB_BLANK_VSYNC_SUSPEND) < 0) {
IOCTL_LOGE(FB_BLANK_VSYNC_SUSPEND, device_type_);
return kErrorHardware;
diff --git a/sdm/libs/core/fb/hw_primary.h b/sdm/libs/core/fb/hw_primary.h
index 69b5445..c6ca5a9 100644
--- a/sdm/libs/core/fb/hw_primary.h
+++ b/sdm/libs/core/fb/hw_primary.h
@@ -1,5 +1,5 @@
/*
-* Copyright (c) 2015-2016, The Linux Foundation. All rights reserved.
+* Copyright (c) 2015-2016, 2018 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:
@@ -46,8 +46,8 @@
virtual DisplayError SetDisplayAttributes(uint32_t index);
virtual DisplayError GetConfigIndex(char *mode, uint32_t *index);
virtual DisplayError PowerOff();
- virtual DisplayError Doze();
- virtual DisplayError DozeSuspend();
+ virtual DisplayError Doze(int *release_fence);
+ virtual DisplayError DozeSuspend(int *release_fence);
virtual DisplayError Validate(HWLayers *hw_layers);
virtual DisplayError Commit(HWLayers *hw_layers);
virtual void SetIdleTimeoutMs(uint32_t timeout_ms);
diff --git a/sdm/libs/core/hw_interface.h b/sdm/libs/core/hw_interface.h
index 9bb825e..483a4df 100644
--- a/sdm/libs/core/hw_interface.h
+++ b/sdm/libs/core/hw_interface.h
@@ -1,5 +1,5 @@
/*
-* Copyright (c) 2014 - 2017, The Linux Foundation. All rights reserved.
+* Copyright (c) 2014 - 2018, 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:
@@ -85,10 +85,10 @@
virtual DisplayError SetDisplayAttributes(uint32_t index) = 0;
virtual DisplayError SetDisplayAttributes(const HWDisplayAttributes &display_attributes) = 0;
virtual DisplayError GetConfigIndex(char *mode, uint32_t *index) = 0;
- virtual DisplayError PowerOn() = 0;
+ virtual DisplayError PowerOn(int *release_fence) = 0;
virtual DisplayError PowerOff() = 0;
- virtual DisplayError Doze() = 0;
- virtual DisplayError DozeSuspend() = 0;
+ virtual DisplayError Doze(int *release_fence) = 0;
+ virtual DisplayError DozeSuspend(int *release_fence) = 0;
virtual DisplayError Standby() = 0;
virtual DisplayError Validate(HWLayers *hw_layers) = 0;
virtual DisplayError Commit(HWLayers *hw_layers) = 0;
diff --git a/sdm/libs/core/resource_default.cpp b/sdm/libs/core/resource_default.cpp
index f8909f4..cce2cec 100644
--- a/sdm/libs/core/resource_default.cpp
+++ b/sdm/libs/core/resource_default.cpp
@@ -1,5 +1,5 @@
/*
-* Copyright (c) 2014 - 2016, The Linux Foundation. All rights reserved.
+* Copyright (c) 2014-2016, 2018, 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:
@@ -465,11 +465,16 @@
HWLayerConfig *layer_config) {
HWPipeInfo *left_pipe = &layer_config->left_pipe;
HWPipeInfo *right_pipe = &layer_config->right_pipe;
- float src_width = src_rect.right - src_rect.left;
- float dst_width = dst_rect.right - dst_rect.left;
+ uint32_t max_pipe_width = hw_res_info_.max_pipe_width;
+ uint32_t src_width = (uint32_t)(src_rect.right - src_rect.left);
+ uint32_t dst_width = (uint32_t)(dst_rect.right - dst_rect.left);
+
+ if (src_width != dst_width) {
+ max_pipe_width = hw_res_info_.max_scaler_pipe_width;
+ }
// Layer cannot qualify for SrcSplit if source or destination width exceeds max pipe width.
- if ((src_width > hw_res_info_.max_pipe_width) || (dst_width > hw_res_info_.max_pipe_width)) {
+ if ((src_width > max_pipe_width) || (dst_width > max_pipe_width)) {
SplitRect(src_rect, dst_rect, &left_pipe->src_roi, &left_pipe->dst_roi, &right_pipe->src_roi,
&right_pipe->dst_roi);
left_pipe->valid = true;
diff --git a/sdm/libs/hwc2/Android.mk b/sdm/libs/hwc2/Android.mk
index bd33aff..79f32e2 100644
--- a/sdm/libs/hwc2/Android.mk
+++ b/sdm/libs/hwc2/Android.mk
@@ -9,6 +9,7 @@
LOCAL_MODULE_RELATIVE_PATH := hw
LOCAL_MODULE_TAGS := optional
LOCAL_C_INCLUDES := $(common_includes)
+LOCAL_C_INCLUDES += $(kernel_includes)
LOCAL_HEADER_LIBRARIES := display_headers
LOCAL_CFLAGS := -Wno-missing-field-initializers -Wno-unused-parameter \
diff --git a/sdm/libs/hwc2/display_null.cpp b/sdm/libs/hwc2/display_null.cpp
index 16f4da6..99cd017 100644
--- a/sdm/libs/hwc2/display_null.cpp
+++ b/sdm/libs/hwc2/display_null.cpp
@@ -1,5 +1,5 @@
/*
-* Copyright (c) 2017, The Linux Foundation. All rights reserved.
+* Copyright (c) 2017-2018, 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
@@ -33,7 +33,100 @@
namespace sdm {
-DisplayError DisplayNull::Commit(LayerStack *layer_stack) {
+DisplayError DisplayNull::Init() {
+ default_variable_config_.vsync_period_ns = 16600000;
+ default_variable_config_.x_pixels = 1080;
+ default_variable_config_.y_pixels = 1920;
+ default_variable_config_.x_dpi = 300;
+ default_variable_config_.y_dpi = 300;
+ default_variable_config_.fps = 60;
+ default_variable_config_.is_yuv = false;
+
+ return kErrorNone;
+}
+
+DisplayError DisplayNull::GetMixerResolution(uint32_t *width, uint32_t *height) {
+ if (!width || !height) {
+ return kErrorParameters;
+ }
+
+ *width = default_variable_config_.x_pixels;
+ *height = default_variable_config_.y_pixels;
+ return kErrorNone;
+}
+
+DisplayError DisplayNull::GetFrameBufferConfig(DisplayConfigVariableInfo *variable_info) {
+ if (!variable_info) {
+ return kErrorParameters;
+ }
+
+ *variable_info = default_variable_config_;
+ return kErrorNone;
+}
+
+DisplayError DisplayNull::GetConfig(uint32_t index, DisplayConfigVariableInfo *disp_attr) {
+ if (!disp_attr) {
+ return kErrorParameters;
+ }
+
+ *disp_attr = default_variable_config_;
+ return kErrorNone;
+}
+
+DisplayError DisplayNull::GetConfig(DisplayConfigFixedInfo *fixed_info) {
+ if (!fixed_info) {
+ return kErrorParameters;
+ }
+
+ *fixed_info = default_fixed_config_;
+ return kErrorNone;
+}
+
+DisplayError DisplayNull::GetRefreshRateRange(uint32_t *min_refresh_rate,
+ uint32_t *max_refresh_rate) {
+ if (!min_refresh_rate || !max_refresh_rate) {
+ return kErrorParameters;
+ }
+
+ *min_refresh_rate = 60;
+ *max_refresh_rate = 60;
+ return kErrorNone;
+}
+
+DisplayError DisplayNull::GetActiveConfig(uint32_t *config) {
+ if (!config) {
+ return kErrorParameters;
+ }
+
+ *config = 0;
+ return kErrorNone;
+}
+
+DisplayError DisplayNull::GetNumVariableInfoConfigs(uint32_t *count) {
+ if (!count) {
+ return kErrorParameters;
+ }
+
+ *count = 1;
+ return kErrorNone;
+}
+
+DisplayError DisplayNull::Prepare(LayerStack *layer_stack) {
+ if (!layer_stack) {
+ return kErrorParameters;
+ }
+
+ for (auto layer : layer_stack->layers) {
+ layer->composition = kCompositionGPU;
+ }
+ return kErrorNone;
+}
+
+DisplayError DisplayNullExternal::Commit(LayerStack *layer_stack) {
+ if (!layer_stack) {
+ return kErrorParameters;
+ }
+
for (Layer *layer : layer_stack->layers) {
if (layer->composition != kCompositionGPUTarget) {
layer->composition = kCompositionSDE;
@@ -41,26 +134,34 @@
}
}
layer_stack->retire_fence_fd = -1;
-
return kErrorNone;
}
-DisplayError DisplayNull::GetDisplayState(DisplayState *state) {
+DisplayError DisplayNullExternal::GetDisplayState(DisplayState *state) {
+ if (!state) {
+ return kErrorParameters;
+ }
+
*state = state_;
return kErrorNone;
}
-DisplayError DisplayNull::SetDisplayState(DisplayState state) {
+DisplayError DisplayNullExternal::SetDisplayState(DisplayState state, int *release_fence) {
state_ = state;
return kErrorNone;
}
-DisplayError DisplayNull::SetFrameBufferConfig(const DisplayConfigVariableInfo &variable_info) {
+DisplayError DisplayNullExternal::SetFrameBufferConfig(const DisplayConfigVariableInfo
+ &variable_info) {
fb_config_ = variable_info;
return kErrorNone;
}
-DisplayError DisplayNull::GetFrameBufferConfig(DisplayConfigVariableInfo *variable_info) {
+DisplayError DisplayNullExternal::GetFrameBufferConfig(DisplayConfigVariableInfo *variable_info) {
+ if (!variable_info) {
+ return kErrorParameters;
+ }
+
*variable_info = fb_config_;
return kErrorNone;
}
diff --git a/sdm/libs/hwc2/display_null.h b/sdm/libs/hwc2/display_null.h
index f6c0dda..01f5909 100644
--- a/sdm/libs/hwc2/display_null.h
+++ b/sdm/libs/hwc2/display_null.h
@@ -1,5 +1,5 @@
/*
-* Copyright (c) 2017, The Linux Foundation. All rights reserved.
+* Copyright (c) 2017-2018, 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
@@ -36,35 +36,32 @@
namespace sdm {
-#define MAKE_NO_OP(virtual_method_name) \
- virtual DisplayError virtual_method_name { return kErrorNone; }
+#define MAKE_NO_OP(virtual_method_signature) \
+ virtual DisplayError virtual_method_signature { 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 Init();
+ virtual DisplayError GetMixerResolution(uint32_t *width, uint32_t *height);
+
virtual DisplayError GetFrameBufferConfig(DisplayConfigVariableInfo *variable_info);
+ virtual DisplayError GetConfig(uint32_t index, DisplayConfigVariableInfo *disp_attr);
+ virtual DisplayError GetConfig(DisplayConfigFixedInfo *fixed_info);
+ virtual DisplayError GetRefreshRateRange(uint32_t *min_refresh_rate, uint32_t *max_refresh_rate);
+ virtual DisplayError GetActiveConfig(uint32_t *config);
+ virtual DisplayError GetNumVariableInfoConfigs(uint32_t *count);
+ virtual DisplayError Prepare(LayerStack *layer_stack);
+ virtual bool IsPrimaryDisplay() { return true; }
virtual bool IsUnderscanSupported() { return true; }
virtual void SetIdleTimeoutMs(uint32_t active_ms) { }
- virtual bool IsPrimaryDisplay() { return true; }
+ virtual std::string Dump() { return ""; }
- void SetActive(bool active) {
- active_ = active;
- }
-
- bool IsActive() {
- return active_;
- }
-
- MAKE_NO_OP(Prepare(LayerStack *))
+ MAKE_NO_OP(Commit(LayerStack *))
+ MAKE_NO_OP(GetDisplayState(DisplayState *))
+ MAKE_NO_OP(SetDisplayState(DisplayState, int*))
+ MAKE_NO_OP(SetFrameBufferConfig(const DisplayConfigVariableInfo &))
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 *))
@@ -86,18 +83,29 @@
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))
MAKE_NO_OP(GetClientTargetSupport(uint32_t, uint32_t, LayerBufferFormat,
const ColorMetaData &))
- std::string Dump() { return ""; }
+
+ DisplayConfigVariableInfo default_variable_config_ = {};
+ DisplayConfigFixedInfo default_fixed_config_ = {};
+};
+
+class DisplayNullExternal : public DisplayNull {
+ public:
+ virtual DisplayError Commit(LayerStack *layer_stack);
+ virtual DisplayError GetDisplayState(DisplayState *state);
+ virtual DisplayError SetDisplayState(DisplayState state, int *release_fence);
+ virtual DisplayError SetFrameBufferConfig(const DisplayConfigVariableInfo &variable_info);
+ virtual DisplayError GetFrameBufferConfig(DisplayConfigVariableInfo *variable_info);
+ void SetActive(bool active) { active_ = active; }
+ bool IsActive() { return active_; }
private:
bool active_ = false;
diff --git a/sdm/libs/hwc2/hwc_buffer_allocator.cpp b/sdm/libs/hwc2/hwc_buffer_allocator.cpp
index e9839b9..84fbd80 100644
--- a/sdm/libs/hwc2/hwc_buffer_allocator.cpp
+++ b/sdm/libs/hwc2/hwc_buffer_allocator.cpp
@@ -1,5 +1,5 @@
/*
-* Copyright (c) 2015-2017, The Linux Foundation. All rights reserved.
+* Copyright (c) 2015-2018, 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
@@ -293,6 +293,7 @@
*target = HAL_PIXEL_FORMAT_YCrCb_420_SP_VENUS;
break;
case kFormatYCbCr420SPVenusUbwc:
+ case kFormatYCbCr420SPVenusTile:
*target = HAL_PIXEL_FORMAT_YCbCr_420_SP_VENUS_UBWC;
*flags |= GRALLOC_USAGE_PRIVATE_ALLOC_UBWC;
break;
@@ -330,10 +331,12 @@
*target = HAL_PIXEL_FORMAT_YCbCr_420_P010;
break;
case kFormatYCbCr420TP10Ubwc:
+ case kFormatYCbCr420TP10Tile:
*target = HAL_PIXEL_FORMAT_YCbCr_420_TP10_UBWC;
*flags |= GRALLOC_USAGE_PRIVATE_ALLOC_UBWC;
break;
case kFormatYCbCr420P010Ubwc:
+ case kFormatYCbCr420P010Tile:
*target = HAL_PIXEL_FORMAT_YCbCr_420_P010_UBWC;
*flags |= GRALLOC_USAGE_PRIVATE_ALLOC_UBWC;
break;
diff --git a/sdm/libs/hwc2/hwc_buffer_sync_handler.cpp b/sdm/libs/hwc2/hwc_buffer_sync_handler.cpp
index 784e91b..f2dacb2 100644
--- a/sdm/libs/hwc2/hwc_buffer_sync_handler.cpp
+++ b/sdm/libs/hwc2/hwc_buffer_sync_handler.cpp
@@ -27,6 +27,7 @@
* IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
+#include <errno.h>
#include <sync/sync.h>
#include <utils/constants.h>
#include <utils/debug.h>
diff --git a/sdm/libs/hwc2/hwc_display.cpp b/sdm/libs/hwc2/hwc_display.cpp
index 0ce1f1e..340a7ac 100644
--- a/sdm/libs/hwc2/hwc_display.cpp
+++ b/sdm/libs/hwc2/hwc_display.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2014-2017, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2014-2018, The Linux Foundation. All rights reserved.
* Not a Contribution.
*
* Copyright 2015 The Android Open Source Project
@@ -360,11 +360,23 @@
}
int HWCDisplay::Init() {
- DisplayError 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;
+ DisplayError error = kErrorNone;
+
+ HWCDebugHandler::Get()->GetProperty("sdm.debug.enable_null_display", &null_display_mode_);
+
+ if (null_display_mode_) {
+ DisplayNull *disp_null = new DisplayNull();
+ disp_null->Init();
+ use_metadata_refresh_rate_ = false;
+ display_intf_ = disp_null;
+ ALOGI("Enabling null display mode for display type %d", type_);
+ } else {
+ 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;
+ }
}
validated_ = false;
@@ -405,10 +417,15 @@
}
int HWCDisplay::Deinit() {
- DisplayError error = core_intf_->DestroyDisplay(display_intf_);
- if (error != kErrorNone) {
- DLOGE("Display destroy failed. Error = %d", error);
- return -EINVAL;
+ if (null_display_mode_) {
+ delete static_cast<DisplayNull *>(display_intf_);
+ display_intf_ = nullptr;
+ } else {
+ DisplayError error = core_intf_->DestroyDisplay(display_intf_);
+ if (error != kErrorNone) {
+ DLOGE("Display destroy failed. Error = %d", error);
+ return -EINVAL;
+ }
}
delete client_target_;
@@ -421,8 +438,10 @@
delete color_mode_;
}
- delete tone_mapper_;
- tone_mapper_ = nullptr;
+ if (tone_mapper_) {
+ delete tone_mapper_;
+ tone_mapper_ = nullptr;
+ }
return 0;
}
@@ -434,6 +453,8 @@
*out_layer_id = layer->GetId();
geometry_changes_ |= GeometryChanges::kAdded;
validated_ = false;
+ layer_stack_invalid_ = true;
+
return HWC2::Error::None;
}
@@ -466,6 +487,8 @@
geometry_changes_ |= GeometryChanges::kRemoved;
validated_ = false;
+ layer_stack_invalid_ = true;
+
return HWC2::Error::None;
}
@@ -633,6 +656,8 @@
}
// set secure display
SetSecureDisplay(secure_display_active);
+
+ layer_stack_invalid_ = false;
}
void HWCDisplay::BuildSolidFillStack() {
@@ -742,9 +767,10 @@
default:
return HWC2::Error::BadParameter;
}
+ int release_fence = -1;
ATRACE_INT("SetPowerMode ", state);
- DisplayError error = display_intf_->SetDisplayState(state);
+ DisplayError error = display_intf_->SetDisplayState(state, &release_fence);
validated_ = false;
if (error == kErrorNone) {
@@ -758,6 +784,20 @@
return HWC2::Error::BadParameter;
}
+ if (release_fence >= 0) {
+ for (auto hwc_layer : layer_set_) {
+ auto fence = hwc_layer->PopBackReleaseFence();
+ auto merged_fence = -1;
+ if (fence >= 0) {
+ merged_fence = sync_merge("sync_merge", release_fence, fence);
+ ::close(fence);
+ } else {
+ merged_fence = ::dup(release_fence);
+ }
+ hwc_layer->PushBackReleaseFence(merged_fence);
+ }
+ ::close(release_fence);
+ }
return HWC2::Error::None;
}
@@ -1014,7 +1054,10 @@
HWC2::Error HWCDisplay::PrepareLayerStack(uint32_t *out_num_types, uint32_t *out_num_requests) {
layer_changes_.clear();
layer_requests_.clear();
+ has_client_composition_ = false;
+
if (shutdown_pending_) {
+ validated_ = false;
return HWC2::Error::BadDisplay;
}
@@ -1029,9 +1072,8 @@
// so that previous buffer and fences are released, and override the error.
flush_ = true;
}
+ validated_ = false;
return HWC2::Error::BadDisplay;
- } else {
- validated_ = true;
}
} else {
// Skip is not set
@@ -1055,6 +1097,9 @@
// Set SDM composition to HWC2 type in HWCLayer
hwc_layer->SetComposition(composition);
HWC2::Composition device_composition = hwc_layer->GetDeviceSelectedCompositionType();
+ if (device_composition == HWC2::Composition::Client) {
+ has_client_composition_ = true;
+ }
// Update the changes list only if the requested composition is different from SDM comp type
// TODO(user): Take Care of other comptypes(BLIT)
if (requested_composition != device_composition) {
@@ -1062,15 +1107,14 @@
}
hwc_layer->ResetValidation();
}
+
client_target_->ResetValidation();
*out_num_types = UINT32(layer_changes_.size());
*out_num_requests = UINT32(layer_requests_.size());
- skip_validate_ = false;
- if (*out_num_types > 0) {
- return HWC2::Error::HasChanges;
- } else {
- return HWC2::Error::None;
- }
+ validate_state_ = kNormalValidate;
+ validated_ = true;
+
+ return ((*out_num_types > 0) ? HWC2::Error::HasChanges : HWC2::Error::None);
}
HWC2::Error HWCDisplay::AcceptDisplayChanges() {
@@ -1129,7 +1173,7 @@
for (uint32_t i = 0; i < *out_num_elements; i++, it++) {
auto hwc_layer = *it;
out_layers[i] = hwc_layer->GetId();
- out_fences[i] = hwc_layer->PopReleaseFence();
+ out_fences[i] = hwc_layer->PopFrontReleaseFence();
}
} else {
*out_num_elements = UINT32(layer_set_.size());
@@ -1214,10 +1258,6 @@
HWC2::Error HWCDisplay::CommitLayerStack(void) {
- if (skip_validate_ && !CanSkipValidate()) {
- validated_ = false;
- }
-
if (!validated_) {
DLOGV_IF(kTagClient, "Display %d is not validated", id_);
return HWC2::Error::NotValidated;
@@ -1263,7 +1303,7 @@
}
}
- skip_validate_ = true;
+ validate_state_ = kSkipValidate;
return HWC2::Error::None;
}
@@ -1300,15 +1340,15 @@
if (swap_interval_zero_ || layer->flags.single_buffer) {
close(layer_buffer->release_fence_fd);
} else if (layer->composition != kCompositionGPU) {
- hwc_layer->PushReleaseFence(layer_buffer->release_fence_fd);
+ hwc_layer->PushBackReleaseFence(layer_buffer->release_fence_fd);
} else {
- hwc_layer->PushReleaseFence(-1);
+ hwc_layer->PushBackReleaseFence(-1);
}
} else {
// In case of flush, we don't return an error to f/w, so it will get a release fence out of
// the hwc_layer's release fence queue. We should push a -1 to preserve release fence
// circulation semantics.
- hwc_layer->PushReleaseFence(-1);
+ hwc_layer->PushBackReleaseFence(-1);
}
layer_buffer->release_fence_fd = -1;
@@ -1761,7 +1801,7 @@
if (hwc_layer->GetDeviceSelectedCompositionType() != HWC2::Composition::Cursor) {
return HWC2::Error::None;
}
- if (!skip_validate_ && validated_) {
+ if ((validate_state_ != kSkipValidate) && validated_) {
// the device is currently in the middle of the validate/present sequence,
// cannot set the Position(as per HWC2 spec)
return HWC2::Error::NotValidated;
@@ -2040,6 +2080,11 @@
<< std::endl;
}
+ if (layer_stack_invalid_) {
+ os << "\n Layers added or removed but not reflected to SDM's layer stack yet\n";
+ return os.str();
+ }
+
if (color_mode_) {
os << "\n----------Color Modes---------\n";
color_mode_->Dump(&os);
@@ -2056,8 +2101,7 @@
}
bool HWCDisplay::CanSkipValidate() {
- if (solid_fill_enable_) {
- DLOGV_IF(kTagClient, "Solid fill is enabled. Returning false.");
+ if (!validated_ || solid_fill_enable_) {
return false;
}
@@ -2091,4 +2135,12 @@
return true;
}
+HWC2::Error HWCDisplay::GetValidateDisplayOutput(uint32_t *out_num_types,
+ uint32_t *out_num_requests) {
+ *out_num_types = UINT32(layer_changes_.size());
+ *out_num_requests = UINT32(layer_requests_.size());
+
+ return ((*out_num_types > 0) ? HWC2::Error::HasChanges : HWC2::Error::None);
+}
+
} // namespace sdm
diff --git a/sdm/libs/hwc2/hwc_display.h b/sdm/libs/hwc2/hwc_display.h
index c251944..212de7f 100644
--- a/sdm/libs/hwc2/hwc_display.h
+++ b/sdm/libs/hwc2/hwc_display.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2014-2017, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2014-2018, The Linux Foundation. All rights reserved.
* Not a Contribution.
*
* Copyright 2015 The Android Open Source Project
@@ -36,6 +36,7 @@
#include "hwc_buffer_allocator.h"
#include "hwc_callbacks.h"
#include "hwc_layers.h"
+#include "display_null.h"
namespace sdm {
@@ -102,6 +103,12 @@
kDisplayStatusResume,
};
+ enum DisplayValidateState {
+ kNormalValidate,
+ kInternalValidate,
+ kSkipValidate,
+ };
+
virtual ~HWCDisplay() {}
virtual int Init();
virtual int Deinit();
@@ -164,6 +171,11 @@
HWCLayer *GetHWCLayer(hwc2_layer_t layer_id);
void ResetValidation() { validated_ = false; }
uint32_t GetGeometryChanges() { return geometry_changes_; }
+ bool CanSkipValidate();
+ bool HasClientComposition() { return has_client_composition_; }
+ bool IsSkipValidateState() { return (validate_state_ == kSkipValidate); }
+ bool IsInternalValidateState() { return (validated_ && (validate_state_ == kInternalValidate)); }
+ void SetValidationState(DisplayValidateState state) { validate_state_ = state; }
// HWC2 APIs
virtual HWC2::Error AcceptDisplayChanges(void);
@@ -219,6 +231,7 @@
validated_ = false;
return HWC2::Error::None;
}
+ virtual HWC2::Error GetValidateDisplayOutput(uint32_t *out_num_types, uint32_t *out_num_requests);
protected:
// Maximum number of layers supported by display manager.
@@ -257,6 +270,7 @@
};
bool validated_ = false;
+ bool layer_stack_invalid_ = true;
CoreInterface *core_intf_ = nullptr;
HWCCallbacks *callbacks_ = nullptr;
HWCBufferAllocator *buffer_allocator_ = NULL;
@@ -302,12 +316,13 @@
private:
void DumpInputBuffers(void);
- bool CanSkipValidate();
qService::QService *qservice_ = NULL;
DisplayClass display_class_;
uint32_t geometry_changes_ = GeometryChanges::kNone;
- bool skip_validate_ = false;
bool animating_ = false;
+ int null_display_mode_ = 0;
+ bool has_client_composition_ = false;
+ DisplayValidateState validate_state_ = kNormalValidate;
};
inline int HWCDisplay::Perform(uint32_t operation, ...) {
diff --git a/sdm/libs/hwc2/hwc_display_external.cpp b/sdm/libs/hwc2/hwc_display_external.cpp
index 2bc2d18..675484b 100644
--- a/sdm/libs/hwc2/hwc_display_external.cpp
+++ b/sdm/libs/hwc2/hwc_display_external.cpp
@@ -1,5 +1,5 @@
/*
-* Copyright (c) 2014-2017, The Linux Foundation. All rights reserved.
+* Copyright (c) 2014-2018, 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
@@ -230,9 +230,12 @@
DLOGW("Set frame buffer config failed. Error = %d", error);
return -1;
}
-
+ int release_fence = -1;
display_null_.GetDisplayState(&state);
- display_intf_->SetDisplayState(state);
+ display_intf_->SetDisplayState(state, &release_fence);
+ if (release_fence >= 0) {
+ ::close(release_fence);
+ }
validated_ = false;
SetVsyncEnabled(HWC2::Vsync::Enable);
@@ -244,10 +247,14 @@
}
} else {
if (!display_null_.IsActive()) {
+ int release_fence = -1;
// Preserve required attributes of HDMI display that surfaceflinger sees.
// Restore HDMI attributes when display is reconnected.
display_intf_->GetDisplayState(&state);
- display_null_.SetDisplayState(state);
+ display_null_.SetDisplayState(state, &release_fence);
+ if (release_fence >= 0) {
+ ::close(release_fence);
+ }
error = display_intf_->GetFrameBufferConfig(&fb_config);
if (error != kErrorNone) {
diff --git a/sdm/libs/hwc2/hwc_display_external.h b/sdm/libs/hwc2/hwc_display_external.h
index fbee6a3..75e9387 100644
--- a/sdm/libs/hwc2/hwc_display_external.h
+++ b/sdm/libs/hwc2/hwc_display_external.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2014-2017, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2014-2018, 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
@@ -58,7 +58,7 @@
static void GetDownscaleResolution(uint32_t primary_width, uint32_t primary_height,
uint32_t *virtual_width, uint32_t *virtual_height);
- DisplayNull display_null_;
+ DisplayNullExternal display_null_;
int underscan_width_ = 0;
int underscan_height_ = 0;
};
diff --git a/sdm/libs/hwc2/hwc_display_primary.cpp b/sdm/libs/hwc2/hwc_display_primary.cpp
index 1f2fdf6..21c958d 100644
--- a/sdm/libs/hwc2/hwc_display_primary.cpp
+++ b/sdm/libs/hwc2/hwc_display_primary.cpp
@@ -1,5 +1,5 @@
/*
-* Copyright (c) 2014 - 2017, The Linux Foundation. All rights reserved.
+* Copyright (c) 2014 - 2018, 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
@@ -475,13 +475,17 @@
}
void HWCDisplayPrimary::HandleFrameDump() {
- if (dump_frame_count_ && output_buffer_.release_fence_fd >= 0) {
- int ret = sync_wait(output_buffer_.release_fence_fd, 1000);
- ::close(output_buffer_.release_fence_fd);
- output_buffer_.release_fence_fd = -1;
- if (ret < 0) {
- DLOGE("sync_wait error errno = %d, desc = %s", errno, strerror(errno));
- } else {
+ if (dump_frame_count_) {
+ int ret = 0;
+ if (output_buffer_.release_fence_fd >= 0) {
+ ret = sync_wait(output_buffer_.release_fence_fd, 1000);
+ ::close(output_buffer_.release_fence_fd);
+ output_buffer_.release_fence_fd = -1;
+ if (ret < 0) {
+ DLOGE("sync_wait error errno = %d, desc = %s", errno, strerror(errno));
+ }
+ }
+ if (ret >= 0) {
DumpOutputBuffer(output_buffer_info_, output_buffer_base_, layer_stack_.retire_fence_fd);
}
}
diff --git a/sdm/libs/hwc2/hwc_layers.cpp b/sdm/libs/hwc2/hwc_layers.cpp
index d611352..1193ec4 100644
--- a/sdm/libs/hwc2/hwc_layers.cpp
+++ b/sdm/libs/hwc2/hwc_layers.cpp
@@ -174,14 +174,14 @@
layer_ = new Layer();
// Fences are deferred, so the first time this layer is presented, return -1
// TODO(user): Verify that fences are properly obtained on suspend/resume
- release_fences_.push(-1);
+ release_fences_.push_back(-1);
}
HWCLayer::~HWCLayer() {
// Close any fences left for this layer
while (!release_fences_.empty()) {
::close(release_fences_.front());
- release_fences_.pop();
+ release_fences_.pop_front();
}
if (layer_) {
if (layer_->input_buffer.acquire_fence_fd >= 0) {
@@ -892,14 +892,28 @@
return;
}
-void HWCLayer::PushReleaseFence(int32_t fence) {
- release_fences_.push(fence);
+
+void HWCLayer::PushBackReleaseFence(int32_t fence) {
+ release_fences_.push_back(fence);
}
-int32_t HWCLayer::PopReleaseFence(void) {
+
+int32_t HWCLayer::PopBackReleaseFence() {
if (release_fences_.empty())
return -1;
+
+ auto fence = release_fences_.back();
+ release_fences_.pop_back();
+
+ return fence;
+}
+
+int32_t HWCLayer::PopFrontReleaseFence() {
+ if (release_fences_.empty())
+ return -1;
+
auto fence = release_fences_.front();
- release_fences_.pop();
+ release_fences_.pop_front();
+
return fence;
}
diff --git a/sdm/libs/hwc2/hwc_layers.h b/sdm/libs/hwc2/hwc_layers.h
index ed03c50..a7d7f01 100644
--- a/sdm/libs/hwc2/hwc_layers.h
+++ b/sdm/libs/hwc2/hwc_layers.h
@@ -32,7 +32,7 @@
#undef HWC2_INCLUDE_STRINGIFICATION
#undef HWC2_USE_CPP11
#include <map>
-#include <queue>
+#include <deque>
#include <set>
#include "core/buffer_allocator.h"
#include "hwc_buffer_allocator.h"
@@ -88,8 +88,9 @@
int32_t GetLayerDataspace() { return dataspace_; }
uint32_t GetGeometryChanges() { return geometry_changes_; }
void ResetGeometryChanges() { geometry_changes_ = GeometryChanges::kNone; }
- void PushReleaseFence(int32_t fence);
- int32_t PopReleaseFence(void);
+ void PushBackReleaseFence(int32_t fence);
+ int32_t PopBackReleaseFence(void);
+ int32_t PopFrontReleaseFence(void);
bool ValidateAndSetCSC();
bool SupportLocalConversion(ColorPrimaries working_primaries);
void ResetValidation() { needs_validate_ = false; }
@@ -104,7 +105,7 @@
const hwc2_layer_t id_;
const hwc2_display_t display_id_;
static std::atomic<hwc2_layer_t> next_id_;
- std::queue<int32_t> release_fences_;
+ std::deque<int32_t> release_fences_;
HWCBufferAllocator *buffer_allocator_ = NULL;
int32_t dataspace_ = HAL_DATASPACE_UNKNOWN;
LayerTransform layer_transform_ = {};
diff --git a/sdm/libs/hwc2/hwc_session.cpp b/sdm/libs/hwc2/hwc_session.cpp
index 36b55d0..4302bd9 100644
--- a/sdm/libs/hwc2/hwc_session.cpp
+++ b/sdm/libs/hwc2/hwc_session.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2014-2017, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2014-2018, The Linux Foundation. All rights reserved.
* Not a Contribution.
*
* Copyright 2015 The Android Open Source Project
@@ -72,6 +72,7 @@
static HWCUEvent g_hwc_uevent_;
Locker HWCSession::locker_[HWC_NUM_DISPLAY_TYPES];
+static const int kSolidFillDelay = 100 * 1000;
void HWCUEvent::UEventThread(HWCUEvent *hwc_uevent) {
const char *uevent_thread_name = "HWC_UeventThread";
@@ -160,35 +161,44 @@
StartServices();
+ HWCDebugHandler::Get()->GetProperty("sdm.debug.enable_null_display", &null_display_mode_);
+
DisplayError error = buffer_allocator_.Init();
if (error != kErrorNone) {
- ALOGE("%s::%s: Buffer allocaor initialization failed. Error = %d",
+ ALOGE("%s::%s: Buffer allocator initialization failed. Error = %d",
__CLASS__, __FUNCTION__, error);
return -EINVAL;
}
- g_hwc_uevent_.Register(this);
+ HWDisplayInterfaceInfo hw_disp_info = {};
+ if (null_display_mode_) {
+ hw_disp_info.type = kPrimary;
+ hw_disp_info.is_connected = true;
+ } else {
+ g_hwc_uevent_.Register(this);
- error = CoreInterface::CreateCore(HWCDebugHandler::Get(), &buffer_allocator_,
- &buffer_sync_handler_, &socket_handler_, &core_intf_);
- if (error != kErrorNone) {
- buffer_allocator_.Deinit();
- ALOGE("%s::%s: Display core initialization failed. Error = %d", __CLASS__, __FUNCTION__, error);
- return -EINVAL;
+ error = CoreInterface::CreateCore(HWCDebugHandler::Get(), &buffer_allocator_,
+ &buffer_sync_handler_, &socket_handler_, &core_intf_);
+
+ if (error != kErrorNone) {
+ buffer_allocator_.Deinit();
+ ALOGE("%s::%s: Display core initialization failed. Error = %d", __CLASS__, __FUNCTION__,
+ error);
+ return -EINVAL;
+ }
+
+ error = core_intf_->GetFirstDisplayInterfaceType(&hw_disp_info);
+
+ if (error != kErrorNone) {
+ g_hwc_uevent_.Register(nullptr);
+ CoreInterface::DestroyCore();
+ buffer_allocator_.Deinit();
+ DLOGE("Primary display type not recognized. Error = %d", error);
+ return -EINVAL;
+ }
}
-
// 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) {
- g_hwc_uevent_.Register(nullptr);
- CoreInterface::DestroyCore();
- buffer_allocator_.Deinit();
- DLOGE("Primary display type not recognized. Error = %d", error);
- return -EINVAL;
- }
-
if (hw_disp_info.type == kHDMI) {
status = 0;
hdmi_is_primary_ = true;
@@ -246,11 +256,13 @@
color_mgr_->DestroyColorManager();
}
- g_hwc_uevent_.Register(nullptr);
+ if (!null_display_mode_) {
+ g_hwc_uevent_.Register(nullptr);
- DisplayError error = CoreInterface::DestroyCore();
- if (error != kErrorNone) {
- ALOGE("Display core de-initialization failed. Error = %d", error);
+ DisplayError error = CoreInterface::DestroyCore();
+ if (error != kErrorNone) {
+ ALOGE("Display core de-initialization failed. Error = %d", error);
+ }
}
return 0;
@@ -542,7 +554,7 @@
// TODO(user): Handle virtual display/HDMI concurrency
if (hwc_session->hwc_display_[display]) {
- status = hwc_session->hwc_display_[display]->Present(out_retire_fence);
+ status = hwc_session->PresentDisplayInternal(display, out_retire_fence);
}
}
@@ -782,24 +794,7 @@
{
SEQUENCE_ENTRY_SCOPE_LOCK(locker_[display]);
if (hwc_session->hwc_display_[display]) {
- if (display == HWC_DISPLAY_PRIMARY) {
- // TODO(user): This can be moved to HWCDisplayPrimary
- if (hwc_session->reset_panel_) {
- DLOGW("panel is in bad state, resetting the panel");
- hwc_session->ResetPanel();
- }
-
- if (hwc_session->need_invalidate_) {
- hwc_session->Refresh(display);
- hwc_session->need_invalidate_ = false;
- }
-
- if (hwc_session->color_mgr_) {
- hwc_session->color_mgr_->SetColorModeDetailEnhancer(hwc_session->hwc_display_[display]);
- }
- }
-
- status = hwc_session->hwc_display_[display]->Validate(out_num_types, out_num_requests);
+ status = hwc_session->ValidateDisplayInternal(display, out_num_types, out_num_requests);
}
}
@@ -1530,14 +1525,22 @@
ret = color_mgr_->EnableQDCMMode(false, hwc_display_[HWC_DISPLAY_PRIMARY]);
break;
case kApplySolidFill:
- ret = color_mgr_->SetSolidFill(pending_action.params,
+ {
+ SCOPE_LOCK(locker_[HWC_DISPLAY_PRIMARY]);
+ ret = color_mgr_->SetSolidFill(pending_action.params,
true, hwc_display_[HWC_DISPLAY_PRIMARY]);
+ }
Refresh(HWC_DISPLAY_PRIMARY);
+ usleep(kSolidFillDelay);
break;
case kDisableSolidFill:
- ret = color_mgr_->SetSolidFill(pending_action.params,
+ {
+ SCOPE_LOCK(locker_[HWC_DISPLAY_PRIMARY]);
+ ret = color_mgr_->SetSolidFill(pending_action.params,
false, hwc_display_[HWC_DISPLAY_PRIMARY]);
+ }
Refresh(HWC_DISPLAY_PRIMARY);
+ usleep(kSolidFillDelay);
break;
case kSetPanelBrightness:
brightness_value = reinterpret_cast<int32_t *>(resp_payload.payload);
@@ -1880,4 +1883,48 @@
}
#endif
+HWC2::Error HWCSession::ValidateDisplayInternal(hwc2_display_t display, uint32_t *out_num_types,
+ uint32_t *out_num_requests) {
+ HWCDisplay *hwc_display = hwc_display_[display];
+ if (hwc_display->IsInternalValidateState()) {
+ // Internal Validation has already been done on display, get the Output params.
+ return hwc_display->GetValidateDisplayOutput(out_num_types, out_num_requests);
+ }
+
+ if (display == HWC_DISPLAY_PRIMARY) {
+ // TODO(user): This can be moved to HWCDisplayPrimary
+ if (reset_panel_) {
+ DLOGW("panel is in bad state, resetting the panel");
+ ResetPanel();
+ }
+
+ if (need_invalidate_) {
+ Refresh(display);
+ need_invalidate_ = false;
+ }
+
+ if (color_mgr_) {
+ color_mgr_->SetColorModeDetailEnhancer(hwc_display_[display]);
+ }
+ }
+
+ return hwc_display->Validate(out_num_types, out_num_requests);
+}
+
+HWC2::Error HWCSession::PresentDisplayInternal(hwc2_display_t display, int32_t *out_retire_fence) {
+ HWCDisplay *hwc_display = hwc_display_[display];
+ // If display is in Skip-Validate state and Validate cannot be skipped, do Internal
+ // Validation to optimize for the frames which don't require the Client composition.
+ if (hwc_display->IsSkipValidateState() && !hwc_display->CanSkipValidate()) {
+ uint32_t out_num_types = 0, out_num_requests = 0;
+ HWC2::Error error = ValidateDisplayInternal(display, &out_num_types, &out_num_requests);
+ if ((error != HWC2::Error::None) || hwc_display->HasClientComposition()) {
+ hwc_display->SetValidationState(HWCDisplay::kInternalValidate);
+ return HWC2::Error::NotValidated;
+ }
+ }
+
+ return hwc_display->Present(out_retire_fence);
+}
+
} // namespace sdm
diff --git a/sdm/libs/hwc2/hwc_session.h b/sdm/libs/hwc2/hwc_session.h
index 8d25989..4bd7b00 100644
--- a/sdm/libs/hwc2/hwc_session.h
+++ b/sdm/libs/hwc2/hwc_session.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2014-2017, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2014-2018, The Linux Foundation. All rights reserved.
* Not a Contribution.
*
* Copyright 2015 The Android Open Source Project
@@ -247,6 +247,9 @@
void Refresh(hwc2_display_t display);
void HotPlug(hwc2_display_t display, HWC2::Connection state);
+ HWC2::Error ValidateDisplayInternal(hwc2_display_t display, uint32_t *out_num_types,
+ uint32_t *out_num_requests);
+ HWC2::Error PresentDisplayInternal(hwc2_display_t display, int32_t *out_retire_fence);
CoreInterface *core_intf_ = nullptr;
HWCDisplay *hwc_display_[HWC_NUM_DISPLAY_TYPES] = {nullptr};
@@ -267,6 +270,7 @@
Locker callbacks_lock_;
int hpd_bpp_ = 0;
int hpd_pattern_ = 0;
+ int null_display_mode_ = 0;
};
} // namespace sdm
diff --git a/sdm/libs/hwc2/hwc_session_services.cpp b/sdm/libs/hwc2/hwc_session_services.cpp
index 6984711..f91b8f1 100644
--- a/sdm/libs/hwc2/hwc_session_services.cpp
+++ b/sdm/libs/hwc2/hwc_session_services.cpp
@@ -1,5 +1,5 @@
/*
-* Copyright (c) 2017, The Linux Foundation. All rights reserved.
+* Copyright (c) 2017-2018, 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
@@ -452,6 +452,10 @@
Return<int32_t> HWCSession::setCameraLaunchStatus(uint32_t on) {
SEQUENCE_WAIT_SCOPE_LOCK(locker_[HWC_DISPLAY_PRIMARY]);
+ if (null_display_mode_) {
+ return 0;
+ }
+
if (!core_intf_) {
DLOGW("core_intf_ not initialized.");
return -ENOENT;
diff --git a/sdm/libs/hwc2/hwc_tonemapper.cpp b/sdm/libs/hwc2/hwc_tonemapper.cpp
index 26caec9..2ae1afc 100644
--- a/sdm/libs/hwc2/hwc_tonemapper.cpp
+++ b/sdm/libs/hwc2/hwc_tonemapper.cpp
@@ -146,22 +146,22 @@
release_fence_fd_[current_buffer_index_] = dup(fd);
}
-void ToneMapSession::SetToneMapConfig(Layer *layer) {
+void ToneMapSession::SetToneMapConfig(Layer *layer, PrimariesTransfer blend_cs) {
// HDR -> SDR is FORWARD and SDR - > HDR is INVERSE
tone_map_config_.type = layer->input_buffer.flags.hdr ? TONEMAP_FORWARD : TONEMAP_INVERSE;
- tone_map_config_.colorPrimaries = layer->input_buffer.color_metadata.colorPrimaries;
+ tone_map_config_.blend_cs = blend_cs;
tone_map_config_.transfer = layer->input_buffer.color_metadata.transfer;
tone_map_config_.secure = layer->request.flags.secure;
tone_map_config_.format = layer->request.format;
}
-bool ToneMapSession::IsSameToneMapConfig(Layer *layer) {
+bool ToneMapSession::IsSameToneMapConfig(Layer *layer, PrimariesTransfer blend_cs) {
LayerBuffer& buffer = layer->input_buffer;
private_handle_t *handle = static_cast<private_handle_t *>(buffer_info_[0].private_data);
int tonemap_type = buffer.flags.hdr ? TONEMAP_FORWARD : TONEMAP_INVERSE;
return ((tonemap_type == tone_map_config_.type) &&
- (buffer.color_metadata.colorPrimaries == tone_map_config_.colorPrimaries) &&
+ (blend_cs == tone_map_config_.blend_cs) &&
(buffer.color_metadata.transfer == tone_map_config_.transfer) &&
(layer->request.flags.secure == tone_map_config_.secure) &&
(layer->request.format == tone_map_config_.format) &&
@@ -197,11 +197,11 @@
return 0;
}
}
- error = AcquireToneMapSession(layer, &session_index);
+ error = AcquireToneMapSession(layer, &session_index, layer_stack->blend_cs);
fb_session_index_ = INT(session_index);
break;
default:
- error = AcquireToneMapSession(layer, &session_index);
+ error = AcquireToneMapSession(layer, &session_index, layer_stack->blend_cs);
break;
}
@@ -331,7 +331,8 @@
CloseFd(acquire_fd);
}
-DisplayError HWCToneMapper::AcquireToneMapSession(Layer *layer, uint32_t *session_index) {
+DisplayError HWCToneMapper::AcquireToneMapSession(Layer *layer, uint32_t *session_index,
+ PrimariesTransfer blend_cs) {
// 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.
@@ -344,7 +345,7 @@
// Check if we can re-use an existing tone map session.
for (uint32_t i = 0; i < tone_map_sessions_.size(); i++) {
ToneMapSession *tonemap_session = tone_map_sessions_.at(i);
- if (!tonemap_session->acquired_ && tonemap_session->IsSameToneMapConfig(layer)) {
+ if (!tonemap_session->acquired_ && tonemap_session->IsSameToneMapConfig(layer, blend_cs)) {
tonemap_session->current_buffer_index_ = (tonemap_session->current_buffer_index_ + 1) %
ToneMapSession::kNumIntermediateBuffers;
tonemap_session->acquired_ = true;
@@ -358,7 +359,7 @@
return kErrorMemory;
}
- session->SetToneMapConfig(layer);
+ session->SetToneMapConfig(layer, blend_cs);
ToneMapGetInstanceContext ctx;
ctx.layer = layer;
diff --git a/sdm/libs/hwc2/hwc_tonemapper.h b/sdm/libs/hwc2/hwc_tonemapper.h
index 8bef3b1..bc564eb 100644
--- a/sdm/libs/hwc2/hwc_tonemapper.h
+++ b/sdm/libs/hwc2/hwc_tonemapper.h
@@ -1,5 +1,5 @@
/*
-* Copyright (c) 2016 - 2017, The Linux Foundation. All rights reserved.
+* Copyright (c) 2016 - 2018, 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,7 +64,7 @@
struct ToneMapConfig {
int type = 0;
- ColorPrimaries colorPrimaries = ColorPrimaries_Max;
+ PrimariesTransfer blend_cs = {};
GammaTransfer transfer = Transfer_Max;
LayerBufferFormat format = kFormatRGBA8888;
bool secure = false;
@@ -78,8 +78,8 @@
void FreeIntermediateBuffers();
void UpdateBuffer(int acquire_fence, LayerBuffer *buffer);
void SetReleaseFence(int fd);
- void SetToneMapConfig(Layer *layer);
- bool IsSameToneMapConfig(Layer *layer);
+ void SetToneMapConfig(Layer *layer, PrimariesTransfer blend_cs);
+ bool IsSameToneMapConfig(Layer *layer, PrimariesTransfer blend_cs);
// TaskHandler methods implementation.
virtual void OnTask(const ToneMapTaskCode &task_code,
@@ -110,7 +110,7 @@
private:
void ToneMap(Layer *layer, ToneMapSession *session);
- DisplayError AcquireToneMapSession(Layer *layer, uint32_t *session_index);
+ DisplayError AcquireToneMapSession(Layer *layer, uint32_t *sess_idx, PrimariesTransfer blend_cs);
void DumpToneMapOutput(ToneMapSession *session, int *acquire_fence);
std::vector<ToneMapSession*> tone_map_sessions_;
diff --git a/sdm/libs/utils/formats.cpp b/sdm/libs/utils/formats.cpp
index 42dfea9..bb6ee94 100644
--- a/sdm/libs/utils/formats.cpp
+++ b/sdm/libs/utils/formats.cpp
@@ -1,5 +1,5 @@
/*
-* Copyright (c) 2016-2017, The Linux Foundation. All rights reserved.
+* Copyright (c) 2016-2018, 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
@@ -100,6 +100,7 @@
case kFormatYCbCr422H2V1SemiPlanar: return "Y_CBCR_422_H2V1";
case kFormatYCrCb422H2V1SemiPlanar: return "Y_CRCB_422_H2V2";
case kFormatYCbCr420SPVenusUbwc: return "Y_CBCR_420_VENUS_UBWC";
+ case kFormatYCbCr420SPVenusTile: return "Y_CBCR_420_VENUS_TILED";
case kFormatYCbCr422H2V1Packed: return "YCBYCR_422_H2V1";
case kFormatCbYCrY422H2V1Packed: return "CBYCRY_422_H2V1";
case kFormatRGBA1010102: return "RGBA_1010102";
@@ -116,6 +117,8 @@
case kFormatYCbCr420TP10Ubwc: return "Y_CBCR_420_TP10_UBWC";
case kFormatYCbCr420P010Ubwc: return "Y_CBCR_420_P010_UBWC";
case kFormatYCbCr420P010Venus: return "Y_CBCR_420_P010_VENUS";
+ case kFormatYCbCr420TP10Tile: return "Y_CBCR_420_TP10_TILED";
+ case kFormatYCbCr420P010Tile: return "Y_CBCR_420_P010_TILED";
default: return "UNKNOWN";
}
}
@@ -123,7 +126,11 @@
BufferLayout GetBufferLayout(LayerBufferFormat format) {
switch (format) {
case kFormatYCbCr420TP10Ubwc:
+ case kFormatYCbCr420TP10Tile:
return kTPTiled;
+ case kFormatYCbCr420SPVenusTile:
+ case kFormatYCbCr420P010Tile:
+ return kUBWC;
default:
return (IsUBWCFormat(format) ? kUBWC : kLinear);
}
@@ -156,6 +163,7 @@
case kFormatYCbCr420P010:
case kFormatYCbCr420P010Ubwc:
case kFormatYCbCr420P010Venus:
+ case kFormatYCbCr420P010Tile:
return 3.0f;
case kFormatRGB565:
case kFormatBGR565:
@@ -167,6 +175,7 @@
case kFormatYCrCb422H2V1SemiPlanar:
case kFormatYCbCr422H2V1SemiPlanar:
case kFormatYCbCr420TP10Ubwc:
+ case kFormatYCbCr420TP10Tile:
case kFormatYCbCr422H1V2SemiPlanar:
case kFormatYCrCb422H1V2SemiPlanar:
return 2.0f;
@@ -178,6 +187,7 @@
case kFormatYCbCr420SemiPlanarVenus:
case kFormatYCrCb420SemiPlanarVenus:
case kFormatYCbCr420SPVenusUbwc:
+ case kFormatYCbCr420SPVenusTile:
return 1.5f;
default:
return 0.0f;
@@ -189,18 +199,21 @@
DisplayError GetBufferFormatTileSize(LayerBufferFormat format, FormatTileSize *tile_size) {
switch (format) {
case kFormatYCbCr420SPVenusUbwc:
+ case kFormatYCbCr420SPVenusTile:
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:
+ case kFormatYCbCr420TP10Tile:
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:
+ case kFormatYCbCr420P010Tile:
tile_size->tile_width = 32;
tile_size->tile_height = 4;
tile_size->uv_tile_width = 16;
@@ -212,5 +225,25 @@
return kErrorNone;
}
+bool HasAlphaChannel(LayerBufferFormat format) {
+ switch (format) {
+ case kFormatARGB8888:
+ case kFormatRGBA8888:
+ case kFormatBGRA8888:
+ case kFormatRGBA5551:
+ case kFormatRGBA4444:
+ case kFormatRGBA8888Ubwc:
+ case kFormatRGBA1010102:
+ case kFormatARGB2101010:
+ case kFormatBGRA1010102:
+ case kFormatABGR2101010:
+ case kFormatRGBA1010102Ubwc:
+ return true;
+ default:
+ return false;
+ }
+}
+
+
} // namespace sdm
diff --git a/sdm/libs/utils/rect.cpp b/sdm/libs/utils/rect.cpp
index a830542..e121b58 100644
--- a/sdm/libs/utils/rect.cpp
+++ b/sdm/libs/utils/rect.cpp
@@ -1,5 +1,5 @@
/*
-* Copyright (c) 2015-2017, The Linux Foundation. All rights reserved.
+* Copyright (c) 2015-2018, 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
@@ -98,6 +98,47 @@
return res;
}
+// Is rect2 completely inside rect1?
+bool Contains(const LayerRect &rect1, const LayerRect &rect2) {
+ if (!IsValid(rect1) || !IsValid(rect2)) {
+ return false;
+ }
+ return (rect1.top <= rect2.top && rect1.bottom >= rect2.bottom &&
+ rect1.left <= rect2.left && rect1.right >= rect2.right);
+}
+
+// subtracts 2 rects iff result of subtraction is 2 rects.
+void Subtract(const LayerRect &rect1, const LayerRect &rect2, LayerRect *res) {
+ if (!res) {
+ return;
+ }
+ if (!IsValid(rect1) || !IsValid(rect2)) {
+ return;
+ }
+
+ if (rect1.left != rect2.left || rect1.right != rect2.right) {
+ return;
+ }
+ res[0].left = rect1.left;
+ res[0].right = rect1.right;
+ if (rect1.top < rect2.top) {
+ res[0].top = rect1.top;
+ res[0].bottom = rect2.top;
+ } else {
+ res[0].top = rect2.top;
+ res[0].bottom = rect1.top;
+ }
+ res[1].left = rect1.left;
+ res[1].right = rect1.right;
+ if (rect1.bottom < rect2.bottom) {
+ res[1].top = rect1.bottom;
+ res[1].bottom = rect2.bottom;
+ } else {
+ res[1].top = rect2.bottom;
+ res[1].bottom = rect1.bottom;
+ }
+}
+
// Not a geometrical rect deduction. Deducts rect2 from rect1 only if it results a single rect
LayerRect Subtract(const LayerRect &rect1, const LayerRect &rect2) {
LayerRect res;