Merge branch 'staging/lineage-15.1-caf-8996' of https://github.com/LineageOS/android_hardware_qcom_display into HEAD

Change-Id: Ic92c5edd0aef5c33dc84ef46ed38d8671d746da9
This commit is contained in:
dadi11 2018-01-20 23:30:38 +01:00
commit ee9aec33b6
48 changed files with 1979 additions and 470 deletions

View File

@ -1,31 +1,31 @@
/*
* Copyight (c) 2017 The Linux Foundation. All ights reserved.
*
* Redistibution and use in souce and binary forms, with or without
* modification, ae pemitted provided that the following conditions are
* met:
* * Redistibutions of souce code must retain the above copyright
* notice, this list of conditions and the following disclaime.
* * Redistibutions in binay form must reproduce the above
* copyight notice, this list of conditions and the following
* disclaime in the documentation and/o other materials provided
* with the distibution.
* * Neither the name of The Linux Foundation. no the names of its
* contibutos may be used to endorse or promote products derived
* fom this softwae without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
* OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
* IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
* Copyright (c) 2017 The Linux Foundation. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following
* disclaimer in the documentation and/or other materials provided
* with the distribution.
* * Neither the name of The Linux Foundation. nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
* OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
* IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef __DISPLAY_CONFIG_H__
#define __DISPLAY_CONFIG_H__

View File

@ -71,7 +71,7 @@ static int gralloc_map_metadata(buffer_handle_t handle) {
hnd, hnd->fd_metadata, strerror(errno));
return -errno;
}
hnd->base_metadata = uint64_t(mappedAddress) + hnd->offset_metadata;
hnd->base_metadata = uint64_t(mappedAddress);
}
return 0;
}
@ -102,7 +102,7 @@ static int gralloc_map(gralloc_module_t const* module,
return -errno;
}
hnd->base = uint64_t(mappedAddress) + hnd->offset;
hnd->base = uint64_t(mappedAddress);
} else {
// Cannot map secure buffers or framebuffers, but still need to map
// metadata for secure buffers.

View File

@ -48,16 +48,12 @@ AdrenoMemInfo *AdrenoMemInfo::GetInstance() {
lock_guard<mutex> obj(s_lock);
if (!s_instance) {
s_instance = new AdrenoMemInfo();
if (!s_instance->Init()) {
delete s_instance;
s_instance = nullptr;
}
}
return s_instance;
}
bool AdrenoMemInfo::Init() {
AdrenoMemInfo::AdrenoMemInfo() {
libadreno_utils_ = ::dlopen("libadreno_utils.so", RTLD_NOW);
if (libadreno_utils_) {
*reinterpret_cast<void **>(&LINK_adreno_compute_aligned_width_and_height) =
@ -74,7 +70,6 @@ bool AdrenoMemInfo::Init() {
::dlsym(libadreno_utils_, "get_gpu_pixel_alignment");
} else {
ALOGE(" Failed to load libadreno_utils.so");
return false;
}
// Check if the overriding property debug.gralloc.gfx_ubwc_disable
@ -91,8 +86,6 @@ bool AdrenoMemInfo::Init() {
(!strncasecmp(property, "true", PROPERTY_VALUE_MAX)))) {
map_fb_ = true;
}
return true;
}
AdrenoMemInfo::~AdrenoMemInfo() {
@ -170,6 +163,8 @@ void AdrenoMemInfo::AlignCompressedRGB(int width, int height, int format, unsign
width, height, format, 0, raster_mode, padding_threshold,
reinterpret_cast<int *>(aligned_w), reinterpret_cast<int *>(aligned_h), &bytesPerPixel);
} else {
*aligned_w = (unsigned int)ALIGN(width, 32);
*aligned_h = (unsigned int)ALIGN(height, 32);
ALOGW("%s: Warning!! compute_compressedfmt_aligned_width_and_height not found", __FUNCTION__);
}
}

View File

@ -71,8 +71,6 @@ typedef enum {
class AdrenoMemInfo {
public:
bool Init();
/*
* Function to compute aligned width and aligned height based on
* width, height, format and usage flags.
@ -123,6 +121,7 @@ class AdrenoMemInfo {
static AdrenoMemInfo *GetInstance();
private:
AdrenoMemInfo();
~AdrenoMemInfo();
// link(s)to adreno surface padding library.
int (*LINK_adreno_compute_padding)(int width, int bpp, int surface_tile_height,

View File

@ -49,13 +49,6 @@ BufferManager::BufferManager() : next_id_(0) {
map_fb_mem_ = true;
}
// Enable UBWC for framebuffer
if ((property_get("debug.gralloc.enable_fb_ubwc", property, NULL) > 0) &&
(!strncmp(property, "1", PROPERTY_VALUE_MAX) ||
(!strncasecmp(property, "true", PROPERTY_VALUE_MAX)))) {
ubwc_for_fb_ = true;
}
handles_map_.clear();
allocator_ = new Allocator();
allocator_->Init();
@ -199,7 +192,13 @@ void BufferManager::CreateSharedHandle(buffer_handle_t inbuffer, const BufferDes
gralloc1_error_t BufferManager::FreeBuffer(std::shared_ptr<Buffer> buf) {
auto hnd = buf->handle;
ALOGD_IF(DEBUG, "FreeBuffer handle:%p id: %" PRIu64, hnd, hnd->id);
ALOGD_IF(DEBUG, "FreeBuffer handle:%p", hnd);
if (private_handle_t::validate(hnd) != 0) {
ALOGE("FreeBuffer: Invalid handle: %p", hnd);
return GRALLOC1_ERROR_BAD_HANDLE;
}
if (allocator_->FreeBuffer(reinterpret_cast<void *>(hnd->base), hnd->size, hnd->offset,
hnd->fd, buf->ion_handle_main) != 0) {
return GRALLOC1_ERROR_BAD_HANDLE;
@ -279,19 +278,12 @@ gralloc1_error_t BufferManager::RetainBuffer(private_handle_t const *hnd) {
} else {
private_handle_t *handle = const_cast<private_handle_t *>(hnd);
err = ImportHandleLocked(handle);
if (err == GRALLOC1_ERROR_NONE) {
// TODO(user): See bug 35955598
if (hnd->flags & private_handle_t::PRIV_FLAGS_SECURE_BUFFER) {
return GRALLOC1_ERROR_NONE; // Don't map secure buffer
}
err = MapBuffer(hnd);
}
}
return err;
}
gralloc1_error_t BufferManager::ReleaseBuffer(private_handle_t const *hnd) {
ALOGD_IF(DEBUG, "Release buffer handle:%p id: %" PRIu64, hnd, hnd->id);
ALOGD_IF(DEBUG, "Release buffer handle:%p", hnd);
std::lock_guard<std::mutex> lock(buffer_lock_);
auto buf = GetBufferFromHandleLocked(hnd);
if (buf == nullptr) {
@ -329,16 +321,20 @@ gralloc1_error_t BufferManager::LockBuffer(const private_handle_t *hnd,
err = MapBuffer(hnd);
}
// Invalidate if CPU reads in software and there are non-CPU
// writers. No need to do this for the metadata buffer as it is
// only read/written in software.
// todo use handle here
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)) {
return GRALLOC1_ERROR_BAD_HANDLE;
// Invalidate if CPU reads in software and there are non-CPU
// writers. No need to do this for the metadata buffer as it is
// only read/written in software.
if ((cons_usage & (GRALLOC1_CONSUMER_USAGE_CPU_READ | GRALLOC1_CONSUMER_USAGE_CPU_READ_OFTEN))
&& (hnd->flags & private_handle_t::PRIV_FLAGS_NON_CPU_WRITER)) {
if (allocator_->CleanBuffer(reinterpret_cast<void *>(hnd->base), hnd->size, hnd->offset,
buf->ion_handle_main, CACHE_INVALIDATE)) {
return GRALLOC1_ERROR_BAD_HANDLE;
}
}
}
@ -482,14 +478,14 @@ int BufferManager::AllocateBuffer(const BufferDescriptor &descriptor, buffer_han
BufferInfo info = GetBufferInfo(descriptor);
GetBufferSizeAndDimensions(info, &size, &alignedw, &alignedh);
size = (bufferSize >= size) ? bufferSize : size;
size = size * layer_count;
int err = 0;
int flags = 0;
auto page_size = UINT(getpagesize());
AllocData data;
data.align = GetDataAlignment(format, prod_usage, cons_usage);
data.size = ALIGN(size, data.align);
size = ALIGN(size, data.align) * layer_count;
data.size = size;
data.handle = (uintptr_t) handle;
data.uncached = allocator_->UseUncached(prod_usage, cons_usage);
@ -526,7 +522,7 @@ int BufferManager::AllocateBuffer(const BufferDescriptor &descriptor, buffer_han
descriptor.GetHeight(),
format,
buffer_type,
size,
data.size,
prod_usage,
cons_usage);
@ -558,6 +554,10 @@ gralloc1_error_t BufferManager::Perform(int operation, va_list args) {
int format = va_arg(args, int);
native_handle_t **handle = va_arg(args, native_handle_t **);
if (!handle) {
return GRALLOC1_ERROR_BAD_HANDLE;
}
private_handle_t *hnd = reinterpret_cast<private_handle_t *>(
native_handle_create(private_handle_t::kNumFds, private_handle_t::NumInts()));
if (hnd) {
@ -567,7 +567,7 @@ gralloc1_error_t BufferManager::Perform(int operation, va_list args) {
hnd->flags = private_handle_t::PRIV_FLAGS_USES_ION;
hnd->size = size;
hnd->offset = offset;
hnd->base = uint64_t(base) + offset;
hnd->base = uint64_t(base);
hnd->gpuaddr = 0;
BufferInfo info(width, height, format);
GetAlignedWidthAndHeight(info, &alignedw, &alignedh);
@ -585,6 +585,11 @@ gralloc1_error_t BufferManager::Perform(int operation, va_list args) {
int format = va_arg(args, int);
int *stride = va_arg(args, int *);
unsigned int alignedw = 0, alignedh = 0;
if (!stride) {
return GRALLOC1_ERROR_BAD_VALUE;
}
BufferInfo info(width, width, format);
GetAlignedWidthAndHeight(info, &alignedw, &alignedh);
*stride = INT(alignedw);
@ -597,6 +602,10 @@ gralloc1_error_t BufferManager::Perform(int operation, va_list args) {
return GRALLOC1_ERROR_BAD_HANDLE;
}
if (!stride) {
return GRALLOC1_ERROR_BAD_VALUE;
}
BufferDim_t buffer_dim;
if (getMetaData(hnd, GET_BUFFER_GEOMETRY, &buffer_dim) == 0) {
*stride = buffer_dim.sliceWidth;
@ -614,6 +623,10 @@ gralloc1_error_t BufferManager::Perform(int operation, va_list args) {
return GRALLOC1_ERROR_BAD_HANDLE;
}
if (!stride || !height) {
return GRALLOC1_ERROR_BAD_VALUE;
}
BufferDim_t buffer_dim;
if (getMetaData(hnd, GET_BUFFER_GEOMETRY, &buffer_dim) == 0) {
*stride = buffer_dim.sliceWidth;
@ -638,6 +651,10 @@ gralloc1_error_t BufferManager::Perform(int operation, va_list args) {
int *aligned_width = va_arg(args, int *);
int *aligned_height = va_arg(args, int *);
int *tile_enabled = va_arg(args, int *);
if (!aligned_width || !aligned_height || !tile_enabled) {
return GRALLOC1_ERROR_BAD_VALUE;
}
unsigned int alignedw, alignedh;
BufferInfo info(width, height, format, prod_usage, cons_usage);
*tile_enabled = IsUBwcEnabled(format, prod_usage, cons_usage);
@ -649,9 +666,15 @@ gralloc1_error_t BufferManager::Perform(int operation, va_list args) {
case GRALLOC_MODULE_PERFORM_GET_COLOR_SPACE_FROM_HANDLE: {
private_handle_t *hnd = va_arg(args, private_handle_t *);
int *color_space = va_arg(args, int *);
if (private_handle_t::validate(hnd) != 0) {
return GRALLOC1_ERROR_BAD_HANDLE;
}
if (!color_space) {
return GRALLOC1_ERROR_BAD_VALUE;
}
*color_space = 0;
#ifdef USE_COLOR_METADATA
ColorMetaData color_metadata;
@ -683,6 +706,11 @@ gralloc1_error_t BufferManager::Perform(int operation, va_list args) {
if (private_handle_t::validate(hnd) != 0) {
return GRALLOC1_ERROR_BAD_HANDLE;
}
if (!ycbcr) {
return GRALLOC1_ERROR_BAD_VALUE;
}
if (GetYUVPlaneInfo(hnd, ycbcr)) {
return GRALLOC1_ERROR_UNDEFINED;
}
@ -691,10 +719,15 @@ gralloc1_error_t BufferManager::Perform(int operation, va_list args) {
case GRALLOC_MODULE_PERFORM_GET_MAP_SECURE_BUFFER_INFO: {
private_handle_t *hnd = va_arg(args, private_handle_t *);
int *map_secure_buffer = va_arg(args, int *);
if (private_handle_t::validate(hnd) != 0) {
return GRALLOC1_ERROR_BAD_HANDLE;
}
if (!map_secure_buffer) {
return GRALLOC1_ERROR_BAD_VALUE;
}
if (getMetaData(hnd, GET_MAP_SECURE_BUFFER, map_secure_buffer) == 0) {
*map_secure_buffer = 0;
}
@ -703,9 +736,15 @@ gralloc1_error_t BufferManager::Perform(int operation, va_list args) {
case GRALLOC_MODULE_PERFORM_GET_UBWC_FLAG: {
private_handle_t *hnd = va_arg(args, private_handle_t *);
int *flag = va_arg(args, int *);
if (private_handle_t::validate(hnd) != 0) {
return GRALLOC1_ERROR_BAD_HANDLE;
}
if (!flag) {
return GRALLOC1_ERROR_BAD_VALUE;
}
*flag = hnd->flags &private_handle_t::PRIV_FLAGS_UBWC_ALIGNED;
int linear_format = 0;
if (getMetaData(hnd, GET_LINEAR_FORMAT, &linear_format) == 0) {
@ -718,9 +757,15 @@ gralloc1_error_t BufferManager::Perform(int operation, va_list args) {
case GRALLOC_MODULE_PERFORM_GET_RGB_DATA_ADDRESS: {
private_handle_t *hnd = va_arg(args, private_handle_t *);
void **rgb_data = va_arg(args, void **);
if (private_handle_t::validate(hnd) != 0) {
return GRALLOC1_ERROR_BAD_HANDLE;
}
if (!rgb_data) {
return GRALLOC1_ERROR_BAD_VALUE;
}
if (GetRgbDataAddress(hnd, rgb_data)) {
return GRALLOC1_ERROR_UNDEFINED;
}
@ -737,6 +782,11 @@ gralloc1_error_t BufferManager::Perform(int operation, va_list args) {
uint32_t *aligned_width = va_arg(args, uint32_t *);
uint32_t *aligned_height = va_arg(args, uint32_t *);
uint32_t *size = va_arg(args, uint32_t *);
if (!aligned_width || !aligned_height || !size) {
return GRALLOC1_ERROR_BAD_VALUE;
}
auto info = BufferInfo(width, height, format, producer_usage, consumer_usage);
GetBufferSizeAndDimensions(info, size, aligned_width, aligned_height);
// Align size
@ -744,9 +794,8 @@ gralloc1_error_t BufferManager::Perform(int operation, va_list args) {
*size = ALIGN(*size, align);
} break;
// TODO(user): Break out similar functionality, preferably moving to a common lib.
case GRALLOC1_MODULE_PERFORM_ALLOCATE_BUFFER: {
std::lock_guard<std::mutex> lock(buffer_lock_);
int width = va_arg(args, int);
int height = va_arg(args, int);
int format = va_arg(args, int);
@ -765,9 +814,15 @@ gralloc1_error_t BufferManager::Perform(int operation, va_list args) {
case GRALLOC1_MODULE_PERFORM_GET_INTERLACE_FLAG: {
private_handle_t *hnd = va_arg(args, private_handle_t *);
int *flag = va_arg(args, int *);
if (private_handle_t::validate(hnd) != 0) {
return GRALLOC1_ERROR_BAD_HANDLE;
}
if (!flag) {
return GRALLOC1_ERROR_BAD_VALUE;
}
if (getMetaData(hnd, GET_PP_PARAM_INTERLACED, flag) != 0) {
*flag = 0;
}

View File

@ -118,7 +118,6 @@ class BufferManager {
std::shared_ptr<Buffer> GetBufferFromHandleLocked(const private_handle_t *hnd);
bool map_fb_mem_ = false;
bool ubwc_for_fb_ = false;
Allocator *allocator_ = NULL;
std::mutex buffer_lock_;
std::mutex descriptor_lock_;

View File

@ -344,6 +344,10 @@ gralloc1_error_t GrallocImpl::GetLayerCount(gralloc1_device_t *device, buffer_ha
gralloc1_error_t GrallocImpl::GetProducerUsage(gralloc1_device_t *device, buffer_handle_t buffer,
gralloc1_producer_usage_t *outUsage) {
if (!outUsage) {
return GRALLOC1_ERROR_BAD_VALUE;
}
gralloc1_error_t status = CheckDeviceAndHandle(device, buffer);
if (status == GRALLOC1_ERROR_NONE) {
const private_handle_t *hnd = PRIV_HANDLE_CONST(buffer);
@ -355,6 +359,10 @@ gralloc1_error_t GrallocImpl::GetProducerUsage(gralloc1_device_t *device, buffer
gralloc1_error_t GrallocImpl::GetBufferStride(gralloc1_device_t *device, buffer_handle_t buffer,
uint32_t *outStride) {
if (!outStride) {
return GRALLOC1_ERROR_BAD_VALUE;
}
gralloc1_error_t status = CheckDeviceAndHandle(device, buffer);
if (status == GRALLOC1_ERROR_NONE) {
*outStride = UINT(PRIV_HANDLE_CONST(buffer)->GetStride());
@ -370,6 +378,10 @@ gralloc1_error_t GrallocImpl::AllocateBuffers(gralloc1_device_t *device, uint32_
return GRALLOC1_ERROR_BAD_DESCRIPTOR;
}
if (!device) {
return GRALLOC1_ERROR_BAD_VALUE;
}
GrallocImpl const *dev = GRALLOC_IMPL(device);
gralloc1_error_t status = dev->buf_mgr_->AllocateBuffers(num_descriptors, descriptors,
out_buffers);
@ -389,18 +401,21 @@ gralloc1_error_t GrallocImpl::RetainBuffer(gralloc1_device_t *device, buffer_han
}
gralloc1_error_t GrallocImpl::ReleaseBuffer(gralloc1_device_t *device, buffer_handle_t buffer) {
gralloc1_error_t status = CheckDeviceAndHandle(device, buffer);
if (status == GRALLOC1_ERROR_NONE) {
const private_handle_t *hnd = PRIV_HANDLE_CONST(buffer);
GrallocImpl const *dev = GRALLOC_IMPL(device);
status = dev->buf_mgr_->ReleaseBuffer(hnd);
if (!device || !buffer) {
return GRALLOC1_ERROR_BAD_DESCRIPTOR;
}
return status;
const private_handle_t *hnd = PRIV_HANDLE_CONST(buffer);
GrallocImpl const *dev = GRALLOC_IMPL(device);
return dev->buf_mgr_->ReleaseBuffer(hnd);
}
gralloc1_error_t GrallocImpl::GetNumFlexPlanes(gralloc1_device_t *device, buffer_handle_t buffer,
uint32_t *out_num_planes) {
if (!out_num_planes) {
return GRALLOC1_ERROR_BAD_VALUE;
}
gralloc1_error_t status = CheckDeviceAndHandle(device, buffer);
if (status == GRALLOC1_ERROR_NONE) {
GrallocImpl const *dev = GRALLOC_IMPL(device);
@ -422,7 +437,8 @@ gralloc1_error_t GrallocImpl::LockBuffer(gralloc1_device_t *device, buffer_handl
const gralloc1_rect_t *region, void **out_data,
int32_t acquire_fence) {
gralloc1_error_t status = CheckDeviceAndHandle(device, buffer);
if (status != GRALLOC1_ERROR_NONE) {
if (status != GRALLOC1_ERROR_NONE || !out_data ||
!region) { // currently we ignore the region/rect client wants to lock
CloseFdIfValid(acquire_fence);
return status;
}
@ -447,13 +463,8 @@ gralloc1_error_t GrallocImpl::LockBuffer(gralloc1_device_t *device, buffer_handl
// return GRALLOC1_ERROR_BAD_VALUE;
}
// currently we ignore the region/rect client wants to lock
if (region == NULL) {
return GRALLOC1_ERROR_BAD_VALUE;
}
// TODO(user): Need to check if buffer was allocated with the same flags
status = dev->buf_mgr_->LockBuffer(hnd, prod_usage, cons_usage);
*out_data = reinterpret_cast<void *>(hnd->base);
return status;
@ -465,7 +476,12 @@ gralloc1_error_t GrallocImpl::LockFlex(gralloc1_device_t *device, buffer_handle_
const gralloc1_rect_t *region,
struct android_flex_layout *out_flex_layout,
int32_t acquire_fence) {
void *out_data;
if (!out_flex_layout) {
CloseFdIfValid(acquire_fence);
return GRALLOC1_ERROR_BAD_VALUE;
}
void *out_data {};
gralloc1_error_t status = GrallocImpl::LockBuffer(device, buffer, prod_usage, cons_usage, region,
&out_data, acquire_fence);
if (status != GRALLOC1_ERROR_NONE) {
@ -481,11 +497,14 @@ gralloc1_error_t GrallocImpl::LockFlex(gralloc1_device_t *device, buffer_handle_
gralloc1_error_t GrallocImpl::UnlockBuffer(gralloc1_device_t *device, buffer_handle_t buffer,
int32_t *release_fence) {
gralloc1_error_t status = CheckDeviceAndHandle(device, buffer);
if (status != GRALLOC1_ERROR_NONE) {
return status;
}
if (!release_fence) {
return GRALLOC1_ERROR_BAD_VALUE;
}
const private_handle_t *hnd = PRIV_HANDLE_CONST(buffer);
GrallocImpl const *dev = GRALLOC_IMPL(device);
@ -495,6 +514,10 @@ gralloc1_error_t GrallocImpl::UnlockBuffer(gralloc1_device_t *device, buffer_han
}
gralloc1_error_t GrallocImpl::Gralloc1Perform(gralloc1_device_t *device, int operation, ...) {
if (!device) {
return GRALLOC1_ERROR_BAD_VALUE;
}
va_list args;
va_start(args, operation);
GrallocImpl const *dev = GRALLOC_IMPL(device);

View File

@ -61,7 +61,7 @@ inline int roundUpToPageSize(int x) {
#define GRALLOC1_CONSUMER_USAGE_PRIVATE_WFD 0x00200000
/* This flag is used for SECURE display usecase */
#define GRALLOC1_CONSUMER_USAGE_PRIVATE_SECURE_DISPLAY 0x00800000
#define GRALLOC1_CONSUMER_USAGE_PRIVATE_SECURE_DISPLAY 0x01000000
/* Buffer content should be displayed on a primary display only */
#define GRALLOC1_CONSUMER_USAGE_PRIVATE_INTERNAL_ONLY 0x04000000
@ -77,6 +77,7 @@ inline int roundUpToPageSize(int x) {
#define GRALLOC_USAGE_PRIVATE_IOMMU_HEAP GRALLOC1_PRODUCER_USAGE_PRIVATE_IOMMU_HEAP
#define GRALLOC_USAGE_PRIVATE_WFD GRALLOC1_CONSUMER_USAGE_PRIVATE_WFD
#define GRALLOC_USAGE_PRIVATE_CAMERA_HEAP GRALLOC1_PRODUCER_USAGE_PRIVATE_CAMERA_HEAP
#define GRALLOC_USAGE_PRIVATE_SECURE_DISPLAY GRALLOC1_CONSUMER_USAGE_PRIVATE_SECURE_DISPLAY
#define GRALLOC_USAGE_PRIVATE_MM_HEAP 0x0

View File

@ -361,8 +361,14 @@ static int open_lights(const struct hw_module_t* module, char const* name,
set_light = set_light_battery;
else if (0 == strcmp(LIGHT_ID_NOTIFICATIONS, name))
set_light = set_light_notifications;
else if (0 == strcmp(LIGHT_ID_BUTTONS, name))
set_light = set_light_buttons;
else if (0 == strcmp(LIGHT_ID_BUTTONS, name)) {
if (!access(BUTTON_FILE, F_OK)) {
// enable light button when the file is present
set_light = set_light_buttons;
} else {
return -EINVAL;
}
}
else if (0 == strcmp(LIGHT_ID_ATTENTION, name))
set_light = set_light_attention;
else

View File

@ -8,6 +8,7 @@ LOCAL_MODULE_TAGS := optional
LOCAL_SHARED_LIBRARIES := $(common_libs) libbinder libqservice
LOCAL_C_INCLUDES := $(common_includes) $(kernel_includes)
LOCAL_HEADER_LIBRARIES := display_headers
LOCAL_HEADER_LIBRARIES += libhardware_headers
LOCAL_CFLAGS := $(common_flags) -DLOG_TAG=\"qdutils\" -Wno-sign-conversion
LOCAL_ADDITIONAL_DEPENDENCIES := $(common_deps)
LOCAL_COPY_HEADERS_TO := $(common_header_export_path)

View File

@ -57,9 +57,9 @@ static int getExternalNode(const char *type) {
char msmFbTypePath[MAX_FRAME_BUFFER_NAME_SIZE];
int j = 0;
for(j = 0; j < HWC_NUM_DISPLAY_TYPES; j++) {
for(j = 0; j < kFBNodeMax; j++) {
snprintf (msmFbTypePath, sizeof(msmFbTypePath),
"/sys/class/graphics/fb%d/msm_fb_type", j);
"/sys/devices/virtual/graphics/fb%d/msm_fb_type", j);
displayDeviceFP = fopen(msmFbTypePath, "r");
if(displayDeviceFP) {
fread(fbType, sizeof(char), MAX_FRAME_BUFFER_NAME_SIZE,
@ -71,11 +71,11 @@ static int getExternalNode(const char *type) {
}
fclose(displayDeviceFP);
} else {
ALOGE("%s: Failed to open fb node %d", __func__, j);
ALOGE("%s: Failed to open fb node %s", __func__, msmFbTypePath);
}
}
if (j < HWC_NUM_DISPLAY_TYPES)
if (j < kFBNodeMax)
return j;
else
ALOGE("%s: Failed to find %s node", __func__, type);
@ -186,12 +186,12 @@ int getEdidRawData(char *buffer)
}
snprintf(msmFbTypePath, sizeof(msmFbTypePath),
"/sys/class/graphics/fb%d/edid_raw_data", node_id);
"/sys/devices/virtual/graphics/fb%d/edid_raw_data", node_id);
edidFile = open(msmFbTypePath, O_RDONLY, 0);
if (edidFile < 0) {
ALOGE("%s no edid raw data found", __func__);
ALOGE("%s no edid raw data found %s", __func__,msmFbTypePath);
return 0;
}
@ -214,11 +214,11 @@ bool isDPConnected() {
}
snprintf(connectPath, sizeof(connectPath),
"/sys/class/graphics/fb%d/connected", nodeId);
"/sys/devices/virtual/graphics/fb%d/connected", nodeId);
connectFile = fopen(connectPath, "rb");
if (!connectFile) {
ALOGW("Failed to open connect node for device node %d", nodeId);
ALOGW("Failed to open connect node for device node %s", connectPath);
return false;
}
@ -253,11 +253,11 @@ int getDPTestConfig(uint32_t *panelBpp, uint32_t *patternType) {
}
snprintf(configPath, sizeof(configPath),
"/sys/class/graphics/fb%d/config", nodeId);
"/sys/devices/virtual/graphics/fb%d/config", nodeId);
configFile = fopen(configPath, "rb");
if (!configFile) {
ALOGW("Failed to open config node for device node %d", nodeId);
ALOGW("Failed to open config node for device node %s", configPath);
return -EINVAL;
}

View File

@ -70,6 +70,6 @@ enum class DriverType {
};
DriverType getDriverType();
const char *GetHALPixelFormatString(int format);
static const int kFBNodeMax = 4;
}; //namespace qdutils
#endif

View File

@ -664,6 +664,20 @@ class DisplayInterface {
*/
virtual DisplayError SetCompositionState(LayerComposition composition_type, bool enable) = 0;
/*! @brief Method to check whether a client target with the given properties
can be supported/handled by hardware.
@param[in] width client target width
@param[in] height client target height
@param[in] format client target format
@param[in] colorMetaData client target colorMetaData
@return \link DisplayError \endlink
*/
virtual DisplayError GetClientTargetSupport(uint32_t width, uint32_t height,
LayerBufferFormat format,
const ColorMetaData &color_metadata) = 0;
protected:
virtual ~DisplayInterface() { }
};

View File

@ -59,6 +59,7 @@ enum PendingAction {
kDisableFrameCapture = BITMAP(7),
kConfigureDetailedEnhancer = BITMAP(8),
kInvalidatingAndkSetPanelBrightness = BITMAP(9),
kModeSet = BITMAP(10),
kGetDetailedEnhancerData = BITMAP(21),
kNoAction = BITMAP(31),
};
@ -119,11 +120,12 @@ enum PPGlobalColorFeatureID {
kGlobalColorFeatureDither,
kGlobalColorFeatureGamut,
kGlobalColorFeaturePADither,
kGlobalColorFeatureCsc,
kMaxNumPPFeatures,
};
struct PPPendingParams {
PendingAction action = kNoAction;
int32_t action = kNoAction;
void *params = NULL;
};
@ -331,6 +333,21 @@ struct SDEPccCfg {
SDEPccCfg *GetConfig() { return this; }
};
struct SDECscCfg {
static const uint32_t kCscMVSize = 9;
static const uint32_t kCscBVSize = 3;
static const uint32_t kCscLVSize = 6;
uint32_t flags;
uint32_t csc_mv[kCscMVSize];
uint32_t csc_pre_bv[kCscBVSize];
uint32_t csc_post_bv[kCscBVSize];
uint32_t csc_pre_lv[kCscLVSize];
uint32_t csc_post_lv[kCscLVSize];
static SDECscCfg *Init(uint32_t arg __attribute__((__unused__)));
SDECscCfg *GetConfig() { return this; }
};
struct SDEDitherCfg {
uint32_t g_y_depth;
uint32_t r_cr_depth;

View File

@ -162,6 +162,7 @@ struct HWResourceInfo {
uint32_t num_smp_per_pipe = 0;
uint32_t max_scale_up = 1;
uint32_t max_scale_down = 1;
float rot_downscale_max = 0.0f;
uint64_t max_bandwidth_low = 0;
uint64_t max_bandwidth_high = 0;
uint32_t max_mixer_width = 2048;

View File

@ -226,6 +226,8 @@ void CompManager::PrepareStrategyConstraints(Handle comp_handle, HWLayers *hw_la
DisplayCompositionContext *display_comp_ctx =
reinterpret_cast<DisplayCompositionContext *>(comp_handle);
StrategyConstraints *constraints = &display_comp_ctx->constraints;
bool low_end_hw = ((hw_res_info_.num_vig_pipe + hw_res_info_.num_rgb_pipe +
hw_res_info_.num_dma_pipe) <= kSafeModeThreshold);
constraints->safe_mode = safe_mode_;
constraints->use_cursor = false;
@ -234,10 +236,25 @@ void CompManager::PrepareStrategyConstraints(Handle comp_handle, HWLayers *hw_la
// Limit 2 layer SDE Comp if its not a Primary Display.
// Safe mode is the policy for External display on a low end device.
if (!display_comp_ctx->is_primary_panel) {
bool low_end_hw = ((hw_res_info_.num_vig_pipe + hw_res_info_.num_rgb_pipe +
hw_res_info_.num_dma_pipe) <= kSafeModeThreshold);
constraints->max_layers = max_sde_ext_layers_;
constraints->safe_mode = (low_end_hw && !hw_res_info_.separate_rotator) ? true : safe_mode_;
if(hw_layers->info.stack->flags.secure_present)
secure_external_layer_ = true;
else
secure_external_layer_ = false;
}
// When Secure layer is present on external, GPU composition should be policy
// for Primary on low end devices
if(display_comp_ctx->is_primary_panel && (registered_displays_.count() > 1)
&& low_end_hw && secure_external_layer_) {
DLOGV_IF(kTagCompManager,"Secure layer present for LET. Fallingback to GPU");
hw_layers->info.stack->flags.skip_present = 1;
for(auto &layer : hw_layers->info.stack->layers) {
if(layer->composition != kCompositionGPUTarget) {
layer->flags.skip = 1;
}
}
}
// If a strategy fails after successfully allocating resources, then set safe mode

View File

@ -112,6 +112,7 @@ class CompManager : public DumpImpl {
bool safe_mode_ = false; // Flag to notify all displays to be in resource crunch
// mode, where strategy manager chooses the best strategy
// that uses optimal number of pipes for each display
bool secure_external_layer_ = false;
HWResourceInfo hw_res_info_;
BufferAllocator *buffer_allocator_ = NULL;
ExtensionInterface *extension_intf_ = NULL;

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2014 - 2016, The Linux Foundation. All rights reserved.
* Copyright (c) 2014 - 2017, The Linux Foundation. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification, are permitted
* provided that the following conditions are met:
@ -73,6 +73,9 @@ DisplayError CoreImpl::Init() {
goto CleanupOnError;
}
if (hw_info_intf_ == NULL) {
return kErrorResources;
}
error = hw_info_intf_->GetHWResourceInfo(&hw_resource_);
if (error != kErrorNone) {
goto CleanupOnError;

View File

@ -298,10 +298,9 @@ DisplayError DisplayBase::Commit(LayerStack *layer_stack) {
CommitLayerParams(layer_stack);
if (comp_manager_->Commit(display_comp_ctx_, &hw_layers_)) {
if (error != kErrorNone) {
return error;
}
error = comp_manager_->Commit(display_comp_ctx_, &hw_layers_);
if (error != kErrorNone) {
return error;
}
// check if feature list cache is dirty and pending.
@ -1430,4 +1429,94 @@ DisplayError DisplayBase::HandleHDR(LayerStack *layer_stack) {
return error;
}
DisplayError DisplayBase::GetClientTargetSupport(uint32_t width, uint32_t height,
LayerBufferFormat format,
const ColorMetaData &color_metadata) {
if (format != kFormatRGBA8888 && format != kFormatRGBA1010102) {
DLOGW("Unsupported format = %d", format);
return kErrorNotSupported;
} else if (ValidateScaling(width, height) != kErrorNone) {
DLOGW("Unsupported width = %d height = %d", width, height);
return kErrorNotSupported;
} else if (color_metadata.transfer && color_metadata.colorPrimaries) {
DisplayError error = ValidateDataspace(color_metadata);
if (error != kErrorNone) {
DLOGW("Unsupported Transfer Request = %d Color Primary = %d",
color_metadata.transfer, color_metadata.colorPrimaries);
return error;
}
// Check for BT2020 support
if (color_metadata.colorPrimaries == ColorPrimaries_BT2020) {
DLOGW("Unsupported Color Primary = %d", color_metadata.colorPrimaries);
return kErrorNotSupported;
}
}
return kErrorNone;
}
DisplayError DisplayBase::ValidateScaling(uint32_t width, uint32_t height) {
uint32_t display_width = display_attributes_.x_pixels;
uint32_t display_height = display_attributes_.y_pixels;
HWResourceInfo hw_resource_info = HWResourceInfo();
hw_info_intf_->GetHWResourceInfo(&hw_resource_info);
float max_scale_down = FLOAT(hw_resource_info.max_scale_down);
float max_scale_up = FLOAT(hw_resource_info.max_scale_up);
float scale_x = FLOAT(width / display_width);
float scale_y = FLOAT(height / display_height);
if (scale_x > max_scale_down || scale_y > max_scale_down) {
return kErrorNotSupported;
}
if (UINT32(scale_x) < 1 && scale_x > 0.0f) {
if ((1.0f / scale_x) > max_scale_up) {
return kErrorNotSupported;
}
}
if (UINT32(scale_y) < 1 && scale_y > 0.0f) {
if ((1.0f / scale_y) > max_scale_up) {
return kErrorNotSupported;
}
}
return kErrorNone;
}
DisplayError DisplayBase::ValidateDataspace(const ColorMetaData &color_metadata) {
// Handle transfer
switch (color_metadata.transfer) {
case Transfer_sRGB:
case Transfer_SMPTE_170M:
case Transfer_SMPTE_ST2084:
case Transfer_HLG:
case Transfer_Linear:
case Transfer_Gamma2_2:
break;
default:
DLOGW("Unsupported Transfer Request = %d", color_metadata.transfer);
return kErrorNotSupported;
}
// Handle colorPrimaries
switch (color_metadata.colorPrimaries) {
case ColorPrimaries_BT709_5:
case ColorPrimaries_BT601_6_525:
case ColorPrimaries_BT601_6_625:
case ColorPrimaries_DCIP3:
case ColorPrimaries_BT2020:
break;
default:
DLOGW("Unsupported Color Primary = %d", color_metadata.colorPrimaries);
return kErrorNotSupported;
}
return kErrorNone;
}
} // namespace sdm

View File

@ -114,6 +114,9 @@ class DisplayBase : public DisplayInterface, DumpImpl {
virtual DisplayError GetDisplayPort(DisplayPort *port);
virtual bool IsPrimaryDisplay();
virtual DisplayError SetCompositionState(LayerComposition composition_type, bool enable);
virtual DisplayError GetClientTargetSupport(uint32_t width, uint32_t height,
LayerBufferFormat format,
const ColorMetaData &color_metadata);
protected:
DisplayError BuildLayerStackStats(LayerStack *layer_stack);
@ -121,6 +124,8 @@ class DisplayBase : public DisplayInterface, DumpImpl {
void CommitLayerParams(LayerStack *layer_stack);
void PostCommitLayerParams(LayerStack *layer_stack);
DisplayError HandleHDR(LayerStack *layer_stack);
DisplayError ValidateScaling(uint32_t width, uint32_t height);
DisplayError ValidateDataspace(const ColorMetaData &color_metadata);
// DumpImpl method
void AppendDump(char *buffer, uint32_t length);

View File

@ -303,14 +303,19 @@ HWDeviceDRM::HWDeviceDRM(BufferSyncHandler *buffer_sync_handler, BufferAllocator
}
DisplayError HWDeviceDRM::Init() {
default_mode_ = (DRMLibLoader::GetInstance()->IsLoaded() == false);
DRMLibLoader *drm_lib = DRMLibLoader::GetInstance();
if (drm_lib == nullptr) {
DLOGE("Failed to load DRM Lib");
return kErrorResources;
}
default_mode_ = (drm_lib->IsLoaded() == false);
if (!default_mode_) {
DRMMaster *drm_master = {};
int dev_fd = -1;
DRMMaster::GetInstance(&drm_master);
drm_master->GetHandle(&dev_fd);
DRMLibLoader::GetInstance()->FuncGetDRMManager()(dev_fd, &drm_mgr_intf_);
drm_lib->FuncGetDRMManager()(dev_fd, &drm_mgr_intf_);
if (drm_mgr_intf_->RegisterDisplay(DRMDisplayType::PERIPHERAL, &token_)) {
DLOGE("RegisterDisplay failed");
return kErrorResources;

View File

@ -105,7 +105,12 @@ HWResourceInfo *HWInfoDRM::hw_resource_ = nullptr;
HWInfoDRM::HWInfoDRM() {
DRMLogger::Set(new DRMLoggerImpl());
default_mode_ = (DRMLibLoader::GetInstance()->IsLoaded() == false);
drm_lib = DRMLibLoader::GetInstance();
if (drm_lib == nullptr) {
DLOGE("Failed to load DRM Library");
return;
}
default_mode_ = (drm_lib->IsLoaded() == false);
if (!default_mode_) {
DRMMaster *drm_master = {};
int dev_fd = -1;
@ -115,20 +120,25 @@ HWInfoDRM::HWInfoDRM() {
return;
}
drm_master->GetHandle(&dev_fd);
DRMLibLoader::GetInstance()->FuncGetDRMManager()(dev_fd, &drm_mgr_intf_);
drm_lib->FuncGetDRMManager()(dev_fd, &drm_mgr_intf_);
}
}
HWInfoDRM::~HWInfoDRM() {
delete hw_resource_;
hw_resource_ = nullptr;
if (hw_resource_ != nullptr) {
delete hw_resource_;
hw_resource_ = nullptr;
}
if (drm_mgr_intf_) {
DRMLibLoader::GetInstance()->FuncDestroyDRMManager()();
if (drm_lib != nullptr) {
drm_lib->FuncDestroyDRMManager()();
}
drm_mgr_intf_ = nullptr;
}
DRMLibLoader::Destroy();
drm_lib->Destroy();
drm_lib = nullptr;
DRMMaster::DestroyInstance();
}

View File

@ -36,6 +36,7 @@
#include <private/hw_info_types.h>
#include <bitset>
#include <vector>
#include <drm_lib_loader.h>
#include "hw_info_interface.h"
@ -72,6 +73,8 @@ class HWInfoDRM: public HWInfoInterface {
static const int kHWMdssVersion5 = 500; // MDSS_V5
static const int kMaxStringLength = 1024;
static HWResourceInfo *hw_resource_;
drm_utils::DRMLibLoader *drm_lib = nullptr;
};
} // namespace sdm

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2015-2016, The Linux Foundation. All rights reserved.
* Copyright (c) 2015-2017, The Linux Foundation. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
@ -53,6 +53,7 @@ DisplayError (*HWColorManager::SetFeature[])(const PPFeatureInfo &, msmfb_mdp_pp
[kGlobalColorFeatureDither] = &HWColorManager::SetDither,
[kGlobalColorFeatureGamut] = &HWColorManager::SetGamut,
[kGlobalColorFeaturePADither] = &HWColorManager::SetPADither,
[kGlobalColorFeatureCsc] = &HWColorManager::SetCSCLegacy,
};
DisplayError HWColorManager::SetPCC(const PPFeatureInfo &feature, msmfb_mdp_pp *kernel_params) {
@ -163,4 +164,25 @@ DisplayError HWColorManager::SetPADither(const PPFeatureInfo &feature,
return ret;
}
DisplayError HWColorManager::SetCSCLegacy(const PPFeatureInfo &feature, msmfb_mdp_pp *kernel_params) {
DisplayError ret = kErrorNone;
kernel_params->op = mdp_op_csc_cfg;
kernel_params->data.csc_cfg_data.block = MDP_BLOCK_DMA_P;
std::memcpy(&kernel_params->data.csc_cfg_data.csc_data, feature.GetConfigData(),
sizeof(mdp_csc_cfg));
for( int row = 0; row < 3; row++) {
DLOGV_IF(kTagQDCM, "kernel mv[%d][0]=0x%x mv[%d][1]=0x%x mv[%d][2]=0x%x\n",
row, kernel_params->data.csc_cfg_data.csc_data.csc_mv[row*3 + 0],
row, kernel_params->data.csc_cfg_data.csc_data.csc_mv[row*3 + 1],
row, kernel_params->data.csc_cfg_data.csc_data.csc_mv[row*3 + 2]);
DLOGV_IF(kTagQDCM, "kernel pre_bv[%d]=%x\n", row,
kernel_params->data.csc_cfg_data.csc_data.csc_pre_bv[row]);
DLOGV_IF(kTagQDCM, "kernel post_bv[%d]=%x\n", row,
kernel_params->data.csc_cfg_data.csc_data.csc_post_bv[row]);
}
return ret;
}
} // namespace sdm

View File

@ -1,4 +1,4 @@
/* Copyright (c) 2015-2016, The Linux Foundataion. All rights reserved.
/* Copyright (c) 2015-2017, The Linux Foundataion. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
@ -47,7 +47,7 @@ class HWColorManager {
static DisplayError SetDither(const PPFeatureInfo &feature, msmfb_mdp_pp *kernel_params);
static DisplayError SetGamut(const PPFeatureInfo &feature, msmfb_mdp_pp *kernel_params);
static DisplayError SetPADither(const PPFeatureInfo &feature, msmfb_mdp_pp *kernel_params);
static DisplayError SetCSCLegacy(const PPFeatureInfo &feature, msmfb_mdp_pp *kernel_params);
static DisplayError (*SetFeature[kMaxNumPPFeatures])(const PPFeatureInfo &feature,
msmfb_mdp_pp *kernel_params);

View File

@ -46,6 +46,8 @@
#define __CLASS__ "HWHDMI"
#define MIN_HDR_RESET_WAITTIME_SEC 2
namespace sdm {
#ifdef MDP_HDR_STREAM
@ -196,6 +198,10 @@ HWHDMI::HWHDMI(BufferSyncHandler *buffer_sync_handler, HWInfoInterface *hw_info
HWDevice::device_type_ = kDeviceHDMI;
HWDevice::device_name_ = "HDMI Display Device";
HWDevice::hw_info_intf_ = hw_info_intf;
(void)hdr_reset_start_;
(void)hdr_reset_end_;
(void)reset_hdr_flag_;
(void)cdm_color_space_;
}
DisplayError HWHDMI::Init() {
@ -443,8 +449,19 @@ DisplayError HWHDMI::Commit(HWLayers *hw_layers) {
if (error != kErrorNone) {
return error;
}
if (cdm_color_space_commit_) {
#ifdef MDP_COMMIT_UPDATE_CDM_COLOR_SPACE
mdp_layer_commit_v1 &mdp_commit = mdp_disp_commit_.commit_v1;
mdp_commit.cdm_color_space = cdm_color_space_;
mdp_commit.flags |= MDP_COMMIT_UPDATE_CDM_COLOR_SPACE;
#endif
}
return HWDevice::Commit(hw_layers);
error = HWDevice::Commit(hw_layers);
if (cdm_color_space_commit_)
cdm_color_space_commit_ = false;
return error;
}
DisplayError HWHDMI::GetHWScanInfo(HWScanInfo *scan_info) {
@ -994,23 +1011,17 @@ void HWHDMI::UpdateMixerAttributes() {
}
DisplayError HWHDMI::UpdateHDRMetaData(HWLayers *hw_layers) {
const HWHDRLayerInfo &hdr_layer_info = hw_layers->info.hdr_layer_info;
if (!hw_panel_info_.hdr_enabled || hdr_layer_info.operation == HWHDRLayerInfo::kNoOp) {
if (!hw_panel_info_.hdr_enabled) {
return kErrorNone;
}
DisplayError error = kErrorNone;
#ifdef MDP_HDR_STREAM
const HWHDRLayerInfo &hdr_layer_info = hw_layers->info.hdr_layer_info;
char hdr_stream_path[kMaxStringLength] = {};
snprintf(hdr_stream_path, sizeof(hdr_stream_path), "%s%d/hdr_stream", fb_path_, fb_node_index_);
int fd = Sys::open_(hdr_stream_path, O_WRONLY);
if (fd < 0) {
DLOGE("Failed to open %s with error %s", hdr_stream_path, strerror(errno));
return kErrorFileDescriptor;
}
Layer hdr_layer = {};
if (hdr_layer_info.operation == HWHDRLayerInfo::kSet && hdr_layer_info.layer_index > -1) {
hdr_layer = *(hw_layers->info.stack->layers.at(UINT32(hdr_layer_info.layer_index)));
@ -1021,47 +1032,89 @@ DisplayError HWHDMI::UpdateHDRMetaData(HWLayers *hw_layers) {
const ContentLightLevel &light_level = layer_buffer->color_metadata.contentLightLevel;
const Primaries &primaries = mastering_display.primaries;
mdp_hdr_stream hdr_stream = {};
mdp_hdr_stream_ctrl hdr_ctrl = {};
if (hdr_layer_info.operation == HWHDRLayerInfo::kSet) {
int32_t eotf = GetEOTF(layer_buffer->color_metadata.transfer);
hdr_stream.eotf = (eotf < 0) ? 0 : UINT32(eotf);
hdr_stream.white_point_x = primaries.whitePoint[0];
hdr_stream.white_point_y = primaries.whitePoint[1];
hdr_stream.display_primaries_x[0] = primaries.rgbPrimaries[0][0];
hdr_stream.display_primaries_y[0] = primaries.rgbPrimaries[0][1];
hdr_stream.display_primaries_x[1] = primaries.rgbPrimaries[1][0];
hdr_stream.display_primaries_y[1] = primaries.rgbPrimaries[1][1];
hdr_stream.display_primaries_x[2] = primaries.rgbPrimaries[2][0];
hdr_stream.display_primaries_y[2] = primaries.rgbPrimaries[2][1];
hdr_stream.min_luminance = mastering_display.minDisplayLuminance;
hdr_stream.max_luminance = mastering_display.maxDisplayLuminance/10000;
hdr_stream.max_content_light_level = light_level.maxContentLightLevel;
hdr_stream.max_average_light_level = light_level.minPicAverageLightLevel;
hdr_ctrl.hdr_stream.eotf = (eotf < 0) ? 0 : UINT32(eotf);
hdr_ctrl.hdr_stream.white_point_x = primaries.whitePoint[0];
hdr_ctrl.hdr_stream.white_point_y = primaries.whitePoint[1];
hdr_ctrl.hdr_stream.display_primaries_x[0] = primaries.rgbPrimaries[0][0];
hdr_ctrl.hdr_stream.display_primaries_y[0] = primaries.rgbPrimaries[0][1];
hdr_ctrl.hdr_stream.display_primaries_x[1] = primaries.rgbPrimaries[1][0];
hdr_ctrl.hdr_stream.display_primaries_y[1] = primaries.rgbPrimaries[1][1];
hdr_ctrl.hdr_stream.display_primaries_x[2] = primaries.rgbPrimaries[2][0];
hdr_ctrl.hdr_stream.display_primaries_y[2] = primaries.rgbPrimaries[2][1];
hdr_ctrl.hdr_stream.min_luminance = mastering_display.minDisplayLuminance;
hdr_ctrl.hdr_stream.max_luminance = mastering_display.maxDisplayLuminance/10000;
hdr_ctrl.hdr_stream.max_content_light_level = light_level.maxContentLightLevel;
hdr_ctrl.hdr_stream.max_average_light_level = light_level.minPicAverageLightLevel;
hdr_ctrl.hdr_state = HDR_ENABLE;
reset_hdr_flag_ = false;
#ifdef MDP_COMMIT_UPDATE_CDM_COLOR_SPACE
HWDevice::SetCSC(layer_buffer->color_metadata, &cdm_color_space_);
cdm_color_space_commit_ = true;
#endif
// DP related
int32_t pixel_encoding = GetPixelEncoding(hdr_layer.input_buffer);
hdr_stream.pixel_encoding = (pixel_encoding < 0) ? 0 : UINT32(pixel_encoding);
hdr_ctrl.hdr_stream.pixel_encoding = (pixel_encoding < 0) ? 0 : UINT32(pixel_encoding);
int32_t colorimetry = GetColoriMetry(hdr_layer.input_buffer);
hdr_stream.colorimetry = (colorimetry < 0) ? 0 : UINT32(colorimetry);
hdr_stream.range = GetRange(hdr_layer.input_buffer.color_metadata.range);
hdr_ctrl.hdr_stream.colorimetry = (colorimetry < 0) ? 0 : UINT32(colorimetry);
hdr_ctrl.hdr_stream.range = GetRange(hdr_layer.input_buffer.color_metadata.range);
int32_t bits_per_component = GetBitsPerComponent(hdr_layer.input_buffer);
hdr_stream.bits_per_component = (bits_per_component < 0) ? 0 : UINT32(bits_per_component);
hdr_stream.content_type = GetContentType(hdr_layer.input_buffer);
hdr_ctrl.hdr_stream.bits_per_component =
(bits_per_component < 0) ? 0 : UINT32(bits_per_component);
hdr_ctrl.hdr_stream.content_type = GetContentType(hdr_layer.input_buffer);
DLOGV_IF(kTagDriverConfig, "HDR Stream : MaxDisplayLuminance = %d MinDisplayLuminance = %d\n"
"MaxContentLightLevel = %d MaxAverageLightLevel = %d Red_x = %d Red_y = %d Green_x = %d\n"
"Green_y = %d Blue_x = %d Blue_y = %d WhitePoint_x = %d WhitePoint_y = %d EOTF = %d\n"
"PixelEncoding = %d Colorimetry = %d Range = %d BPC = %d ContentType = %d",
hdr_stream.max_luminance, hdr_stream.min_luminance, hdr_stream.max_content_light_level,
hdr_stream.max_average_light_level, hdr_stream.display_primaries_x[0],
hdr_stream.display_primaries_y[0], hdr_stream.display_primaries_x[1],
hdr_stream.display_primaries_y[1], hdr_stream.display_primaries_x[2],
hdr_stream.display_primaries_y[2], hdr_stream.white_point_x, hdr_stream.white_point_x,
hdr_stream.eotf, hdr_stream.pixel_encoding, hdr_stream.colorimetry, hdr_stream.range,
hdr_stream.bits_per_component, hdr_stream.content_type);
DLOGV_IF(kTagDriverConfig, "kSet: HDR Stream : MaxDisplayLuminance = %d\n"
"MinDisplayLuminance = %d MaxContentLightLevel = %d MaxAverageLightLevel = %d\n"
"Red_x = %d Red_y = %d Green_x = %d Green_y = %d Blue_x = %d Blue_y = %d\n"
"WhitePoint_x = %d WhitePoint_y = %d EOTF = %d PixelEncoding = %d Colorimetry = %d\n"
"Range = %d BPC = %d ContentType = %d hdr_state = %d",
hdr_ctrl.hdr_stream.max_luminance, hdr_ctrl.hdr_stream.min_luminance,
hdr_ctrl.hdr_stream.max_content_light_level, hdr_ctrl.hdr_stream.max_average_light_level,
hdr_ctrl.hdr_stream.display_primaries_x[0], hdr_ctrl.hdr_stream.display_primaries_y[0],
hdr_ctrl.hdr_stream.display_primaries_x[1], hdr_ctrl.hdr_stream.display_primaries_y[1],
hdr_ctrl.hdr_stream.display_primaries_x[2], hdr_ctrl.hdr_stream.display_primaries_y[2],
hdr_ctrl.hdr_stream.white_point_x, hdr_ctrl.hdr_stream.white_point_x,
hdr_ctrl.hdr_stream.eotf, hdr_ctrl.hdr_stream.pixel_encoding,
hdr_ctrl.hdr_stream.colorimetry, hdr_ctrl.hdr_stream.range,
hdr_ctrl.hdr_stream.bits_per_component, hdr_ctrl.hdr_stream.content_type,
hdr_ctrl.hdr_state);
} else if (hdr_layer_info.operation == HWHDRLayerInfo::kReset) {
memset(&hdr_ctrl.hdr_stream, 0, sizeof(hdr_ctrl.hdr_stream));
hdr_ctrl.hdr_state = HDR_RESET;
reset_hdr_flag_ = true;
hdr_reset_start_ = time(NULL);
#ifdef MDP_COMMIT_UPDATE_CDM_COLOR_SPACE
cdm_color_space_ = (mdp_color_space) MDP_CSC_DEFAULT;
cdm_color_space_commit_ = true;
#endif
DLOGV_IF(kTagDriverConfig, "kReset: HDR Stream: HDR_RESET");
} else if (hdr_layer_info.operation == HWHDRLayerInfo::kNoOp) {
if (reset_hdr_flag_) {
hdr_reset_end_ = time(NULL);
if ((hdr_reset_end_ - hdr_reset_start_) >= MIN_HDR_RESET_WAITTIME_SEC) {
reset_hdr_flag_ = false;
memset(&hdr_ctrl.hdr_stream, 0, sizeof(hdr_ctrl.hdr_stream));
hdr_ctrl.hdr_state = HDR_DISABLE;
DLOGV_IF(kTagDriverConfig, "kNoOp: HDR Stream: HDR_DISABLE");
} else {
return kErrorNone;
}
} else {
return kErrorNone;
}
}
const void *hdr_metadata = reinterpret_cast<const void*>(&hdr_stream);
ssize_t len = Sys::pwrite_(fd, hdr_metadata, sizeof(hdr_stream), 0);
int fd = Sys::open_(hdr_stream_path, O_WRONLY);
if (fd < 0) {
DLOGE("Failed to open %s with error %s", hdr_stream_path, strerror(errno));
return kErrorFileDescriptor;
}
const void *hdr_metadata = reinterpret_cast<const void*>(&hdr_ctrl);
ssize_t len = Sys::pwrite_(fd, hdr_metadata, sizeof(hdr_ctrl), 0);
if (len <= 0) {
DLOGE("Failed to write hdr_metadata");
error = kErrorUndefined;

View File

@ -118,6 +118,10 @@ class HWHDMI : public HWDevice {
vector<HWS3DMode> supported_s3d_modes_;
msm_hdmi_s3d_mode active_mdp_s3d_mode_ = HDMI_S3D_NONE;
uint32_t frame_rate_ = 0;
time_t hdr_reset_start_ = 0, hdr_reset_end_ = 0;
bool reset_hdr_flag_ = false;
mdp_color_space cdm_color_space_ = {};
bool cdm_color_space_commit_ = false;
};
} // namespace sdm

View File

@ -154,7 +154,9 @@ DisplayError HWInfo::GetHWResourceInfo(HWResourceInfo *hw_resource) {
while (Sys::getline_(fs, line)) {
// parse the line and update information accordingly
if (!ParseString(line.c_str(), tokens, max_count, ":, =\n", &token_count)) {
if (!strncmp(tokens[0], "hw_rev", strlen("hw_rev"))) {
if (!strncmp(tokens[0], "mdp_version", strlen("mdp_version"))) {
hw_resource_->hw_version = UINT32(atoi(tokens[1])); // HW Version 3/5
} else if (!strncmp(tokens[0], "hw_rev", strlen("hw_rev"))) {
hw_resource_->hw_revision = UINT32(atoi(tokens[1])); // HW Rev, v1/v2
} else if (!strncmp(tokens[0], "rot_input_fmts", strlen("rot_input_fmts"))) {
ParseFormats(&tokens[1], (token_count - 1), kHWRotatorInput, hw_resource_);
@ -168,6 +170,8 @@ DisplayError HWInfo::GetHWResourceInfo(HWResourceInfo *hw_resource) {
hw_resource_->max_scale_down = UINT32(atoi(tokens[1]));
} else if (!strncmp(tokens[0], "max_upscale_ratio", strlen("max_upscale_ratio"))) {
hw_resource_->max_scale_up = UINT32(atoi(tokens[1]));
} else if (!strncmp(tokens[0], "rot_dwnscale_max", strlen("rot_dwnscale_max"))) {
hw_resource_->rot_downscale_max = FLOAT(atoi(tokens[1]));
} else if (!strncmp(tokens[0], "max_bandwidth_low", strlen("max_bandwidth_low"))) {
hw_resource_->max_bandwidth_low = UINT64(atol(tokens[1]));
} else if (!strncmp(tokens[0], "max_bandwidth_high", strlen("max_bandwidth_high"))) {

View File

@ -604,14 +604,22 @@ DisplayError HWPrimary::GetPPFeaturesVersion(PPFeatureVersion *vers) {
uint32_t feature_id_mapping[kMaxNumPPFeatures] = { PCC, IGC, GC, GC, PA, DITHER, GAMUT };
#endif
for (int i(0); i < kMaxNumPPFeatures; i++) {
version.pp_feature = feature_id_mapping[i];
if (hw_resource_.hw_version != kHWMdssVersion3) {
// Do not query kGlobalColorFeatureCsc for kHWMdssVersion5
for (int i(0); i < (kMaxNumPPFeatures - 1); i++) {
version.pp_feature = feature_id_mapping[i];
if (Sys::ioctl_(device_fd_, INT(MSMFB_MDP_PP_GET_FEATURE_VERSION), &version) < 0) {
IOCTL_LOGE(MSMFB_MDP_PP_GET_FEATURE_VERSION, device_type_);
return kErrorHardware;
if (Sys::ioctl_(device_fd_, INT(MSMFB_MDP_PP_GET_FEATURE_VERSION), &version) < 0) {
IOCTL_LOGE(MSMFB_MDP_PP_GET_FEATURE_VERSION, device_type_);
return kErrorHardware;
}
vers->version[i] = version.version_info;
}
} else {
for (int i(0); i < kMaxNumPPFeatures; i++) {
version.pp_feature = feature_id_mapping[i];
vers->version[i] = mdp_pp_legacy;
}
vers->version[i] = version.version_info;
}
return kErrorNone;

View File

@ -73,6 +73,7 @@ class HWPrimary : public HWDevice {
kMaxSysfsCommandLength = 12,
};
static const int kHWMdssVersion3 = 3;
DisplayError PopulateDisplayAttributes();
void InitializeConfigs();
bool IsResolutionSwitchEnabled() { return !display_configs_.empty(); }

View File

@ -17,7 +17,7 @@ LOCAL_CLANG := true
LOCAL_SHARED_LIBRARIES := libsdmcore libqservice libbinder libhardware libhardware_legacy \
libutils libcutils libsync libmemalloc libqdutils libdl \
libpowermanager libsdmutils libgpu_tonemapper libc++ liblog \
libdrmutils libui
libdrmutils libui libbfqio_vendor
LOCAL_SRC_FILES := hwc_session.cpp \
hwc_display.cpp \

View File

@ -33,6 +33,7 @@
#include <utils/constants.h>
#include <utils/String16.h>
#include <cutils/properties.h>
#include <bfqio/bfqio.h>
#include <hardware_legacy/uevent.h>
#include <sys/resource.h>
#include <sys/prctl.h>
@ -1430,6 +1431,7 @@ void* HWCSession::HWCUeventThreadHandler() {
uevent_locker_.Lock();
prctl(PR_SET_NAME, uevent_thread_name_, 0, 0, 0);
setpriority(PRIO_PROCESS, 0, HAL_PRIORITY_URGENT_DISPLAY);
android_set_rt_ioprio(0, 1);
if (!uevent_init()) {
DLOGE("Failed to init uevent");
pthread_exit(0);

View File

@ -22,7 +22,7 @@ LOCAL_SHARED_LIBRARIES := libsdmcore libqservice libbinder libhardware li
libutils libcutils libsync libqdutils libqdMetaData libdl libdrmutils \
libsdmutils libc++ liblog libgrallocutils libdl \
vendor.display.config@1.0_vendor libhidlbase libhidltransport \
libui libgpu_tonemapper
libui libgpu_tonemapper libbfqio_vendor
ifneq ($(TARGET_USES_GRALLOC1), true)
LOCAL_SHARED_LIBRARIES += libmemalloc
@ -42,7 +42,8 @@ LOCAL_SRC_FILES := hwc_session.cpp \
../hwc/cpuhint.cpp \
../hwc/hwc_socket_handler.cpp \
display_null.cpp \
hwc_tonemapper.cpp
hwc_tonemapper.cpp \
hwc_display_external_test.cpp
ifneq ($(TARGET_USES_GRALLOC1), true)
LOCAL_SRC_FILES += ../hwc/hwc_buffer_allocator.cpp

View File

@ -95,6 +95,8 @@ class DisplayNull : public DisplayInterface {
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 &))
private:
bool active_ = false;

View File

@ -41,27 +41,45 @@
namespace sdm {
HWCBufferAllocator::HWCBufferAllocator() {
DisplayError HWCBufferAllocator::Init() {
int err = hw_get_module(GRALLOC_HARDWARE_MODULE_ID, &module_);
if (err != 0) {
DLOGE("FATAL: can not open GRALLOC module");
} else {
gralloc1_open(module_, &gralloc_device_);
DLOGE("FATAL: can not get GRALLOC module");
return kErrorResources;
}
if (gralloc_device_ != nullptr) {
ReleaseBuffer_ = reinterpret_cast<GRALLOC1_PFN_RELEASE>(
gralloc_device_->getFunction(gralloc_device_, GRALLOC1_FUNCTION_RELEASE));
Perform_ = reinterpret_cast<GRALLOC1_PFN_PERFORM>(
gralloc_device_->getFunction(gralloc_device_, GRALLOC1_FUNCTION_PERFORM));
Lock_ = reinterpret_cast<GRALLOC1_PFN_LOCK>(
gralloc_device_->getFunction(gralloc_device_, GRALLOC1_FUNCTION_LOCK));
err = gralloc1_open(module_, &gralloc_device_);
if (err != 0) {
DLOGE("FATAL: can not open GRALLOC device");
return kErrorResources;
}
if (gralloc_device_ == nullptr) {
DLOGE("FATAL: gralloc device is null");
return kErrorResources;
}
ReleaseBuffer_ = reinterpret_cast<GRALLOC1_PFN_RELEASE>(
gralloc_device_->getFunction(gralloc_device_, GRALLOC1_FUNCTION_RELEASE));
Perform_ = reinterpret_cast<GRALLOC1_PFN_PERFORM>(
gralloc_device_->getFunction(gralloc_device_, GRALLOC1_FUNCTION_PERFORM));
Lock_ = reinterpret_cast<GRALLOC1_PFN_LOCK>(
gralloc_device_->getFunction(gralloc_device_, GRALLOC1_FUNCTION_LOCK));
Unlock_ = reinterpret_cast<GRALLOC1_PFN_UNLOCK>(
gralloc_device_->getFunction(gralloc_device_, GRALLOC1_FUNCTION_UNLOCK));
return kErrorNone;
}
HWCBufferAllocator::~HWCBufferAllocator() {
DisplayError HWCBufferAllocator::Deinit() {
if (gralloc_device_ != nullptr) {
gralloc1_close(gralloc_device_);
int err = gralloc1_close(gralloc_device_);
if (err != 0) {
DLOGE("FATAL: can not close GRALLOC device");
return kErrorResources;
}
}
return kErrorNone;
}
DisplayError HWCBufferAllocator::AllocateBuffer(BufferInfo *buffer_info) {
@ -80,6 +98,10 @@ DisplayError HWCBufferAllocator::AllocateBuffer(BufferInfo *buffer_info) {
alloc_flags |= GRALLOC1_PRODUCER_USAGE_PROTECTED;
}
if (buffer_config.secure_camera) {
alloc_flags |= GRALLOC1_PRODUCER_USAGE_CAMERA;
}
if (!buffer_config.cache) {
// Allocate uncached buffers
alloc_flags |= GRALLOC_USAGE_PRIVATE_UNCACHED;
@ -90,7 +112,7 @@ DisplayError HWCBufferAllocator::AllocateBuffer(BufferInfo *buffer_info) {
}
uint64_t producer_usage = alloc_flags;
uint64_t consumer_usage = alloc_flags;
uint64_t consumer_usage = (alloc_flags | GRALLOC1_CONSUMER_USAGE_HWCOMPOSER);
// CreateBuffer
private_handle_t *hnd = nullptr;
Perform_(gralloc_device_, GRALLOC1_MODULE_PERFORM_ALLOCATE_BUFFER, width, height, format,
@ -99,6 +121,8 @@ DisplayError HWCBufferAllocator::AllocateBuffer(BufferInfo *buffer_info) {
if (hnd) {
alloc_buffer_info->fd = hnd->fd;
alloc_buffer_info->stride = UINT32(hnd->width);
alloc_buffer_info->aligned_width = UINT32(hnd->width);
alloc_buffer_info->aligned_height = UINT32(hnd->height);
alloc_buffer_info->size = hnd->size;
} else {
DLOGE("Failed to allocate memory");
@ -137,6 +161,9 @@ void HWCBufferAllocator::GetAlignedWidthAndHeight(int width, int height, int for
if (alloc_type & GRALLOC_USAGE_HW_FB) {
consumer_usage = GRALLOC1_CONSUMER_USAGE_CLIENT_TARGET;
}
if (alloc_type & GRALLOC_USAGE_PRIVATE_ALLOC_UBWC) {
producer_usage = GRALLOC_USAGE_PRIVATE_ALLOC_UBWC;
}
Perform_(gralloc_device_, GRALLOC_MODULE_PERFORM_GET_ATTRIBUTES, width, height, format,
producer_usage, consumer_usage, aligned_width, aligned_height, &tile_enabled);
@ -375,4 +402,8 @@ DisplayError HWCBufferAllocator::MapBuffer(const private_handle_t *handle, int a
return kErrorNone;
}
DisplayError HWCBufferAllocator::UnmapBuffer(const private_handle_t *handle, int* release_fence) {
return (DisplayError)(Unlock_(gralloc_device_, handle, release_fence));
}
} // namespace sdm

View File

@ -45,9 +45,8 @@ inline Type ALIGN(Type x, Type align) {
class HWCBufferAllocator : public BufferAllocator {
public:
HWCBufferAllocator();
~HWCBufferAllocator();
DisplayError Init();
DisplayError Deinit();
DisplayError AllocateBuffer(BufferInfo *buffer_info);
DisplayError FreeBuffer(BufferInfo *buffer_info);
uint32_t GetBufferSize(BufferInfo *buffer_info);
@ -62,6 +61,7 @@ class HWCBufferAllocator : public BufferAllocator {
uint32_t *num_planes);
int SetBufferInfo(LayerBufferFormat format, int *target, uint64_t *flags);
DisplayError MapBuffer(const private_handle_t *handle, int acquire_fence);
DisplayError UnmapBuffer(const private_handle_t *handle, int* release_fence);
private:
gralloc1_device_t *gralloc_device_ = nullptr;
@ -69,6 +69,7 @@ class HWCBufferAllocator : public BufferAllocator {
GRALLOC1_PFN_RELEASE ReleaseBuffer_ = nullptr;
GRALLOC1_PFN_PERFORM Perform_ = nullptr;
GRALLOC1_PFN_LOCK Lock_ = nullptr;
GRALLOC1_PFN_UNLOCK Unlock_ = nullptr;
};
} // namespace sdm

View File

@ -122,6 +122,16 @@ HWC2::Error HWCColorMode::SetColorMode(android_color_mode_t mode) {
return status;
}
HWC2::Error HWCColorMode::RestoreColorTransform() {
DisplayError error = display_intf_->SetColorTransform(kColorTransformMatrixCount, color_matrix_);
if (error != kErrorNone) {
DLOGE("Failed to set Color Transform");
return HWC2::Error::BadParameter;
}
return HWC2::Error::None;
}
HWC2::Error HWCColorMode::SetColorTransform(const float *matrix, android_color_transform_t hint) {
if (!matrix || (hint < HAL_COLOR_TRANSFORM_IDENTITY ||
hint > HAL_COLOR_TRANSFORM_CORRECT_TRITANOPIA)) {
@ -451,6 +461,7 @@ void HWCDisplay::BuildLayerStack() {
display_rect_ = LayerRect();
metadata_refresh_rate_ = 0;
auto working_primaries = ColorPrimaries_BT709_5;
bool secure_display_active = false;
// Add one layer for fb target
// TODO(user): Add blit target layers
@ -463,12 +474,11 @@ void HWCDisplay::BuildLayerStack() {
layer->flags.solid_fill = true;
}
if (!hwc_layer->ValidateAndSetCSC()) {
#ifdef FEATURE_WIDE_COLOR
if (!hwc_layer->SupportedDataspace()) {
layer->flags.skip = true;
DLOGW_IF(kTagStrategy, "Unsupported dataspace: 0x%x", hwc_layer->GetLayerDataspace());
}
layer->flags.skip = true;
#endif
}
working_primaries = WidestPrimaries(working_primaries,
layer->input_buffer.color_metadata.colorPrimaries);
@ -507,6 +517,10 @@ void HWCDisplay::BuildLayerStack() {
layer_stack_.flags.skip_present = true;
}
if (layer->input_buffer.flags.secure_display) {
secure_display_active = true;
}
if (hwc_layer->GetClientRequestedCompositionType() == HWC2::Composition::Cursor) {
// Currently we support only one HWCursor & only at top most z-order
if ((*layer_set_.rbegin())->GetId() == hwc_layer->GetId()) {
@ -579,7 +593,19 @@ void HWCDisplay::BuildLayerStack() {
// TODO(user): Set correctly when SDM supports geometry_changes as bitmask
layer_stack_.flags.geometry_changed = UINT32(geometry_changes_ > 0);
// Append client target to the layer stack
layer_stack_.layers.push_back(client_target_->GetSDMLayer());
Layer *sdm_client_target = client_target_->GetSDMLayer();
layer_stack_.layers.push_back(sdm_client_target);
// fall back frame composition to GPU when client target is 10bit
// TODO(user): clarify the behaviour from Client(SF) and SDM Extn -
// when handling 10bit FBT, as it would affect blending
if (Is10BitFormat(sdm_client_target->input_buffer.format)) {
// Must fall back to client composition
MarkLayersForClientComposition();
}
// set secure display
SetSecureDisplay(secure_display_active);
}
void HWCDisplay::BuildSolidFillStack() {
@ -708,15 +734,20 @@ HWC2::Error HWCDisplay::SetPowerMode(HWC2::PowerMode mode) {
HWC2::Error HWCDisplay::GetClientTargetSupport(uint32_t width, uint32_t height, int32_t format,
int32_t dataspace) {
DisplayConfigVariableInfo variable_config;
display_intf_->GetFrameBufferConfig(&variable_config);
// TODO(user): Support scaled configurations, other formats and other dataspaces
if (format != HAL_PIXEL_FORMAT_RGBA_8888 || dataspace != HAL_DATASPACE_UNKNOWN ||
width != variable_config.x_pixels || height != variable_config.y_pixels) {
return HWC2::Error::Unsupported;
} else {
return HWC2::Error::None;
ColorMetaData color_metadata = {};
if (dataspace != HAL_DATASPACE_UNKNOWN) {
GetColorPrimary(dataspace, &(color_metadata.colorPrimaries));
GetTransfer(dataspace, &(color_metadata.transfer));
GetRange(dataspace, &(color_metadata.range));
}
LayerBufferFormat sdm_format = GetSDMFormat(format, 0);
if (display_intf_->GetClientTargetSupport(width, height, sdm_format,
color_metadata) != kErrorNone) {
return HWC2::Error::Unsupported;
}
return HWC2::Error::None;
}
HWC2::Error HWCDisplay::GetColorModes(uint32_t *out_num_modes, android_color_mode_t *out_modes) {
@ -746,9 +777,18 @@ HWC2::Error HWCDisplay::GetDisplayConfigs(uint32_t *out_num_configs, hwc2_config
HWC2::Error HWCDisplay::GetDisplayAttribute(hwc2_config_t config, HWC2::Attribute attribute,
int32_t *out_value) {
DisplayConfigVariableInfo variable_config;
if (GetDisplayAttributesForConfig(INT(config), &variable_config) != kErrorNone) {
DLOGE("Get variable config failed");
return HWC2::Error::BadDisplay;
// Get display attributes from config index only if resolution switch is supported.
// Otherwise always send mixer attributes. This is to support destination scaler.
if (num_configs_ > 1) {
if (GetDisplayAttributesForConfig(INT(config), &variable_config) != kErrorNone) {
DLOGE("Get variable config failed");
return HWC2::Error::BadDisplay;
}
} else {
if (display_intf_->GetFrameBufferConfig(&variable_config) != kErrorNone) {
DLOGV("Get variable config failed");
return HWC2::Error::BadDisplay;
}
}
switch (attribute) {
@ -847,7 +887,13 @@ HWC2::Error HWCDisplay::SetClientTarget(buffer_handle_t target, int32_t acquire_
client_target_->SetLayerBuffer(target, acquire_fence);
client_target_->SetLayerSurfaceDamage(damage);
// Ignoring dataspace for now
if (client_target_->GetLayerDataspace() != dataspace) {
client_target_->SetLayerDataspace(dataspace);
Layer *sdm_layer = client_target_->GetSDMLayer();
// Data space would be validated at GetClientTargetSupport, so just use here.
sdm::GetSDMColorSpace(dataspace, &sdm_layer->input_buffer.color_metadata);
}
return HWC2::Error::None;
}
@ -965,6 +1011,7 @@ HWC2::Error HWCDisplay::PrepareLayerStack(uint32_t *out_num_types, uint32_t *out
}
hwc_layer->ResetValidation();
}
client_target_->ResetValidation();
*out_num_types = UINT32(layer_changes_.size());
*out_num_requests = UINT32(layer_requests_.size());
skip_validate_ = false;
@ -1172,6 +1219,7 @@ HWC2::Error HWCDisplay::PostCommitLayerStack(int32_t *out_retire_fence) {
close(client_target_release_fence);
client_target_release_fence = -1;
}
client_target_->ResetGeometryChanges();
for (auto hwc_layer : layer_set_) {
hwc_layer->ResetGeometryChanges();
@ -1381,6 +1429,7 @@ void HWCDisplay::DumpInputBuffers() {
return;
}
DLOGI("dump_frame_count %d dump_input_layers %d", dump_frame_count_, dump_input_layers_);
snprintf(dir_path, sizeof(dir_path), "%s/frame_dump_%s", HWCDebugHandler::DumpDir(),
GetDisplayString());
@ -1409,22 +1458,43 @@ void HWCDisplay::DumpInputBuffers() {
}
}
if (pvt_handle && pvt_handle->base) {
char dump_file_name[PATH_MAX];
size_t result = 0;
DLOGI("Dump layer[%d] of %d pvt_handle %x pvt_handle->base %x", i, layer_stack_.layers.size(),
pvt_handle, pvt_handle? pvt_handle->base : 0);
snprintf(dump_file_name, sizeof(dump_file_name), "%s/input_layer%d_%dx%d_%s_frame%d.raw",
dir_path, i, pvt_handle->width, pvt_handle->height,
qdutils::GetHALPixelFormatString(pvt_handle->format), dump_frame_index_);
FILE *fp = fopen(dump_file_name, "w+");
if (fp) {
result = fwrite(reinterpret_cast<void *>(pvt_handle->base), pvt_handle->size, 1, fp);
fclose(fp);
}
DLOGI("Frame Dump %s: is %s", dump_file_name, result ? "Successful" : "Failed");
if (!pvt_handle) {
DLOGE("Buffer handle is null");
return;
}
if (!pvt_handle->base) {
DisplayError error = buffer_allocator_->MapBuffer(pvt_handle, -1);
if (error != kErrorNone) {
DLOGE("Failed to map buffer, error = %d", error);
return;
}
}
char dump_file_name[PATH_MAX];
size_t result = 0;
snprintf(dump_file_name, sizeof(dump_file_name), "%s/input_layer%d_%dx%d_%s_frame%d.raw",
dir_path, i, pvt_handle->width, pvt_handle->height,
qdutils::GetHALPixelFormatString(pvt_handle->format), dump_frame_index_);
FILE *fp = fopen(dump_file_name, "w+");
if (fp) {
result = fwrite(reinterpret_cast<void *>(pvt_handle->base), pvt_handle->size, 1, fp);
fclose(fp);
}
int release_fence = -1;
DisplayError error = buffer_allocator_->UnmapBuffer(pvt_handle, &release_fence);
if (error != kErrorNone) {
DLOGE("Failed to unmap buffer, error = %d", error);
return;
}
DLOGI("Frame Dump %s: is %s", dump_file_name, result ? "Successful" : "Failed");
}
}
@ -1519,10 +1589,13 @@ int HWCDisplay::SetFrameBufferResolution(uint32_t x_pixels, uint32_t y_pixels) {
int aligned_height;
uint32_t usage = GRALLOC_USAGE_HW_FB;
int format = HAL_PIXEL_FORMAT_RGBA_8888;
int ubwc_enabled = 0;
int ubwc_disabled = 0;
int flags = 0;
HWCDebugHandler::Get()->GetProperty("debug.gralloc.enable_fb_ubwc", &ubwc_enabled);
if (ubwc_enabled == 1) {
// By default UBWC is enabled and below property is global enable/disable for all
// buffers allocated through gralloc , including framebuffer targets.
HWCDebugHandler::Get()->GetProperty("debug.gralloc.gfx_ubwc_disable", &ubwc_disabled);
if (!ubwc_disabled) {
usage |= GRALLOC_USAGE_PRIVATE_ALLOC_UBWC;
flags |= private_handle_t::PRIV_FLAGS_UBWC_ALIGNED;
}
@ -1786,7 +1859,12 @@ int HWCDisplay::GetVisibleDisplayRect(hwc_rect_t *visible_rect) {
}
void HWCDisplay::SetSecureDisplay(bool secure_display_active) {
secure_display_active_ = secure_display_active;
if (secure_display_active_ != secure_display_active) {
DLOGI("SecureDisplay state changed from %d to %d Needs Flush!!", secure_display_active_,
secure_display_active);
secure_display_active_ = secure_display_active;
skip_prepare_ = true;
}
return;
}
@ -1918,6 +1996,10 @@ bool HWCDisplay::CanSkipValidate() {
return false;
}
if (client_target_->NeedsValidation()) {
return false;
}
for (auto hwc_layer : layer_set_) {
if (hwc_layer->NeedsValidation()) {
return false;

View File

@ -62,6 +62,7 @@ class HWCColorMode {
HWC2::Error GetColorModes(uint32_t *out_num_modes, android_color_mode_t *out_modes);
HWC2::Error SetColorMode(android_color_mode_t mode);
HWC2::Error SetColorTransform(const float *matrix, android_color_transform_t hint);
HWC2::Error RestoreColorTransform();
private:
static const uint32_t kColorTransformMatrixCount = 16;
@ -172,6 +173,9 @@ class HWCDisplay : public DisplayEventHandler {
virtual HWC2::Error SetColorMode(android_color_mode_t mode) {
return HWC2::Error::Unsupported;
}
virtual HWC2::Error RestoreColorTransform() {
return HWC2::Error::Unsupported;
}
virtual HWC2::Error SetColorTransform(const float *matrix, android_color_transform_t hint) {
return HWC2::Error::Unsupported;
}

View File

@ -0,0 +1,750 @@
/*
* Copyright (c) 2017, The Linux Foundation. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following
* disclaimer in the documentation and/or other materials provided
* with the distribution.
* * Neither the name of The Linux Foundation nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
* OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
* IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <cutils/properties.h>
#include <sys/mman.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <utils/constants.h>
#include <utils/debug.h>
#include <utils/formats.h>
#include <algorithm>
#include <array>
#include <sstream>
#include <string>
#include <fstream>
#include "hwc_display_external_test.h"
#include "hwc_debugger.h"
#define __CLASS__ "HWCDisplayExternalTest"
namespace sdm {
using std::array;
int HWCDisplayExternalTest::Create(CoreInterface *core_intf,
HWCBufferAllocator *buffer_allocator,
HWCCallbacks *callbacks,
qService::QService *qservice, uint32_t panel_bpp,
uint32_t pattern_type, HWCDisplay **hwc_display) {
HWCDisplay *hwc_external_test = new HWCDisplayExternalTest(core_intf, buffer_allocator,
callbacks, qservice,
panel_bpp, pattern_type);
int status = static_cast<HWCDisplayExternalTest *>(hwc_external_test)->Init();
if (status) {
delete hwc_external_test;
return status;
}
*hwc_display = hwc_external_test;
DLOGE("EXTERNAL panel_bpp %d, pattern_type %d", panel_bpp, pattern_type);
return status;
}
void HWCDisplayExternalTest::Destroy(HWCDisplay *hwc_display) {
static_cast<HWCDisplayExternalTest *>(hwc_display)->Deinit();
delete hwc_display;
}
HWCDisplayExternalTest::HWCDisplayExternalTest(CoreInterface *core_intf,
HWCBufferAllocator *buffer_allocator,
HWCCallbacks *callbacks,
qService::QService *qservice, uint32_t panel_bpp,
uint32_t pattern_type)
: HWCDisplay(core_intf, callbacks, kHDMI, HWC_DISPLAY_EXTERNAL, false, qservice,
DISPLAY_CLASS_EXTERNAL, buffer_allocator), panel_bpp_(panel_bpp),
pattern_type_(pattern_type) {
}
int HWCDisplayExternalTest::Init() {
uint32_t external_width = 0;
uint32_t external_height = 0;
int status = HWCDisplay::Init();
if (status) {
DLOGE("HWCDisplayExternalTest::Init status = %d ", status);
return status;
}
status = CreateLayerStack();
if (status) {
Deinit();
return status;
}
DisplayError error = HWCDisplay::GetMixerResolution(&external_width, &external_height);
if (error != kErrorNone) {
Deinit();
return -EINVAL;
}
status = HWCDisplay::SetFrameBufferResolution(external_width, external_height);
if (status) {
Deinit();
DLOGE("HWCDisplayExternalTest:: set fb resolution status = %d ", status);
return status;
}
return status;
}
int HWCDisplayExternalTest::Deinit() {
DestroyLayerStack();
return HWCDisplay::Deinit();
}
HWC2::Error HWCDisplayExternalTest::Validate(uint32_t *out_num_types, uint32_t *out_num_requests) {
auto status = HWC2::Error::None;
if (secure_display_active_) {
MarkLayersForGPUBypass();
return status;
}
if (layer_set_.empty()) {
flush_ = true;
return status;
}
if (shutdown_pending_) {
return status;
}
DisplayError error = display_intf_->Prepare(&layer_stack_);
if (error != kErrorNone) {
if (error == kErrorShutDown) {
shutdown_pending_ = true;
} else if (error != kErrorPermission) {
DLOGE("Prepare failed. Error = %d", error);
// To prevent surfaceflinger infinite wait, flush the previous frame during Commit()
// so that previous buffer and fences are released, and override the error.
flush_ = true;
}
}
MarkLayersForGPUBypass();
return status;
}
HWC2::Error HWCDisplayExternalTest::Present(int32_t *out_retire_fence) {
auto status = HWC2::Error::None;
if (secure_display_active_) {
return status;
}
if (shutdown_pending_) {
return status;
}
DumpInputBuffer();
if (!flush_) {
DisplayError error = kErrorUndefined;
error = display_intf_->Commit(&layer_stack_);
if (error == kErrorNone) {
// A commit is successfully submitted, start flushing on failure now onwards.
flush_on_error_ = true;
} else {
if (error == kErrorShutDown) {
shutdown_pending_ = true;
return status;
} else if (error != kErrorPermission) {
DLOGE("Commit failed. Error = %d", error);
// To prevent surfaceflinger infinite wait, flush the previous frame during Commit()
// so that previous buffer and fences are released, and override the error.
flush_ = true;
}
}
}
return PostCommit(out_retire_fence);
}
void HWCDisplayExternalTest::SetSecureDisplay(bool secure_display_active) {
if (secure_display_active_ != secure_display_active) {
secure_display_active_ = secure_display_active;
if (secure_display_active_) {
DisplayError error = display_intf_->Flush();
if (error != kErrorNone) {
DLOGE("Flush failed. Error = %d", error);
}
}
}
return;
}
int HWCDisplayExternalTest::Perform(uint32_t operation, ...) {
return 0;
}
void HWCDisplayExternalTest::DumpInputBuffer() {
if (!dump_frame_count_ || flush_ || !dump_input_layers_) {
return;
}
const char *dir_path = "/data/vendor/display/frame_dump_external";
uint32_t width = buffer_info_.alloc_buffer_info.aligned_width;
uint32_t height = buffer_info_.alloc_buffer_info.aligned_height;
string format_str = GetFormatString(buffer_info_.buffer_config.format);
char *buffer = reinterpret_cast<char *>(mmap(NULL, buffer_info_.alloc_buffer_info.size,
PROT_READ|PROT_WRITE, MAP_SHARED,
buffer_info_.alloc_buffer_info.fd, 0));
if (buffer == MAP_FAILED) {
DLOGW("mmap failed. err = %d", errno);
return;
}
if (mkdir(dir_path, 0777) != 0 && errno != EEXIST) {
DLOGW("Failed to create %s directory errno = %d, desc = %s", dir_path, errno, strerror(errno));
return;
}
// if directory exists already, need to explicitly change the permission.
if (errno == EEXIST && chmod(dir_path, 0777) != 0) {
DLOGW("Failed to change permissions on %s directory", dir_path);
return;
}
if (buffer) {
std::stringstream dump_file_name;
dump_file_name << dir_path;
dump_file_name << "/input_layer_" << width << "x" << height << "_" << format_str << ".raw";
std::fstream fs;
fs.open(dump_file_name.str().c_str(), std::fstream::in | std::fstream::out | std::fstream::app);
if (!fs.is_open()) {
DLOGI("File open failed %s", dump_file_name.str().c_str());
return;
}
fs.write(buffer, (std::streamsize)buffer_info_.alloc_buffer_info.size);
fs.close();
DLOGI("Frame Dump %s: is successful", dump_file_name.str().c_str());
}
// Dump only once as the content is going to be same for all draw cycles
if (dump_frame_count_) {
dump_frame_count_ = 0;
}
if (munmap(buffer, buffer_info_.alloc_buffer_info.size) != 0) {
DLOGW("munmap failed. err = %d", errno);
return;
}
}
void HWCDisplayExternalTest::CalcCRC(uint32_t color_val, std::bitset<16> *crc_data) {
std::bitset<16> color = {};
std::bitset<16> temp_crc = {};
switch (panel_bpp_) {
case kDisplayBpp18:
color = (color_val & 0xFC) << 8;
break;
case kDisplayBpp24:
color = color_val << 8;
break;
case kDisplayBpp30:
color = color_val << 6;
break;
default:
return;
}
temp_crc[15] = (*crc_data)[0] ^ (*crc_data)[1] ^ (*crc_data)[2] ^ (*crc_data)[3] ^
(*crc_data)[4] ^ (*crc_data)[5] ^ (*crc_data)[6] ^ (*crc_data)[7] ^
(*crc_data)[8] ^ (*crc_data)[9] ^ (*crc_data)[10] ^ (*crc_data)[11] ^
(*crc_data)[12] ^ (*crc_data)[14] ^ (*crc_data)[15] ^ color[0] ^ color[1] ^
color[2] ^ color[3] ^ color[4] ^ color[5] ^ color[6] ^ color[7] ^ color[8] ^
color[9] ^ color[10] ^ color[11] ^ color[12] ^ color[14] ^ color[15];
temp_crc[14] = (*crc_data)[12] ^ (*crc_data)[13] ^ color[12] ^ color[13];
temp_crc[13] = (*crc_data)[11] ^ (*crc_data)[12] ^ color[11] ^ color[12];
temp_crc[12] = (*crc_data)[10] ^ (*crc_data)[11] ^ color[10] ^ color[11];
temp_crc[11] = (*crc_data)[9] ^ (*crc_data)[10] ^ color[9] ^ color[10];
temp_crc[10] = (*crc_data)[8] ^ (*crc_data)[9] ^ color[8] ^ color[9];
temp_crc[9] = (*crc_data)[7] ^ (*crc_data)[8] ^ color[7] ^ color[8];
temp_crc[8] = (*crc_data)[6] ^ (*crc_data)[7] ^ color[6] ^ color[7];
temp_crc[7] = (*crc_data)[5] ^ (*crc_data)[6] ^ color[5] ^ color[6];
temp_crc[6] = (*crc_data)[4] ^ (*crc_data)[5] ^ color[4] ^ color[5];
temp_crc[5] = (*crc_data)[3] ^ (*crc_data)[4] ^ color[3] ^ color[4];
temp_crc[4] = (*crc_data)[2] ^ (*crc_data)[3] ^ color[2] ^ color[3];
temp_crc[3] = (*crc_data)[1] ^ (*crc_data)[2] ^ (*crc_data)[15] ^ color[1] ^ color[2] ^ color[15];
temp_crc[2] = (*crc_data)[0] ^ (*crc_data)[1] ^ (*crc_data)[14] ^ color[0] ^ color[1] ^ color[14];
temp_crc[1] = (*crc_data)[1] ^ (*crc_data)[2] ^ (*crc_data)[3] ^ (*crc_data)[4] ^ (*crc_data)[5] ^
(*crc_data)[6] ^ (*crc_data)[7] ^ (*crc_data)[8] ^ (*crc_data)[9] ^
(*crc_data)[10] ^ (*crc_data)[11] ^ (*crc_data)[12] ^ (*crc_data)[13] ^
(*crc_data)[14] ^ color[1] ^ color[2] ^ color[3] ^ color[4] ^ color[5] ^ color[6] ^
color[7] ^ color[8] ^ color[9] ^ color[10] ^ color[11] ^ color[12] ^ color[13] ^
color[14];
temp_crc[0] = (*crc_data)[0] ^ (*crc_data)[1] ^ (*crc_data)[2] ^ (*crc_data)[3] ^ (*crc_data)[4] ^
(*crc_data)[5] ^ (*crc_data)[6] ^ (*crc_data)[7] ^ (*crc_data)[8] ^ (*crc_data)[9] ^
(*crc_data)[10] ^ (*crc_data)[11] ^ (*crc_data)[12] ^ (*crc_data)[13] ^
(*crc_data)[15] ^ color[0] ^ color[1] ^ color[2] ^ color[3] ^ color[4] ^ color[5] ^
color[6] ^ color[7] ^ color[8] ^ color[9] ^ color[10] ^ color[11] ^ color[12] ^
color[13] ^ color[15];
(*crc_data) = temp_crc;
}
int HWCDisplayExternalTest::FillBuffer() {
uint8_t *buffer = reinterpret_cast<uint8_t *>(mmap(NULL, buffer_info_.alloc_buffer_info.size,
PROT_READ|PROT_WRITE, MAP_SHARED,
buffer_info_.alloc_buffer_info.fd, 0));
if (buffer == MAP_FAILED) {
DLOGE("mmap failed. err = %d", errno);
return -EFAULT;
}
switch (pattern_type_) {
case kPatternColorRamp:
GenerateColorRamp(buffer);
break;
case kPatternBWVertical:
GenerateBWVertical(buffer);
break;
case kPatternColorSquare:
GenerateColorSquare(buffer);
break;
default:
DLOGW("Invalid Pattern type %d", pattern_type_);
return -EINVAL;
}
if (munmap(buffer, buffer_info_.alloc_buffer_info.size) != 0) {
DLOGE("munmap failed. err = %d", errno);
return -EFAULT;
}
return 0;
}
int HWCDisplayExternalTest::GetStride(LayerBufferFormat format, uint32_t width, uint32_t *stride) {
switch (format) {
case kFormatRGBA8888:
case kFormatRGBA1010102:
*stride = width * 4;
break;
case kFormatRGB888:
*stride = width * 3;
break;
default:
DLOGE("Unsupported format type %d", format);
return -EINVAL;
}
return 0;
}
void HWCDisplayExternalTest::PixelCopy(uint32_t red, uint32_t green, uint32_t blue, uint32_t alpha,
uint8_t **buffer) {
LayerBufferFormat format = buffer_info_.buffer_config.format;
switch (format) {
case kFormatRGBA8888:
*(*buffer)++ = UINT8(red & 0xFF);
*(*buffer)++ = UINT8(green & 0xFF);
*(*buffer)++ = UINT8(blue & 0xFF);
*(*buffer)++ = UINT8(alpha & 0xFF);
break;
case kFormatRGB888:
*(*buffer)++ = UINT8(red & 0xFF);
*(*buffer)++ = UINT8(green & 0xFF);
*(*buffer)++ = UINT8(blue & 0xFF);
break;
case kFormatRGBA1010102:
// Lower 8 bits of red
*(*buffer)++ = UINT8(red & 0xFF);
// Upper 2 bits of Red + Lower 6 bits of green
*(*buffer)++ = UINT8(((green & 0x3F) << 2) | ((red >> 0x8) & 0x3));
// Upper 4 bits of green + Lower 4 bits of blue
*(*buffer)++ = UINT8(((blue & 0xF) << 4) | ((green >> 6) & 0xF));
// Upper 6 bits of blue + Lower 2 bits of alpha
*(*buffer)++ = UINT8(((alpha & 0x3) << 6) | ((blue >> 4) & 0x3F));
break;
default:
DLOGW("format not supported format = %d", format);
break;
}
}
void HWCDisplayExternalTest::GenerateColorRamp(uint8_t *buffer) {
uint32_t width = buffer_info_.buffer_config.width;
uint32_t height = buffer_info_.buffer_config.height;
LayerBufferFormat format = buffer_info_.buffer_config.format;
uint32_t aligned_width = buffer_info_.alloc_buffer_info.aligned_width;
uint32_t buffer_stride = 0;
uint32_t color_ramp = 0;
uint32_t start_color_val = 0;
uint32_t step_size = 1;
uint32_t ramp_width = 0;
uint32_t ramp_height = 0;
uint32_t shift_by = 0;
std::bitset<16> crc_red = {};
std::bitset<16> crc_green = {};
std::bitset<16> crc_blue = {};
switch (panel_bpp_) {
case kDisplayBpp18:
ramp_height = 64;
ramp_width = 64;
shift_by = 2;
break;
case kDisplayBpp24:
ramp_height = 64;
ramp_width = 256;
break;
case kDisplayBpp30:
ramp_height = 32;
ramp_width = 256;
start_color_val = 0x180;
break;
default:
return;
}
GetStride(format, aligned_width, &buffer_stride);
for (uint32_t loop_height = 0; loop_height < height; loop_height++) {
uint32_t color_value = start_color_val;
uint8_t *temp = buffer + (loop_height * buffer_stride);
for (uint32_t loop_width = 0; loop_width < width; loop_width++) {
if (color_ramp == kColorRedRamp) {
PixelCopy(color_value, 0, 0, 0, &temp);
CalcCRC(color_value, &crc_red);
CalcCRC(0, &crc_green);
CalcCRC(0, &crc_blue);
}
if (color_ramp == kColorGreenRamp) {
PixelCopy(0, color_value, 0, 0, &temp);
CalcCRC(0, &crc_red);
CalcCRC(color_value, &crc_green);
CalcCRC(0, &crc_blue);
}
if (color_ramp == kColorBlueRamp) {
PixelCopy(0, 0, color_value, 0, &temp);
CalcCRC(0, &crc_red);
CalcCRC(0, &crc_green);
CalcCRC(color_value, &crc_blue);
}
if (color_ramp == kColorWhiteRamp) {
PixelCopy(color_value, color_value, color_value, 0, &temp);
CalcCRC(color_value, &crc_red);
CalcCRC(color_value, &crc_green);
CalcCRC(color_value, &crc_blue);
}
color_value = (start_color_val + (((loop_width + 1) % ramp_width) * step_size)) << shift_by;
}
if (panel_bpp_ == kDisplayBpp30 && ((loop_height + 1) % ramp_height) == 0) {
if (start_color_val == 0x180) {
start_color_val = 0;
step_size = 4;
} else {
start_color_val = 0x180;
step_size = 1;
color_ramp = (color_ramp + 1) % 4;
}
continue;
}
if (((loop_height + 1) % ramp_height) == 0) {
color_ramp = (color_ramp + 1) % 4;
}
}
DLOGI("CRC red %x", crc_red.to_ulong());
DLOGI("CRC green %x", crc_green.to_ulong());
DLOGI("CRC blue %x", crc_blue.to_ulong());
}
void HWCDisplayExternalTest::GenerateBWVertical(uint8_t *buffer) {
uint32_t width = buffer_info_.buffer_config.width;
uint32_t height = buffer_info_.buffer_config.height;
LayerBufferFormat format = buffer_info_.buffer_config.format;
uint32_t aligned_width = buffer_info_.alloc_buffer_info.aligned_width;
uint32_t buffer_stride = 0;
uint32_t bits_per_component = panel_bpp_ / 3;
uint32_t max_color_val = (1 << bits_per_component) - 1;
std::bitset<16> crc_red = {};
std::bitset<16> crc_green = {};
std::bitset<16> crc_blue = {};
if (panel_bpp_ == kDisplayBpp18) {
max_color_val <<= 2;
}
GetStride(format, aligned_width, &buffer_stride);
for (uint32_t loop_height = 0; loop_height < height; loop_height++) {
uint32_t color = 0;
uint8_t *temp = buffer + (loop_height * buffer_stride);
for (uint32_t loop_width = 0; loop_width < width; loop_width++) {
if (color == kColorBlack) {
PixelCopy(0, 0, 0, 0, &temp);
CalcCRC(0, &crc_red);
CalcCRC(0, &crc_green);
CalcCRC(0, &crc_blue);
}
if (color == kColorWhite) {
PixelCopy(max_color_val, max_color_val, max_color_val, 0, &temp);
CalcCRC(max_color_val, &crc_red);
CalcCRC(max_color_val, &crc_green);
CalcCRC(max_color_val, &crc_blue);
}
color = (color + 1) % 2;
}
}
DLOGI("CRC red %x", crc_red.to_ulong());
DLOGI("CRC green %x", crc_green.to_ulong());
DLOGI("CRC blue %x", crc_blue.to_ulong());
}
void HWCDisplayExternalTest::GenerateColorSquare(uint8_t *buffer) {
uint32_t width = buffer_info_.buffer_config.width;
uint32_t height = buffer_info_.buffer_config.height;
LayerBufferFormat format = buffer_info_.buffer_config.format;
uint32_t aligned_width = buffer_info_.alloc_buffer_info.aligned_width;
uint32_t buffer_stride = 0;
uint32_t max_color_val = 0;
uint32_t min_color_val = 0;
std::bitset<16> crc_red = {};
std::bitset<16> crc_green = {};
std::bitset<16> crc_blue = {};
switch (panel_bpp_) {
case kDisplayBpp18:
max_color_val = 63 << 2; // CEA Dynamic range for 18bpp 0 - 63
min_color_val = 0;
break;
case kDisplayBpp24:
max_color_val = 235; // CEA Dynamic range for 24bpp 16 - 235
min_color_val = 16;
break;
case kDisplayBpp30:
max_color_val = 940; // CEA Dynamic range for 30bpp 64 - 940
min_color_val = 64;
break;
default:
return;
}
array<array<uint32_t, 3>, 8> colors = {{
{{max_color_val, max_color_val, max_color_val}}, // White Color
{{max_color_val, max_color_val, min_color_val}}, // Yellow Color
{{min_color_val, max_color_val, max_color_val}}, // Cyan Color
{{min_color_val, max_color_val, min_color_val}}, // Green Color
{{max_color_val, min_color_val, max_color_val}}, // Megenta Color
{{max_color_val, min_color_val, min_color_val}}, // Red Color
{{min_color_val, min_color_val, max_color_val}}, // Blue Color
{{min_color_val, min_color_val, min_color_val}}, // Black Color
}};
GetStride(format, aligned_width, &buffer_stride);
for (uint32_t loop_height = 0; loop_height < height; loop_height++) {
uint32_t color = 0;
uint8_t *temp = buffer + (loop_height * buffer_stride);
for (uint32_t loop_width = 0; loop_width < width; loop_width++) {
PixelCopy(colors[color][0], colors[color][1], colors[color][2], 0, &temp);
CalcCRC(colors[color][0], &crc_red);
CalcCRC(colors[color][1], &crc_green);
CalcCRC(colors[color][2], &crc_blue);
if (((loop_width + 1) % 64) == 0) {
color = (color + 1) % colors.size();
}
}
if (((loop_height + 1) % 64) == 0) {
std::reverse(colors.begin(), (colors.end() - 1));
}
}
DLOGI("CRC red %x", crc_red.to_ulong());
DLOGI("CRC green %x", crc_green.to_ulong());
DLOGI("CRC blue %x", crc_blue.to_ulong());
}
int HWCDisplayExternalTest::InitLayer(Layer *layer) {
uint32_t active_config = 0;
DisplayConfigVariableInfo var_info = {};
GetActiveDisplayConfig(&active_config);
GetDisplayAttributesForConfig(INT32(active_config), &var_info);
layer->flags.updating = 1;
layer->src_rect = LayerRect(0, 0, var_info.x_pixels, var_info.y_pixels);
layer->dst_rect = layer->src_rect;
layer->frame_rate = var_info.fps;
layer->blending = kBlendingPremultiplied;
layer->input_buffer.unaligned_width = var_info.x_pixels;
layer->input_buffer.unaligned_height = var_info.y_pixels;
buffer_info_.buffer_config.format = kFormatRGBA8888;
if (layer->composition != kCompositionGPUTarget) {
buffer_info_.buffer_config.width = var_info.x_pixels;
buffer_info_.buffer_config.height = var_info.y_pixels;
switch (panel_bpp_) {
case kDisplayBpp18:
case kDisplayBpp24:
buffer_info_.buffer_config.format = kFormatRGB888;
break;
case kDisplayBpp30:
buffer_info_.buffer_config.format = kFormatRGBA1010102;
break;
default:
DLOGW("panel bpp not supported %d", panel_bpp_);
return -EINVAL;
}
buffer_info_.buffer_config.buffer_count = 1;
int ret = buffer_allocator_->AllocateBuffer(&buffer_info_);
if (ret != 0) {
DLOGE("Buffer allocation failed. ret: %d", ret);
return -ENOMEM;
}
ret = FillBuffer();
if (ret != 0) {
buffer_allocator_->FreeBuffer(&buffer_info_);
return ret;
}
layer->input_buffer.width = buffer_info_.alloc_buffer_info.aligned_width;
layer->input_buffer.height = buffer_info_.alloc_buffer_info.aligned_height;
layer->input_buffer.size = buffer_info_.alloc_buffer_info.size;
layer->input_buffer.planes[0].fd = buffer_info_.alloc_buffer_info.fd;
layer->input_buffer.planes[0].stride = buffer_info_.alloc_buffer_info.stride;
layer->input_buffer.format = buffer_info_.buffer_config.format;
DLOGI("Input buffer WxH %dx%d format %s size %d fd %d stride %d", layer->input_buffer.width,
layer->input_buffer.height, GetFormatString(layer->input_buffer.format),
layer->input_buffer.size, layer->input_buffer.planes[0].fd,
layer->input_buffer.planes[0].stride);
}
return 0;
}
int HWCDisplayExternalTest::DeinitLayer(Layer *layer) {
if (layer->composition != kCompositionGPUTarget) {
int ret = buffer_allocator_->FreeBuffer(&buffer_info_);
if (ret != 0) {
DLOGE("Buffer deallocation failed. ret: %d", ret);
return -ENOMEM;
}
}
return 0;
}
int HWCDisplayExternalTest::CreateLayerStack() {
for (uint32_t i = 0; i < (kTestLayerCnt + 1 /* one dummy gpu_target layer */); i++) {
Layer *layer = new Layer();
if (i == kTestLayerCnt) {
layer->composition = kCompositionGPUTarget;
}
DLOGE("External :: CreateLayerStack %d", i);
int ret = InitLayer(layer);
if (ret != 0) {
delete layer;
return ret;
}
layer_stack_.layers.push_back(layer);
}
return 0;
}
int HWCDisplayExternalTest::DestroyLayerStack() {
for (uint32_t i = 0; i < UINT32(layer_stack_.layers.size()); i++) {
Layer *layer = layer_stack_.layers.at(i);
int ret = DeinitLayer(layer);
if (ret != 0) {
return ret;
}
delete layer;
}
layer_stack_.layers = {};
return 0;
}
HWC2::Error HWCDisplayExternalTest::PostCommit(int32_t *out_retire_fence) {
auto status = HWC2::Error::None;
// Do no call flush on errors, if a successful buffer is never submitted.
if (flush_ && flush_on_error_) {
display_intf_->Flush();
}
if (!flush_) {
for (size_t i = 0; i < layer_stack_.layers.size(); i++) {
Layer *layer = layer_stack_.layers.at(i);
LayerBuffer &layer_buffer = layer->input_buffer;
close(layer_buffer.release_fence_fd);
layer_buffer.release_fence_fd = -1;
}
close(layer_stack_.retire_fence_fd);
layer_stack_.retire_fence_fd = -1;
*out_retire_fence = -1;
}
flush_ = false;
return status;
}
} // namespace sdm

View File

@ -0,0 +1,102 @@
/*
* Copyright (c) 2017, The Linux Foundation. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification, are permitted
* provided that the following conditions are met:
* * Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright notice, this list of
* conditions and the following disclaimer in the documentation and/or other materials provided
* with the distribution.
* * Neither the name of The Linux Foundation nor the names of its contributors may be used to
* endorse or promote products derived from this software without specific prior written
* permission.
*
* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef __HWC_DISPLAY_EXTERNAL_TEST_H__
#define __HWC_DISPLAY_EXTERNAL_TEST_H__
#include<bitset>
#include "hwc_display.h"
#include "hwc_buffer_allocator.h"
namespace sdm {
class HWCDisplayExternalTest : public HWCDisplay {
public:
static int Create(CoreInterface *core_intf, HWCBufferAllocator *buffer_allocator,
HWCCallbacks *callbacks, qService::QService *qservice,
uint32_t panel_bpp, uint32_t pattern_type, HWCDisplay **hwc_display);
static void Destroy(HWCDisplay *hwc_display);
virtual HWC2::Error Validate(uint32_t *out_num_types, uint32_t *out_num_requests);
virtual HWC2::Error Present(int32_t *out_retire_fence);
virtual void SetSecureDisplay(bool secure_display_active);
virtual int Perform(uint32_t operation, ...);
protected:
BufferInfo buffer_info_ = {};
uint32_t panel_bpp_ = 0;
uint32_t pattern_type_ = 0;
enum ColorPatternType {
kPatternNone = 0,
kPatternColorRamp,
kPatternBWVertical,
kPatternColorSquare,
};
enum DisplayBpp {
kDisplayBpp18 = 18,
kDisplayBpp24 = 24,
kDisplayBpp30 = 30,
};
enum ColorRamp {
kColorRedRamp = 0,
kColorGreenRamp = 1,
kColorBlueRamp = 2,
kColorWhiteRamp = 3,
};
enum Colors {
kColorBlack = 0,
kColorWhite = 1,
};
private:
HWCDisplayExternalTest(CoreInterface *core_intf, HWCBufferAllocator *buffer_allocator,
HWCCallbacks *callbacks, qService::QService *qservice,
uint32_t panel_bpp, uint32_t pattern_type);
int Init();
int Deinit();
void DumpInputBuffer();
void CalcCRC(uint32_t color_value, std::bitset<16> *crc_data);
int FillBuffer();
int GetStride(LayerBufferFormat format, uint32_t width, uint32_t *stride);
void PixelCopy(uint32_t red, uint32_t green, uint32_t blue, uint32_t alpha, uint8_t **buffer);
void GenerateColorRamp(uint8_t *buffer);
void GenerateBWVertical(uint8_t *buffer);
void GenerateColorSquare(uint8_t *buffer);
int InitLayer(Layer *layer);
int DeinitLayer(Layer *layer);
int CreateLayerStack();
int DestroyLayerStack();
HWC2::Error PostCommit(int32_t *out_retire_fence);
static const uint32_t kTestLayerCnt = 1;
};
} // namespace sdm
#endif // __HWC_DISPLAY_EXTERNAL_TEST_H__

View File

@ -153,8 +153,10 @@ void HWCDisplayPrimary::ProcessBootAnimCompleted() {
boot_animation_completed_ = true;
// Applying default mode after bootanimation is finished And
// If Data is Encrypted, it is ready for access.
if (display_intf_)
if (display_intf_) {
display_intf_->ApplyDefaultDisplayMode();
RestoreColorTransform();
}
}
}
@ -267,6 +269,18 @@ HWC2::Error HWCDisplayPrimary::SetColorMode(android_color_mode_t mode) {
return status;
}
HWC2::Error HWCDisplayPrimary::RestoreColorTransform() {
auto status = color_mode_->RestoreColorTransform();
if (status != HWC2::Error::None) {
DLOGE("failed to RestoreColorTransform");
return status;
}
callbacks_->Refresh(HWC_DISPLAY_PRIMARY);
return status;
}
HWC2::Error HWCDisplayPrimary::SetColorTransform(const float *matrix,
android_color_transform_t hint) {
if (!matrix) {
@ -372,9 +386,12 @@ void HWCDisplayPrimary::SetSecureDisplay(bool secure_display_active) {
DLOGI("SecureDisplay state changed from %d to %d Needs Flush!!", secure_display_active_,
secure_display_active);
secure_display_active_ = secure_display_active;
skip_prepare_ = true;
// Avoid flush for Command mode panel.
DisplayConfigFixedInfo display_config;
display_intf_->GetConfig(&display_config);
skip_prepare_ = !display_config.is_cmdmode;
}
return;
}
void HWCDisplayPrimary::ForceRefreshRate(uint32_t refresh_rate) {

View File

@ -58,6 +58,7 @@ class HWCDisplayPrimary : public HWCDisplay {
virtual HWC2::Error GetColorModes(uint32_t *out_num_modes, android_color_mode_t *out_modes);
virtual HWC2::Error SetColorMode(android_color_mode_t mode);
virtual HWC2::Error SetColorTransform(const float *matrix, android_color_transform_t hint);
virtual HWC2::Error RestoreColorTransform();
virtual int Perform(uint32_t operation, ...);
virtual void SetSecureDisplay(bool secure_display_active);
virtual DisplayError Refresh();

View File

@ -123,6 +123,11 @@ HWC2::Error HWCDisplayVirtual::Validate(uint32_t *out_num_types, uint32_t *out_n
BuildLayerStack();
layer_stack_.output_buffer = output_buffer_;
if (layer_set_.empty()) {
DLOGI("Skipping Validate and Commit");
return status;
}
status = PrepareLayerStack(out_num_types, out_num_requests);
return status;
}
@ -139,10 +144,18 @@ HWC2::Error HWCDisplayVirtual::Present(int32_t *out_retire_fence) {
status = HWCDisplay::CommitLayerStack();
if (status == HWC2::Error::None) {
if (dump_frame_count_ && !flush_ && dump_output_layer_) {
if (output_handle_ && output_handle_->base) {
if (output_handle_) {
BufferInfo buffer_info;
const private_handle_t *output_handle =
reinterpret_cast<const private_handle_t *>(output_buffer_->buffer_id);
DisplayError error = kErrorNone;
if (!output_handle->base) {
error = buffer_allocator_->MapBuffer(output_handle, -1);
if (error != kErrorNone) {
DLOGE("Failed to map output buffer, error = %d", error);
return HWC2::Error::BadParameter;
}
}
buffer_info.buffer_config.width = static_cast<uint32_t>(output_handle->width);
buffer_info.buffer_config.height = static_cast<uint32_t>(output_handle->height);
buffer_info.buffer_config.format =
@ -150,6 +163,13 @@ HWC2::Error HWCDisplayVirtual::Present(int32_t *out_retire_fence) {
buffer_info.alloc_buffer_info.size = static_cast<uint32_t>(output_handle->size);
DumpOutputBuffer(buffer_info, reinterpret_cast<void *>(output_handle->base),
layer_stack_.retire_fence_fd);
int release_fence = -1;
error = buffer_allocator_->UnmapBuffer(output_handle, &release_fence);
if (error != kErrorNone) {
DLOGE("Failed to unmap buffer, error = %d", error);
return HWC2::Error::BadParameter;
}
}
}

View File

@ -68,6 +68,105 @@ DisplayError SetCSC(const private_handle_t *pvt_handle, ColorMetaData *color_met
return kErrorNone;
}
// Returns true when color primary is supported
bool GetColorPrimary(const int32_t &dataspace, ColorPrimaries *color_primary) {
auto standard = dataspace & HAL_DATASPACE_STANDARD_MASK;
bool supported_csc = true;
switch (standard) {
case HAL_DATASPACE_STANDARD_BT709:
*color_primary = ColorPrimaries_BT709_5;
break;
case HAL_DATASPACE_STANDARD_BT601_525:
case HAL_DATASPACE_STANDARD_BT601_525_UNADJUSTED:
*color_primary = ColorPrimaries_BT601_6_525;
break;
case HAL_DATASPACE_STANDARD_BT601_625:
case HAL_DATASPACE_STANDARD_BT601_625_UNADJUSTED:
*color_primary = ColorPrimaries_BT601_6_625;
break;
case HAL_DATASPACE_STANDARD_DCI_P3:
*color_primary = ColorPrimaries_DCIP3;
break;
case HAL_DATASPACE_STANDARD_BT2020:
*color_primary = ColorPrimaries_BT2020;
break;
default:
DLOGV_IF(kTagStrategy, "Unsupported Standard Request = %d", standard);
supported_csc = false;
}
return supported_csc;
}
bool GetTransfer(const int32_t &dataspace, GammaTransfer *gamma_transfer) {
auto transfer = dataspace & HAL_DATASPACE_TRANSFER_MASK;
bool supported_transfer = true;
switch (transfer) {
case HAL_DATASPACE_TRANSFER_SRGB:
*gamma_transfer = Transfer_sRGB;
break;
case HAL_DATASPACE_TRANSFER_SMPTE_170M:
*gamma_transfer = Transfer_SMPTE_170M;
break;
case HAL_DATASPACE_TRANSFER_ST2084:
*gamma_transfer = Transfer_SMPTE_ST2084;
break;
case HAL_DATASPACE_TRANSFER_HLG:
*gamma_transfer = Transfer_HLG;
break;
case HAL_DATASPACE_TRANSFER_LINEAR:
*gamma_transfer = Transfer_Linear;
break;
case HAL_DATASPACE_TRANSFER_GAMMA2_2:
*gamma_transfer = Transfer_Gamma2_2;
break;
default:
DLOGV_IF(kTagStrategy, "Unsupported Transfer Request = %d", transfer);
supported_transfer = false;
}
return supported_transfer;
}
void GetRange(const int32_t &dataspace, ColorRange *color_range) {
auto range = dataspace & HAL_DATASPACE_RANGE_MASK;
switch (range) {
case HAL_DATASPACE_RANGE_FULL:
*color_range = Range_Full;
break;
case HAL_DATASPACE_RANGE_LIMITED:
*color_range = Range_Limited;
break;
default:
DLOGV_IF(kTagStrategy, "Unsupported Range Request = %d", range);
break;
}
}
bool IsBT2020(const ColorPrimaries &color_primary) {
switch (color_primary) {
case ColorPrimaries_BT2020:
return true;
break;
default:
return false;
}
}
// Retrieve ColorMetaData from android_data_space_t (STANDARD|TRANSFER|RANGE)
bool GetSDMColorSpace(const int32_t &dataspace, ColorMetaData *color_metadata) {
bool valid = false;
valid = GetColorPrimary(dataspace, &(color_metadata->colorPrimaries));
if (!valid) {
return valid;
}
valid = GetTransfer(dataspace, &(color_metadata->transfer));
if (!valid) {
return valid;
}
GetRange(dataspace, &(color_metadata->range));
return true;
}
// Layer operations
HWCLayer::HWCLayer(hwc2_display_t display_id, HWCBufferAllocator *buf_allocator)
: id_(next_id_++), display_id_(display_id), buffer_allocator_(buf_allocator) {
@ -270,6 +369,7 @@ HWC2::Error HWCLayer::SetLayerDataspace(int32_t dataspace) {
}
}
// cache the dataspace, to be used later to update SDM ColorMetaData
if (dataspace_ != dataspace) {
geometry_changes_ |= kDataspace;
dataspace_ = dataspace;
@ -559,19 +659,6 @@ LayerBufferS3DFormat HWCLayer::GetS3DFormat(uint32_t s3d_format) {
DisplayError HWCLayer::SetMetaData(const private_handle_t *pvt_handle, Layer *layer) {
LayerBuffer *layer_buffer = &layer->input_buffer;
bool use_color_metadata = true;
#ifdef FEATURE_WIDE_COLOR
// Only use color metadata if Android framework metadata is not set
use_color_metadata = (dataspace_ == HAL_DATASPACE_UNKNOWN);
#endif
if (use_color_metadata) {
if (sdm::SetCSC(pvt_handle, &layer_buffer->color_metadata) != kErrorNone) {
return kErrorNotSupported;
}
}
private_handle_t *handle = const_cast<private_handle_t *>(pvt_handle);
IGC_t igc = {};
LayerIGC layer_igc = layer_buffer->igc;
@ -643,84 +730,44 @@ bool HWCLayer::SupportLocalConversion(ColorPrimaries working_primaries) {
return false;
}
bool HWCLayer::SupportedDataspace() {
if (dataspace_ == HAL_DATASPACE_UNKNOWN) {
// Pick values from metadata
bool HWCLayer::ValidateAndSetCSC() {
if (client_requested_ != HWC2::Composition::Device &&
client_requested_ != HWC2::Composition::Cursor) {
// Check the layers which are configured to Device
return true;
}
LayerBuffer *layer_buffer = &layer_->input_buffer;
GammaTransfer sdm_transfer = {};
ColorPrimaries sdm_primaries = {};
ColorRange sdm_range = {};
auto transfer = dataspace_ & HAL_DATASPACE_TRANSFER_MASK;
// Handle transfer
switch (transfer) {
case HAL_DATASPACE_TRANSFER_SRGB:
sdm_transfer = Transfer_sRGB;
break;
case HAL_DATASPACE_TRANSFER_SMPTE_170M:
sdm_transfer = Transfer_SMPTE_170M;
break;
case HAL_DATASPACE_TRANSFER_ST2084:
sdm_transfer = Transfer_SMPTE_ST2084;
break;
case HAL_DATASPACE_TRANSFER_HLG:
sdm_transfer = Transfer_HLG;
break;
case HAL_DATASPACE_TRANSFER_LINEAR:
sdm_transfer = Transfer_Linear;
break;
case HAL_DATASPACE_TRANSFER_GAMMA2_2:
sdm_transfer = Transfer_Gamma2_2;
break;
default:
bool use_color_metadata = true;
#ifdef FEATURE_WIDE_COLOR
ColorMetaData csc = {};
if (dataspace_ != HAL_DATASPACE_UNKNOWN) {
use_color_metadata = false;
bool valid_csc = GetSDMColorSpace(dataspace_, &csc);
if (!valid_csc) {
return false;
}
// if we are here here, update the sdm layer csc.
layer_buffer->color_metadata.transfer = csc.transfer;
layer_buffer->color_metadata.colorPrimaries = csc.colorPrimaries;
layer_buffer->color_metadata.range = csc.range;
}
#endif
if (IsBT2020(layer_buffer->color_metadata.colorPrimaries)) {
// android_dataspace_t doesnt support mastering display and light levels
// so retrieve it from metadata for BT2020(HDR)
use_color_metadata = true;
}
// Handle standard
auto standard = dataspace_ & HAL_DATASPACE_STANDARD_MASK;
switch (standard) {
case HAL_DATASPACE_STANDARD_BT709:
sdm_primaries = ColorPrimaries_BT709_5;
break;
case HAL_DATASPACE_STANDARD_BT601_525:
case HAL_DATASPACE_STANDARD_BT601_525_UNADJUSTED:
sdm_primaries = ColorPrimaries_BT601_6_525;
break;
case HAL_DATASPACE_STANDARD_BT601_625:
case HAL_DATASPACE_STANDARD_BT601_625_UNADJUSTED:
sdm_primaries = ColorPrimaries_BT601_6_625;
break;
case HAL_DATASPACE_STANDARD_DCI_P3:
sdm_primaries = ColorPrimaries_DCIP3;
break;
case HAL_DATASPACE_STANDARD_BT2020:
sdm_primaries = ColorPrimaries_BT2020;
break;
default:
if (use_color_metadata) {
const private_handle_t *handle =
reinterpret_cast<const private_handle_t *>(layer_buffer->buffer_id);
if (sdm::SetCSC(handle, &layer_buffer->color_metadata) != kErrorNone) {
return false;
}
// TODO(user): Check transfer + primary combination
// Handle range
auto range = dataspace_ & HAL_DATASPACE_RANGE_MASK;
switch (range) {
case HAL_DATASPACE_RANGE_FULL:
sdm_range = Range_Full;
break;
case HAL_DATASPACE_RANGE_LIMITED:
default:
sdm_range = Range_Limited;
break;
}
}
// If we got here, the value is supported, update the layer
layer_buffer->color_metadata.transfer = sdm_transfer;
layer_buffer->color_metadata.colorPrimaries = sdm_primaries;
layer_buffer->color_metadata.range = sdm_range;
return true;
}

View File

@ -40,7 +40,11 @@
namespace sdm {
DisplayError SetCSC(const private_handle_t *pvt_handle, ColorMetaData *color_metadata);
bool GetColorPrimary(const int32_t &dataspace, ColorPrimaries *color_primary);
bool GetTransfer(const int32_t &dataspace, GammaTransfer *gamma_transfer);
void GetRange(const int32_t &dataspace, ColorRange *color_range);
bool GetSDMColorSpace(const int32_t &dataspace, ColorMetaData *color_metadata);
bool IsBT2020(const ColorPrimaries &color_primary);
enum GeometryChanges {
kNone = 0x000,
kBlendMode = 0x001,
@ -85,7 +89,7 @@ class HWCLayer {
void ResetGeometryChanges() { geometry_changes_ = GeometryChanges::kNone; }
void PushReleaseFence(int32_t fence);
int32_t PopReleaseFence(void);
bool SupportedDataspace();
bool ValidateAndSetCSC();
bool SupportLocalConversion(ColorPrimaries working_primaries);
void ResetValidation() { needs_validate_ = false; }
bool NeedsValidation() { return (needs_validate_ || geometry_changes_); }

View File

@ -23,6 +23,7 @@
#include <utils/constants.h>
#include <utils/String16.h>
#include <cutils/properties.h>
#include <bfqio/bfqio.h>
#include <hardware_legacy/uevent.h>
#include <sys/resource.h>
#include <sys/prctl.h>
@ -44,6 +45,8 @@
#include "hwc_debugger.h"
#include "hwc_display_primary.h"
#include "hwc_display_virtual.h"
#include "hwc_display_external_test.h"
#include "qd_utils.h"
#define __CLASS__ "HWCSession"
@ -69,13 +72,14 @@ hwc_module_t HAL_MODULE_INFO_SYM = {
namespace sdm {
static HWCUEvent g_hwc_uevent_;
Locker HWCSession::locker_;
Locker HWCSession::locker_[HWC_NUM_DISPLAY_TYPES];
void HWCUEvent::UEventThread(HWCUEvent *hwc_uevent) {
const char *uevent_thread_name = "HWC_UeventThread";
prctl(PR_SET_NAME, uevent_thread_name, 0, 0, 0);
setpriority(PRIO_PROCESS, 0, HAL_PRIORITY_URGENT_DISPLAY);
android_set_rt_ioprio(0, 1);
int status = uevent_init();
if (!status) {
@ -134,6 +138,8 @@ HWCSession::HWCSession(const hw_module_t *module) {
}
int HWCSession::Init() {
SCOPE_LOCK(locker_[HWC_DISPLAY_PRIMARY]);
int status = -EINVAL;
const char *qservice_name = "display.qservice";
@ -156,10 +162,16 @@ int HWCSession::Init() {
StartServices();
DisplayError error = CoreInterface::CreateCore(HWCDebugHandler::Get(), &buffer_allocator_,
&buffer_sync_handler_, &socket_handler_,
&core_intf_);
DisplayError error = buffer_allocator_.Init();
if (error != kErrorNone) {
DLOGE("Buffer allocaor initialization failed. Error = %d", error);
return -EINVAL;
}
error = CoreInterface::CreateCore(HWCDebugHandler::Get(), &buffer_allocator_,
&buffer_sync_handler_, &socket_handler_, &core_intf_);
if (error != kErrorNone) {
buffer_allocator_.Deinit();
DLOGE("Display core initialization failed. Error = %d", error);
return -EINVAL;
}
@ -172,6 +184,7 @@ int HWCSession::Init() {
if (error != kErrorNone) {
g_hwc_uevent_.Register(nullptr);
CoreInterface::DestroyCore();
buffer_allocator_.Deinit();
DLOGE("Primary display type not recognized. Error = %d", error);
return -EINVAL;
}
@ -181,8 +194,7 @@ int HWCSession::Init() {
hdmi_is_primary_ = true;
// Create display if it is connected, else wait for hotplug connect event.
if (hw_disp_info.is_connected) {
status = HWCDisplayExternal::Create(core_intf_, &buffer_allocator_, &callbacks_, qservice_,
&hwc_display_[HWC_DISPLAY_PRIMARY]);
status = CreateExternalDisplay(HWC_DISPLAY_PRIMARY);
}
} else {
// Create and power on primary display
@ -197,6 +209,7 @@ int HWCSession::Init() {
if (status) {
g_hwc_uevent_.Register(nullptr);
CoreInterface::DestroyCore();
buffer_allocator_.Deinit();
return status;
}
@ -214,6 +227,10 @@ int HWCSession::Init() {
}
int HWCSession::Deinit() {
Locker::SequenceCancelScopeLock lock_v(locker_[HWC_DISPLAY_VIRTUAL]);
Locker::SequenceCancelScopeLock lock_e(locker_[HWC_DISPLAY_EXTERNAL]);
Locker::SequenceCancelScopeLock lock_p(locker_[HWC_DISPLAY_PRIMARY]);
HWCDisplay *primary_display = hwc_display_[HWC_DISPLAY_PRIMARY];
if (primary_display) {
if (hdmi_is_primary_) {
@ -239,8 +256,6 @@ int HWCSession::Deinit() {
}
int HWCSession::Open(const hw_module_t *module, const char *name, hw_device_t **device) {
SCOPE_LOCK(locker_);
if (!module || !name || !device) {
DLOGE("Invalid parameters.");
return -EINVAL;
@ -265,8 +280,6 @@ int HWCSession::Open(const hw_module_t *module, const char *name, hw_device_t **
}
int HWCSession::Close(hw_device_t *device) {
SCOPE_LOCK(locker_);
if (!device) {
return -EINVAL;
}
@ -281,6 +294,10 @@ int HWCSession::Close(hw_device_t *device) {
void HWCSession::GetCapabilities(struct hwc2_device *device, uint32_t *outCount,
int32_t *outCapabilities) {
if (!outCount) {
return;
}
int value = 0;
bool disable_skip_validate = false;
if (Debug::Get()->GetProperty("sdm.debug.disable_skip_validate", &value) == kErrorNone) {
@ -307,24 +324,37 @@ static hwc2_function_pointer_t AsFP(T function) {
// Defined in the same order as in the HWC2 header
int32_t HWCSession::AcceptDisplayChanges(hwc2_device_t *device, hwc2_display_t display) {
SCOPE_LOCK(locker_);
if (display >= HWC_NUM_DISPLAY_TYPES) {
return HWC2_ERROR_BAD_DISPLAY;
}
SCOPE_LOCK(locker_[display]);
return HWCSession::CallDisplayFunction(device, display, &HWCDisplay::AcceptDisplayChanges);
}
int32_t HWCSession::CreateLayer(hwc2_device_t *device, hwc2_display_t display,
hwc2_layer_t *out_layer_id) {
SCOPE_LOCK(locker_);
if (!out_layer_id) {
return HWC2_ERROR_BAD_PARAMETER;
}
if (display >= HWC_NUM_DISPLAY_TYPES) {
return HWC2_ERROR_BAD_DISPLAY;
}
SEQUENCE_WAIT_SCOPE_LOCK(locker_[display]);
return CallDisplayFunction(device, display, &HWCDisplay::CreateLayer, out_layer_id);
}
int32_t HWCSession::CreateVirtualDisplay(hwc2_device_t *device, uint32_t width, uint32_t height,
int32_t *format, hwc2_display_t *out_display_id) {
// TODO(user): Handle concurrency with HDMI
SCOPE_LOCK(locker_);
SCOPE_LOCK(locker_[HWC_DISPLAY_VIRTUAL]);
if (!device) {
return HWC2_ERROR_BAD_DISPLAY;
}
if (!out_display_id || !width || !height || !format) {
return HWC2_ERROR_BAD_PARAMETER;
}
HWCSession *hwc_session = static_cast<HWCSession *>(device);
auto status = hwc_session->CreateVirtualDisplayObject(width, height, format);
if (status == HWC2::Error::None) {
@ -339,16 +369,19 @@ int32_t HWCSession::CreateVirtualDisplay(hwc2_device_t *device, uint32_t width,
int32_t HWCSession::DestroyLayer(hwc2_device_t *device, hwc2_display_t display,
hwc2_layer_t layer) {
SCOPE_LOCK(locker_);
if (display >= HWC_NUM_DISPLAY_TYPES) {
return HWC2_ERROR_BAD_DISPLAY;
}
SEQUENCE_WAIT_SCOPE_LOCK(locker_[display]);
return CallDisplayFunction(device, display, &HWCDisplay::DestroyLayer, layer);
}
int32_t HWCSession::DestroyVirtualDisplay(hwc2_device_t *device, hwc2_display_t display) {
SCOPE_LOCK(locker_);
if (!device || display != HWC_DISPLAY_VIRTUAL) {
return HWC2_ERROR_BAD_DISPLAY;
}
SCOPE_LOCK(locker_[display]);
DLOGI("Destroying virtual display id:%" PRIu64, display);
auto *hwc_session = static_cast<HWCSession *>(device);
@ -362,9 +395,7 @@ int32_t HWCSession::DestroyVirtualDisplay(hwc2_device_t *device, hwc2_display_t
}
void HWCSession::Dump(hwc2_device_t *device, uint32_t *out_size, char *out_buffer) {
SCOPE_LOCK(locker_);
if (!device) {
if (!device || !out_size) {
return;
}
auto *hwc_session = static_cast<HWCSession *>(device);
@ -377,6 +408,7 @@ void HWCSession::Dump(hwc2_device_t *device, uint32_t *out_size, char *out_buffe
DumpInterface::GetDump(sdm_dump, 4096); // TODO(user): Fix this workaround
std::string s("");
for (int id = HWC_DISPLAY_PRIMARY; id <= HWC_DISPLAY_VIRTUAL; id++) {
SEQUENCE_WAIT_SCOPE_LOCK(locker_[id]);
if (hwc_session->hwc_display_[id]) {
s += hwc_session->hwc_display_[id]->Dump();
}
@ -395,6 +427,10 @@ static int32_t GetActiveConfig(hwc2_device_t *device, hwc2_display_t display,
static int32_t GetChangedCompositionTypes(hwc2_device_t *device, hwc2_display_t display,
uint32_t *out_num_elements, hwc2_layer_t *out_layers,
int32_t *out_types) {
// null_ptr check only for out_num_elements, as out_layers and out_types can be null.
if (!out_num_elements) {
return HWC2_ERROR_BAD_PARAMETER;
}
return HWCSession::CallDisplayFunction(device, display, &HWCDisplay::GetChangedCompositionTypes,
out_num_elements, out_layers, out_types);
}
@ -479,18 +515,38 @@ static int32_t GetReleaseFences(hwc2_device_t *device, hwc2_display_t display,
int32_t HWCSession::PresentDisplay(hwc2_device_t *device, hwc2_display_t display,
int32_t *out_retire_fence) {
HWCSession *hwc_session = static_cast<HWCSession *>(device);
bool notify_hotplug = false;
auto status = HWC2::Error::BadDisplay;
DTRACE_SCOPED();
if (!device) {
return HWC2_ERROR_BAD_DISPLAY;
{
SEQUENCE_EXIT_SCOPE_LOCK(locker_[display]);
if (!device) {
return HWC2_ERROR_BAD_DISPLAY;
}
// TODO(user): Handle virtual display/HDMI concurrency
if (hwc_session->hwc_display_[display]) {
status = hwc_session->hwc_display_[display]->Present(out_retire_fence);
// This is only indicative of how many times SurfaceFlinger posts
// frames to the display.
CALC_FPS();
}
}
// Handle Pending external display connection
if (hwc_session->external_pending_connect_ && (display == HWC_DISPLAY_PRIMARY)) {
Locker::ScopeLock lock_e(locker_[HWC_DISPLAY_EXTERNAL]);
Locker::ScopeLock lock_v(locker_[HWC_DISPLAY_VIRTUAL]);
if (!hwc_session->hwc_display_[HWC_DISPLAY_VIRTUAL]) {
DLOGD("Process pending external display connection");
hwc_session->ConnectDisplay(HWC_DISPLAY_EXTERNAL);
hwc_session->external_pending_connect_ = false;
notify_hotplug = true;
}
}
auto status = HWC2::Error::BadDisplay;
// TODO(user): Handle virtual display/HDMI concurrency
if (hwc_session->hwc_display_[display]) {
status = hwc_session->hwc_display_[display]->Present(out_retire_fence);
// This is only indicative of how many times SurfaceFlinger posts
// frames to the display.
CALC_FPS();
if (notify_hotplug) {
hwc_session->HotPlug(HWC_DISPLAY_EXTERNAL, HWC2::Connection::Connected);
}
return INT32(status);
@ -508,10 +564,11 @@ int32_t HWCSession::RegisterCallback(hwc2_device_t *device, int32_t descriptor,
auto error = hwc_session->callbacks_.Register(desc, callback_data, pointer);
DLOGD("Registering callback: %s", to_string(desc).c_str());
if (descriptor == HWC2_CALLBACK_HOTPLUG) {
if (hwc_session->hwc_display_[HWC_DISPLAY_PRIMARY] && !hwc_session->hdmi_is_primary_) {
if (hwc_session->hwc_display_[HWC_DISPLAY_PRIMARY]) {
hwc_session->callbacks_.Hotplug(HWC_DISPLAY_PRIMARY, HWC2::Connection::Connected);
}
}
hwc_session->need_invalidate_ = false;
hwc_session->callbacks_lock_.Broadcast();
return INT32(error);
}
@ -531,14 +588,14 @@ static int32_t SetClientTarget(hwc2_device_t *device, hwc2_display_t display,
int32_t HWCSession::SetColorMode(hwc2_device_t *device, hwc2_display_t display,
int32_t /*android_color_mode_t*/ int_mode) {
auto mode = static_cast<android_color_mode_t>(int_mode);
SCOPE_LOCK(locker_);
SCOPE_LOCK(locker_[display]);
return HWCSession::CallDisplayFunction(device, display, &HWCDisplay::SetColorMode, mode);
}
int32_t HWCSession::SetColorTransform(hwc2_device_t *device, hwc2_display_t display,
const float *matrix,
int32_t /*android_color_transform_t*/ hint) {
SCOPE_LOCK(locker_);
SCOPE_LOCK(locker_[display]);
android_color_transform_t transform_hint = static_cast<android_color_transform_t>(hint);
return HWCSession::CallDisplayFunction(device, display, &HWCDisplay::SetColorTransform, matrix,
transform_hint);
@ -624,7 +681,7 @@ static int32_t SetLayerVisibleRegion(hwc2_device_t *device, hwc2_display_t displ
int32_t HWCSession::SetLayerZOrder(hwc2_device_t *device, hwc2_display_t display,
hwc2_layer_t layer, uint32_t z) {
SCOPE_LOCK(locker_);
SCOPE_LOCK(locker_[display]);
return CallDisplayFunction(device, display, &HWCDisplay::SetLayerZOrder, layer, z);
}
@ -638,6 +695,7 @@ int32_t HWCSession::SetOutputBuffer(hwc2_device_t *device, hwc2_display_t displa
return HWC2_ERROR_UNSUPPORTED;
}
SCOPE_LOCK(locker_[display]);
auto *hwc_session = static_cast<HWCSession *>(device);
if (hwc_session->hwc_display_[display]) {
auto vds = reinterpret_cast<HWCDisplayVirtual *>(hwc_session->hwc_display_[display]);
@ -650,7 +708,7 @@ int32_t HWCSession::SetOutputBuffer(hwc2_device_t *device, hwc2_display_t displa
int32_t HWCSession::SetPowerMode(hwc2_device_t *device, hwc2_display_t display, int32_t int_mode) {
auto mode = static_cast<HWC2::PowerMode>(int_mode);
SCOPE_LOCK(locker_);
SEQUENCE_WAIT_SCOPE_LOCK(locker_[display]);
return CallDisplayFunction(device, display, &HWCDisplay::SetPowerMode, mode);
}
@ -662,7 +720,6 @@ static int32_t SetVsyncEnabled(hwc2_device_t *device, hwc2_display_t display, in
int32_t HWCSession::ValidateDisplay(hwc2_device_t *device, hwc2_display_t display,
uint32_t *out_num_types, uint32_t *out_num_requests) {
DTRACE_SCOPED();
SCOPE_LOCK(locker_);
HWCSession *hwc_session = static_cast<HWCSession *>(device);
if (!device) {
return HWC2_ERROR_BAD_DISPLAY;
@ -671,32 +728,36 @@ int32_t HWCSession::ValidateDisplay(hwc2_device_t *device, hwc2_display_t displa
// TODO(user): Handle secure session, handle QDCM solid fill
// Handle external_pending_connect_ in CreateVirtualDisplay
auto status = HWC2::Error::BadDisplay;
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();
{
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]);
}
}
if (hwc_session->need_invalidate_) {
hwc_session->Refresh(display);
}
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);
// Handle pending external display connection
if (hwc_session->external_pending_connect_ && !hwc_session->hwc_display_[HWC_DISPLAY_VIRTUAL]) {
DLOGE("Process pending external display connection");
hwc_session->ConnectDisplay(HWC_DISPLAY_EXTERNAL);
hwc_session->external_pending_connect_ = false;
hwc_session->HotPlug(HWC_DISPLAY_EXTERNAL, HWC2::Connection::Connected);
status = hwc_session->hwc_display_[display]->Validate(out_num_types, out_num_requests);
}
}
// If validate fails, cancel the sequence lock so that other operations
// (such as Dump or SetPowerMode) may succeed without blocking on the condition
if (status == HWC2::Error::BadDisplay) {
SEQUENCE_CANCEL_SCOPE_LOCK(locker_[display]);
}
return INT32(status);
}
@ -825,8 +886,7 @@ int32_t HWCSession::ConnectDisplay(int disp) {
hwc_display_[HWC_DISPLAY_PRIMARY]->GetFrameBufferResolution(&primary_width, &primary_height);
if (disp == HWC_DISPLAY_EXTERNAL) {
status = HWCDisplayExternal::Create(core_intf_, &buffer_allocator_, &callbacks_, primary_width,
primary_height, qservice_, false, &hwc_display_[disp]);
status = CreateExternalDisplay(disp, primary_width, primary_height);
} else {
DLOGE("Invalid display type");
return -1;
@ -1006,8 +1066,6 @@ android::status_t HWCSession::notifyCallback(uint32_t command, const android::Pa
android::status_t HWCSession::HandleGetDisplayAttributesForConfig(const android::Parcel
*input_parcel,
android::Parcel *output_parcel) {
SCOPE_LOCK(locker_);
int config = input_parcel->readInt32();
int dpy = input_parcel->readInt32();
int error = android::BAD_VALUE;
@ -1017,6 +1075,7 @@ android::status_t HWCSession::HandleGetDisplayAttributesForConfig(const android:
return android::BAD_VALUE;
}
SEQUENCE_WAIT_SCOPE_LOCK(locker_[dpy]);
if (hwc_display_[dpy]) {
error = hwc_display_[dpy]->GetDisplayAttributesForConfig(config, &display_attributes);
if (error == 0) {
@ -1033,7 +1092,7 @@ android::status_t HWCSession::HandleGetDisplayAttributesForConfig(const android:
}
android::status_t HWCSession::ConfigureRefreshRate(const android::Parcel *input_parcel) {
SCOPE_LOCK(locker_);
SEQUENCE_WAIT_SCOPE_LOCK(locker_[HWC_DISPLAY_PRIMARY]);
uint32_t operation = UINT32(input_parcel->readInt32());
HWCDisplay *hwc_display = hwc_display_[HWC_DISPLAY_PRIMARY];
@ -1059,20 +1118,19 @@ android::status_t HWCSession::ConfigureRefreshRate(const android::Parcel *input_
}
android::status_t HWCSession::SetDisplayMode(const android::Parcel *input_parcel) {
SCOPE_LOCK(locker_);
SEQUENCE_WAIT_SCOPE_LOCK(locker_[HWC_DISPLAY_PRIMARY]);
uint32_t mode = UINT32(input_parcel->readInt32());
return hwc_display_[HWC_DISPLAY_PRIMARY]->Perform(HWCDisplayPrimary::SET_DISPLAY_MODE, mode);
}
android::status_t HWCSession::SetMaxMixerStages(const android::Parcel *input_parcel) {
SCOPE_LOCK(locker_);
DisplayError error = kErrorNone;
std::bitset<32> bit_mask_display_type = UINT32(input_parcel->readInt32());
uint32_t max_mixer_stages = UINT32(input_parcel->readInt32());
if (bit_mask_display_type[HWC_DISPLAY_PRIMARY]) {
SEQUENCE_WAIT_SCOPE_LOCK(locker_[HWC_DISPLAY_PRIMARY]);
if (hwc_display_[HWC_DISPLAY_PRIMARY]) {
error = hwc_display_[HWC_DISPLAY_PRIMARY]->SetMaxMixerStages(max_mixer_stages);
if (error != kErrorNone) {
@ -1082,6 +1140,7 @@ android::status_t HWCSession::SetMaxMixerStages(const android::Parcel *input_par
}
if (bit_mask_display_type[HWC_DISPLAY_EXTERNAL]) {
SEQUENCE_WAIT_SCOPE_LOCK(locker_[HWC_DISPLAY_EXTERNAL]);
if (hwc_display_[HWC_DISPLAY_EXTERNAL]) {
error = hwc_display_[HWC_DISPLAY_EXTERNAL]->SetMaxMixerStages(max_mixer_stages);
if (error != kErrorNone) {
@ -1091,6 +1150,7 @@ android::status_t HWCSession::SetMaxMixerStages(const android::Parcel *input_par
}
if (bit_mask_display_type[HWC_DISPLAY_VIRTUAL]) {
SEQUENCE_WAIT_SCOPE_LOCK(locker_[HWC_DISPLAY_VIRTUAL]);
if (hwc_display_[HWC_DISPLAY_VIRTUAL]) {
error = hwc_display_[HWC_DISPLAY_VIRTUAL]->SetMaxMixerStages(max_mixer_stages);
if (error != kErrorNone) {
@ -1103,25 +1163,26 @@ android::status_t HWCSession::SetMaxMixerStages(const android::Parcel *input_par
}
void HWCSession::SetFrameDumpConfig(const android::Parcel *input_parcel) {
SCOPE_LOCK(locker_);
uint32_t frame_dump_count = UINT32(input_parcel->readInt32());
std::bitset<32> bit_mask_display_type = UINT32(input_parcel->readInt32());
uint32_t bit_mask_layer_type = UINT32(input_parcel->readInt32());
if (bit_mask_display_type[HWC_DISPLAY_PRIMARY]) {
SEQUENCE_WAIT_SCOPE_LOCK(locker_[HWC_DISPLAY_PRIMARY]);
if (hwc_display_[HWC_DISPLAY_PRIMARY]) {
hwc_display_[HWC_DISPLAY_PRIMARY]->SetFrameDumpConfig(frame_dump_count, bit_mask_layer_type);
}
}
if (bit_mask_display_type[HWC_DISPLAY_EXTERNAL]) {
SEQUENCE_WAIT_SCOPE_LOCK(locker_[HWC_DISPLAY_EXTERNAL]);
if (hwc_display_[HWC_DISPLAY_EXTERNAL]) {
hwc_display_[HWC_DISPLAY_EXTERNAL]->SetFrameDumpConfig(frame_dump_count, bit_mask_layer_type);
}
}
if (bit_mask_display_type[HWC_DISPLAY_VIRTUAL]) {
SEQUENCE_WAIT_SCOPE_LOCK(locker_[HWC_DISPLAY_VIRTUAL]);
if (hwc_display_[HWC_DISPLAY_VIRTUAL]) {
hwc_display_[HWC_DISPLAY_VIRTUAL]->SetFrameDumpConfig(frame_dump_count, bit_mask_layer_type);
}
@ -1129,8 +1190,6 @@ void HWCSession::SetFrameDumpConfig(const android::Parcel *input_parcel) {
}
android::status_t HWCSession::SetMixerResolution(const android::Parcel *input_parcel) {
SCOPE_LOCK(locker_);
DisplayError error = kErrorNone;
uint32_t dpy = UINT32(input_parcel->readInt32());
@ -1139,6 +1198,7 @@ android::status_t HWCSession::SetMixerResolution(const android::Parcel *input_pa
return -EINVAL;
}
SEQUENCE_WAIT_SCOPE_LOCK(locker_[HWC_DISPLAY_PRIMARY]);
if (!hwc_display_[HWC_DISPLAY_PRIMARY]) {
DLOGI("Primary display is not initialized");
return -EINVAL;
@ -1159,6 +1219,8 @@ android::status_t HWCSession::SetColorModeOverride(const android::Parcel *input_
auto display = static_cast<hwc2_display_t >(input_parcel->readInt32());
auto mode = static_cast<android_color_mode_t>(input_parcel->readInt32());
auto device = static_cast<hwc2_device_t *>(this);
SEQUENCE_WAIT_SCOPE_LOCK(locker_[display]);
auto err = CallDisplayFunction(device, display, &HWCDisplay::SetColorMode, mode);
if (err != HWC2_ERROR_NONE)
return -EINVAL;
@ -1166,7 +1228,7 @@ android::status_t HWCSession::SetColorModeOverride(const android::Parcel *input_
}
void HWCSession::DynamicDebug(const android::Parcel *input_parcel) {
SCOPE_LOCK(locker_);
// TODO(user): Do we really need a lock here?
int type = input_parcel->readInt32();
bool enable = (input_parcel->readInt32() > 0);
@ -1240,56 +1302,73 @@ android::status_t HWCSession::QdcmCMDHandler(const android::Parcel *input_parcel
return ret;
}
switch (pending_action.action) {
case kInvalidating:
Refresh(HWC_DISPLAY_PRIMARY);
break;
case kEnterQDCMMode:
ret = color_mgr_->EnableQDCMMode(true, hwc_display_[HWC_DISPLAY_PRIMARY]);
break;
case kExitQDCMMode:
ret = color_mgr_->EnableQDCMMode(false, hwc_display_[HWC_DISPLAY_PRIMARY]);
break;
case kApplySolidFill:
ret =
color_mgr_->SetSolidFill(pending_action.params, true, hwc_display_[HWC_DISPLAY_PRIMARY]);
Refresh(HWC_DISPLAY_PRIMARY);
break;
case kDisableSolidFill:
ret =
color_mgr_->SetSolidFill(pending_action.params, false, hwc_display_[HWC_DISPLAY_PRIMARY]);
Refresh(HWC_DISPLAY_PRIMARY);
break;
case kSetPanelBrightness:
brightness_value = reinterpret_cast<int32_t *>(resp_payload.payload);
if (brightness_value == NULL) {
DLOGE("Brightness value is Null");
return -EINVAL;
}
if (HWC_DISPLAY_PRIMARY == display_id)
ret = hwc_display_[HWC_DISPLAY_PRIMARY]->SetPanelBrightness(*brightness_value);
break;
case kEnableFrameCapture:
ret = color_mgr_->SetFrameCapture(pending_action.params, true,
hwc_display_[HWC_DISPLAY_PRIMARY]);
Refresh(HWC_DISPLAY_PRIMARY);
break;
case kDisableFrameCapture:
ret = color_mgr_->SetFrameCapture(pending_action.params, false,
hwc_display_[HWC_DISPLAY_PRIMARY]);
break;
case kConfigureDetailedEnhancer:
ret = color_mgr_->SetDetailedEnhancer(pending_action.params,
hwc_display_[HWC_DISPLAY_PRIMARY]);
Refresh(HWC_DISPLAY_PRIMARY);
break;
case kNoAction:
break;
default:
DLOGW("Invalid pending action = %d!", pending_action.action);
break;
}
int32_t action = pending_action.action;
int count = -1;
while (action > 0) {
count++;
int32_t bit = (action & 1);
action = action >> 1;
if (!bit)
continue;
DLOGV_IF(kTagQDCM, "pending action = %d", BITMAP(count));
switch (BITMAP(count)) {
case kInvalidating:
Refresh(HWC_DISPLAY_PRIMARY);
break;
case kEnterQDCMMode:
ret = color_mgr_->EnableQDCMMode(true, hwc_display_[HWC_DISPLAY_PRIMARY]);
break;
case kExitQDCMMode:
ret = color_mgr_->EnableQDCMMode(false, hwc_display_[HWC_DISPLAY_PRIMARY]);
break;
case kApplySolidFill:
ret = color_mgr_->SetSolidFill(pending_action.params,
true, hwc_display_[HWC_DISPLAY_PRIMARY]);
Refresh(HWC_DISPLAY_PRIMARY);
break;
case kDisableSolidFill:
ret = color_mgr_->SetSolidFill(pending_action.params,
false, hwc_display_[HWC_DISPLAY_PRIMARY]);
Refresh(HWC_DISPLAY_PRIMARY);
break;
case kSetPanelBrightness:
brightness_value = reinterpret_cast<int32_t *>(resp_payload.payload);
if (brightness_value == NULL) {
DLOGE("Brightness value is Null");
return -EINVAL;
}
if (HWC_DISPLAY_PRIMARY == display_id)
ret = hwc_display_[HWC_DISPLAY_PRIMARY]->SetPanelBrightness(*brightness_value);
break;
case kEnableFrameCapture:
ret = color_mgr_->SetFrameCapture(pending_action.params, true,
hwc_display_[HWC_DISPLAY_PRIMARY]);
Refresh(HWC_DISPLAY_PRIMARY);
break;
case kDisableFrameCapture:
ret = color_mgr_->SetFrameCapture(pending_action.params, false,
hwc_display_[HWC_DISPLAY_PRIMARY]);
break;
case kConfigureDetailedEnhancer:
ret = color_mgr_->SetDetailedEnhancer(pending_action.params,
hwc_display_[HWC_DISPLAY_PRIMARY]);
Refresh(HWC_DISPLAY_PRIMARY);
break;
case kModeSet:
ret = static_cast<int>
(hwc_display_[HWC_DISPLAY_PRIMARY]->RestoreColorTransform());
Refresh(HWC_DISPLAY_PRIMARY);
break;
case kNoAction:
break;
default:
DLOGW("Invalid pending action = %d!", pending_action.action);
break;
}
}
// for display API getter case, marshall returned params into out_parcel.
output_parcel->writeInt32(ret);
HWCColorManager::MarshallStructIntoParcel(resp_payload, output_parcel);
@ -1301,7 +1380,7 @@ android::status_t HWCSession::QdcmCMDHandler(const android::Parcel *input_parcel
}
void HWCSession::UEventHandler(const char *uevent_data, int length) {
if (strcasestr(HWC_UEVENT_SWITCH_HDMI, uevent_data)) {
if (!strcasecmp(uevent_data, HWC_UEVENT_SWITCH_HDMI)) {
DLOGI("Uevent HDMI = %s", uevent_data);
int connected = GetEventValue(uevent_data, length, "SWITCH_STATE=");
if (connected >= 0) {
@ -1310,7 +1389,7 @@ void HWCSession::UEventHandler(const char *uevent_data, int length) {
DLOGE("Failed handling Hotplug = %s", connected ? "connected" : "disconnected");
}
}
} else if (strcasestr(HWC_UEVENT_GRAPHICS_FB0, uevent_data)) {
} else if (!strcasecmp(uevent_data, HWC_UEVENT_GRAPHICS_FB0)) {
DLOGI("Uevent FB0 = %s", uevent_data);
int panel_reset = GetEventValue(uevent_data, length, "PANEL_ALIVE=");
if (panel_reset == 0) {
@ -1364,31 +1443,34 @@ int HWCSession::HotPlugHandler(bool connected) {
// To prevent sending events to client while a lock is held, acquire scope locks only within
// below scope so that those get automatically unlocked after the scope ends.
do {
SCOPE_LOCK(locker_);
// If HDMI is primary but not created yet (first time), create it and notify surfaceflinger.
// if it is already created, but got disconnected/connected again,
// just toggle display status and do not notify surfaceflinger.
// If HDMI is not primary, create/destroy external display normally.
if (hdmi_is_primary_) {
SCOPE_LOCK(locker_[HWC_DISPLAY_PRIMARY]);
if (hwc_display_[HWC_DISPLAY_PRIMARY]) {
status = hwc_display_[HWC_DISPLAY_PRIMARY]->SetState(connected);
} else {
status = HWCDisplayExternal::Create(core_intf_, &buffer_allocator_, &callbacks_,
qservice_, &hwc_display_[HWC_DISPLAY_PRIMARY]);
status = CreateExternalDisplay(HWC_DISPLAY_PRIMARY);
notify_hotplug = true;
}
break;
}
// Primary display must be connected for HDMI as secondary cases.
if (!hwc_display_[HWC_DISPLAY_PRIMARY]) {
DLOGE("Primary display is not connected.");
return -1;
{
SCOPE_LOCK(locker_[HWC_DISPLAY_PRIMARY]);
// Primary display must be connected for HDMI as secondary cases.
if (!hwc_display_[HWC_DISPLAY_PRIMARY]) {
DLOGE("Primary display is not connected.");
return -1;
}
}
if (connected) {
SCOPE_LOCK(locker_[HWC_DISPLAY_EXTERNAL]);
Locker::ScopeLock lock_v(locker_[HWC_DISPLAY_VIRTUAL]);
// Connect external display if virtual display is not connected.
// Else, defer external display connection and process it when virtual display
// tears down; Do not notify SurfaceFlinger since connection is deferred now.
@ -1403,6 +1485,7 @@ int HWCSession::HotPlugHandler(bool connected) {
external_pending_connect_ = true;
}
} else {
SEQUENCE_WAIT_SCOPE_LOCK(locker_[HWC_DISPLAY_EXTERNAL]);
// Do not return error if external display is not in connected status.
// Due to virtual display concurrency, external display connection might be still pending
// but hdmi got disconnected before pending connection could be processed.
@ -1437,7 +1520,7 @@ int HWCSession::HotPlugHandler(bool connected) {
}
int HWCSession::GetVsyncPeriod(int disp) {
SCOPE_LOCK(locker_);
SCOPE_LOCK(locker_[disp]);
// default value
int32_t vsync_period = 1000000000l / 60;
auto attribute = HWC2::Attribute::VsyncPeriod;
@ -1451,14 +1534,12 @@ int HWCSession::GetVsyncPeriod(int disp) {
android::status_t HWCSession::GetVisibleDisplayRect(const android::Parcel *input_parcel,
android::Parcel *output_parcel) {
SCOPE_LOCK(locker_);
int dpy = input_parcel->readInt32();
if (dpy < HWC_DISPLAY_PRIMARY || dpy > HWC_DISPLAY_VIRTUAL) {
return android::BAD_VALUE;
}
SEQUENCE_WAIT_SCOPE_LOCK(locker_[dpy]);
if (!hwc_display_[dpy]) {
return android::NO_INIT;
}
@ -1495,4 +1576,26 @@ void HWCSession::HotPlug(hwc2_display_t display, HWC2::Connection state) {
}
}
int HWCSession::CreateExternalDisplay(int disp, uint32_t primary_width,
uint32_t primary_height, bool use_primary_res) {
uint32_t panel_bpp = 0;
uint32_t pattern_type = 0;
if (qdutils::isDPConnected()) {
qdutils::getDPTestConfig(&panel_bpp, &pattern_type);
}
if (panel_bpp && pattern_type) {
return HWCDisplayExternalTest::Create(core_intf_, &buffer_allocator_, &callbacks_,
qservice_, panel_bpp,
pattern_type, &hwc_display_[disp]);
}
if (use_primary_res) {
return HWCDisplayExternal::Create(core_intf_, &buffer_allocator_, &callbacks_,
primary_width, primary_height, qservice_,
use_primary_res, &hwc_display_[disp]);
} else {
return HWCDisplayExternal::Create(core_intf_, &buffer_allocator_, &callbacks_,
qservice_, &hwc_display_[disp]);
}
}
} // namespace sdm

View File

@ -78,6 +78,10 @@ class HWCSession : hwc2_device_t, HWCUEventListener, IDisplayConfig, public qCli
static int32_t CallDisplayFunction(hwc2_device_t *device, hwc2_display_t display,
HWC2::Error (HWCDisplay::*member)(Args...), Args... args) {
if (!device) {
return HWC2_ERROR_BAD_PARAMETER;
}
if (display >= HWC_NUM_DISPLAY_TYPES) {
return HWC2_ERROR_BAD_DISPLAY;
}
@ -167,6 +171,9 @@ class HWCSession : hwc2_device_t, HWCUEventListener, IDisplayConfig, public qCli
int32_t SetSecondaryDisplayStatus(int disp_id, HWCDisplay::DisplayStatus status);
int32_t GetPanelBrightness(int *level);
int32_t MinHdcpEncryptionLevelChanged(int disp_id, uint32_t min_enc_level);
int32_t CreateExternalDisplay(int disp, uint32_t primary_width = 0,
uint32_t primary_height = 0,
bool use_primary_res = false);
// service methods
void StartServices();
@ -218,7 +225,7 @@ class HWCSession : hwc2_device_t, HWCUEventListener, IDisplayConfig, public qCli
void Refresh(hwc2_display_t display);
void HotPlug(hwc2_display_t display, HWC2::Connection state);
static Locker locker_;
static Locker locker_[HWC_NUM_DISPLAY_TYPES];
CoreInterface *core_intf_ = nullptr;
HWCDisplay *hwc_display_[HWC_NUM_DISPLAY_TYPES] = {nullptr};
HWCCallbacks callbacks_;

View File

@ -92,12 +92,12 @@ HWCDisplay::DisplayStatus MapExternalStatus(IDisplayConfig::DisplayExternalStatu
// Methods from ::vendor::hardware::display::config::V1_0::IDisplayConfig follow.
Return<void> HWCSession::isDisplayConnected(IDisplayConfig::DisplayType dpy,
isDisplayConnected_cb _hidl_cb) {
SCOPE_LOCK(locker_);
int32_t error = -EINVAL;
bool connected = false;
int disp_id = MapDisplayType(dpy);
SEQUENCE_WAIT_SCOPE_LOCK(locker_[disp_id]);
if (disp_id >= 0) {
connected = hwc_display_[disp_id];
error = 0;
@ -109,12 +109,11 @@ Return<void> HWCSession::isDisplayConnected(IDisplayConfig::DisplayType dpy,
}
int32_t HWCSession::SetSecondaryDisplayStatus(int disp_id, HWCDisplay::DisplayStatus status) {
SCOPE_LOCK(locker_);
if (disp_id < 0) {
return -EINVAL;
}
SEQUENCE_WAIT_SCOPE_LOCK(locker_[disp_id]);
DLOGI("Display = %d, Status = %d", disp_id, status);
if (disp_id == HWC_DISPLAY_PRIMARY) {
@ -135,8 +134,7 @@ Return<int32_t> HWCSession::setSecondayDisplayStatus(IDisplayConfig::DisplayType
Return<int32_t> HWCSession::configureDynRefeshRate(IDisplayConfig::DisplayDynRefreshRateOp op,
uint32_t refreshRate) {
SCOPE_LOCK(locker_);
SEQUENCE_WAIT_SCOPE_LOCK(locker_[HWC_DISPLAY_PRIMARY]);
HWCDisplay *hwc_display = hwc_display_[HWC_DISPLAY_PRIMARY];
switch (op) {
@ -158,9 +156,13 @@ Return<int32_t> HWCSession::configureDynRefeshRate(IDisplayConfig::DisplayDynRef
}
int32_t HWCSession::GetConfigCount(int disp_id, uint32_t *count) {
SCOPE_LOCK(locker_);
if (disp_id < 0) {
return -EINVAL;
}
if (disp_id >= 0 && hwc_display_[disp_id]) {
SEQUENCE_WAIT_SCOPE_LOCK(locker_[disp_id]);
if (hwc_display_[disp_id]) {
return hwc_display_[disp_id]->GetDisplayConfigCount(count);
}
@ -178,9 +180,13 @@ Return<void> HWCSession::getConfigCount(IDisplayConfig::DisplayType dpy,
}
int32_t HWCSession::GetActiveConfigIndex(int disp_id, uint32_t *config) {
SCOPE_LOCK(locker_);
if (disp_id < 0) {
return -EINVAL;
}
if (disp_id >= 0 && hwc_display_[disp_id]) {
SEQUENCE_WAIT_SCOPE_LOCK(locker_[disp_id]);
if (hwc_display_[disp_id]) {
return hwc_display_[disp_id]->GetActiveDisplayConfig(config);
}
@ -198,12 +204,11 @@ Return<void> HWCSession::getActiveConfig(IDisplayConfig::DisplayType dpy,
}
int32_t HWCSession::SetActiveConfigIndex(int disp_id, uint32_t config) {
SCOPE_LOCK(locker_);
if (disp_id < 0) {
return -EINVAL;
}
SEQUENCE_WAIT_SCOPE_LOCK(locker_[disp_id]);
int32_t error = -EINVAL;
if (hwc_display_[disp_id]) {
error = hwc_display_[disp_id]->SetActiveDisplayConfig(config);
@ -222,12 +227,11 @@ Return<int32_t> HWCSession::setActiveConfig(IDisplayConfig::DisplayType dpy, uin
Return<void> HWCSession::getDisplayAttributes(uint32_t configIndex,
IDisplayConfig::DisplayType dpy,
getDisplayAttributes_cb _hidl_cb) {
SCOPE_LOCK(locker_);
int32_t error = -EINVAL;
IDisplayConfig::DisplayAttributes display_attributes = {};
int disp_id = MapDisplayType(dpy);
SEQUENCE_WAIT_SCOPE_LOCK(locker_[disp_id]);
if (disp_id >= 0 && hwc_display_[disp_id]) {
DisplayConfigVariableInfo hwc_display_attributes;
error = hwc_display_[disp_id]->GetDisplayAttributesForConfig(static_cast<int>(configIndex),
@ -247,9 +251,9 @@ Return<void> HWCSession::getDisplayAttributes(uint32_t configIndex,
}
Return<int32_t> HWCSession::setPanelBrightness(uint32_t level) {
SCOPE_LOCK(locker_);
SEQUENCE_WAIT_SCOPE_LOCK(locker_[HWC_DISPLAY_PRIMARY]);
int32_t error = -EINVAL;
if (hwc_display_[HWC_DISPLAY_PRIMARY]) {
error = hwc_display_[HWC_DISPLAY_PRIMARY]->SetPanelBrightness(static_cast<int>(level));
if (error) {
@ -261,8 +265,7 @@ Return<int32_t> HWCSession::setPanelBrightness(uint32_t level) {
}
int32_t HWCSession::GetPanelBrightness(int *level) {
SCOPE_LOCK(locker_);
SEQUENCE_WAIT_SCOPE_LOCK(locker_[HWC_DISPLAY_PRIMARY]);
int32_t error = -EINVAL;
if (hwc_display_[HWC_DISPLAY_PRIMARY]) {
@ -285,14 +288,13 @@ Return<void> HWCSession::getPanelBrightness(getPanelBrightness_cb _hidl_cb) {
}
int32_t HWCSession::MinHdcpEncryptionLevelChanged(int disp_id, uint32_t min_enc_level) {
SCOPE_LOCK(locker_);
DLOGI("Display %d", disp_id);
if (disp_id < 0) {
return -EINVAL;
}
SEQUENCE_WAIT_SCOPE_LOCK(locker_[disp_id]);
if (disp_id != HWC_DISPLAY_EXTERNAL) {
DLOGE("Not supported for display");
} else if (!hwc_display_[disp_id]) {
@ -310,16 +312,13 @@ Return<int32_t> HWCSession::minHdcpEncryptionLevelChanged(IDisplayConfig::Displa
}
Return<int32_t> HWCSession::refreshScreen() {
SCOPE_LOCK(locker_);
SEQUENCE_WAIT_SCOPE_LOCK(locker_[HWC_DISPLAY_PRIMARY]);
Refresh(HWC_DISPLAY_PRIMARY);
return 0;
}
int32_t HWCSession::ControlPartialUpdate(int disp_id, bool enable) {
SCOPE_LOCK(locker_);
if (disp_id < 0) {
return -EINVAL;
}
@ -329,6 +328,7 @@ int32_t HWCSession::ControlPartialUpdate(int disp_id, bool enable) {
return -EINVAL;
}
SEQUENCE_WAIT_SCOPE_LOCK(locker_[disp_id]);
HWCDisplay *hwc_display = hwc_display_[HWC_DISPLAY_PRIMARY];
if (!hwc_display) {
DLOGE("primary display object is not instantiated");
@ -352,7 +352,7 @@ int32_t HWCSession::ControlPartialUpdate(int disp_id, bool enable) {
Refresh(HWC_DISPLAY_PRIMARY);
// Wait until partial update control is complete
int32_t error = locker_.WaitFinite(kPartialUpdateControlTimeoutMs);
int32_t error = locker_[disp_id].WaitFinite(kPartialUpdateControlTimeoutMs);
return error;
}
@ -362,7 +362,7 @@ Return<int32_t> HWCSession::controlPartialUpdate(IDisplayConfig::DisplayType dpy
}
Return<int32_t> HWCSession::toggleScreenUpdate(bool on) {
SCOPE_LOCK(locker_);
SEQUENCE_WAIT_SCOPE_LOCK(locker_[HWC_DISPLAY_PRIMARY]);
int32_t error = -EINVAL;
if (hwc_display_[HWC_DISPLAY_PRIMARY]) {
@ -376,7 +376,7 @@ Return<int32_t> HWCSession::toggleScreenUpdate(bool on) {
}
Return<int32_t> HWCSession::setIdleTimeout(uint32_t value) {
SCOPE_LOCK(locker_);
SEQUENCE_WAIT_SCOPE_LOCK(locker_[HWC_DISPLAY_PRIMARY]);
if (hwc_display_[HWC_DISPLAY_PRIMARY]) {
hwc_display_[HWC_DISPLAY_PRIMARY]->SetIdleTimeoutMs(value);
@ -388,8 +388,6 @@ Return<int32_t> HWCSession::setIdleTimeout(uint32_t value) {
Return<void> HWCSession::getHDRCapabilities(IDisplayConfig::DisplayType dpy,
getHDRCapabilities_cb _hidl_cb) {
SCOPE_LOCK(locker_);
int32_t error = -EINVAL;
IDisplayConfig::DisplayHDRCapabilities hdr_caps = {};
@ -400,6 +398,7 @@ Return<void> HWCSession::getHDRCapabilities(IDisplayConfig::DisplayType dpy,
break;
}
SEQUENCE_WAIT_SCOPE_LOCK(locker_[disp_id]);
HWCDisplay *hwc_display = hwc_display_[disp_id];
if (!hwc_display) {
DLOGE("Display = %d is not connected.", disp_id);
@ -438,7 +437,7 @@ Return<void> HWCSession::getHDRCapabilities(IDisplayConfig::DisplayType dpy,
}
Return<int32_t> HWCSession::setCameraLaunchStatus(uint32_t on) {
SCOPE_LOCK(locker_);
SEQUENCE_WAIT_SCOPE_LOCK(locker_[HWC_DISPLAY_PRIMARY]);
HWBwModes mode = on > 0 ? kBwCamera : kBwDefault;
@ -457,7 +456,7 @@ Return<int32_t> HWCSession::setCameraLaunchStatus(uint32_t on) {
}
int32_t HWCSession::DisplayBWTransactionPending(bool *status) {
SCOPE_LOCK(locker_);
SEQUENCE_WAIT_SCOPE_LOCK(locker_[HWC_DISPLAY_PRIMARY]);
if (hwc_display_[HWC_DISPLAY_PRIMARY]) {
if (sync_wait(bw_mode_release_fd_, 0) < 0) {