hwc: HWC 2.0 implementation

Add HWCLayer, HWCCallbacks and implement HWC2 layer functionality.

Change-Id: Ic7764e72f4cae534e68764df4cf80eb3db982071
This commit is contained in:
Naseer Ahmed 2016-03-12 02:03:48 -05:00
parent c14b2088b0
commit b92e73fc10
22 changed files with 5707 additions and 1 deletions

4
.gitignore vendored Normal file
View File

@ -0,0 +1,4 @@
CMakeLists.txt
.idea/
.editorconfig
.clang-complete

View File

@ -2,7 +2,7 @@ display-hals := libgralloc libcopybit liblight libmemtrack libqservice libqdutil
display-hals += hdmi_cec
sdm-libs := sdm/libs
display-hals += $(sdm-libs)/utils $(sdm-libs)/core $(sdm-libs)/hwc
display-hals += $(sdm-libs)/utils $(sdm-libs)/core $(sdm-libs)/hwc $(sdm-libs)/hwc2
ifeq ($(call is-vendor-board-platform,QCOM),true)
include $(call all-named-subdir-makefiles,$(display-hals))

View File

@ -1,6 +1,8 @@
#Common headers
display_top := $(call my-dir)
use_hwc2 := false
common_includes := $(display_top)/libqdutils
common_includes += $(display_top)/libqservice
common_includes += $(display_top)/libcopybit

13
sdm/.clang-format Normal file
View File

@ -0,0 +1,13 @@
---
Language: Cpp
BasedOnStyle: Google
AllowShortIfStatementsOnASingleLine: false
AllowShortLoopsOnASingleLine: false
AllowShortFunctionsOnASingleLine: Inline
AllowShortBlocksOnASingleLine: false
ColumnLimit: 100
ConstructorInitializerAllOnOneLineOrOnePerLine: true
ConstructorInitializerIndentWidth: 4
DerivePointerAlignment: false
PointerAlignment: Right
#ReflowComments: false

View File

@ -45,6 +45,7 @@
#define DLOGV_IF(tag, format, ...) DLOG(tag, Verbose, format, ##__VA_ARGS__)
#define DLOGE(format, ...) DLOGE_IF(kTagNone, format, ##__VA_ARGS__)
#define DLOGD(format, ...) DLOGD_IF(kTagNone, format, ##__VA_ARGS__)
#define DLOGW(format, ...) DLOGW_IF(kTagNone, format, ##__VA_ARGS__)
#define DLOGI(format, ...) DLOGI_IF(kTagNone, format, ##__VA_ARGS__)
#define DLOGV(format, ...) DLOGV_IF(kTagNone, format, ##__VA_ARGS__)

View File

@ -1,6 +1,7 @@
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
include $(LOCAL_PATH)/../../../common.mk
ifeq ($(use_hwc2),false)
LOCAL_MODULE := hwcomposer.$(TARGET_BOARD_PLATFORM)
LOCAL_MODULE_RELATIVE_PATH := hw
@ -30,3 +31,4 @@ LOCAL_SRC_FILES := hwc_session.cpp \
cpuhint.cpp
include $(BUILD_SHARED_LIBRARY)
endif

37
sdm/libs/hwc2/Android.mk Normal file
View File

@ -0,0 +1,37 @@
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
include $(LOCAL_PATH)/../../../common.mk
ifeq ($(use_hwc2),true)
LOCAL_MODULE := hwcomposer.$(TARGET_BOARD_PLATFORM)
LOCAL_MODULE_RELATIVE_PATH := hw
LOCAL_MODULE_TAGS := optional
LOCAL_C_INCLUDES := $(common_includes)
LOCAL_CFLAGS := -Wno-missing-field-initializers -Wno-unused-parameter \
-std=c++11 -fcolor-diagnostics\
-DLOG_TAG=\"SDM\" $(common_flags) \
-I $(display_top)/sdm/libs/hwc
LOCAL_CLANG := true
LOCAL_SHARED_LIBRARIES := libsdmcore libqservice libbinder libhardware libhardware_legacy \
libutils libcutils libsync libmemalloc libqdutils libdl \
libpowermanager libsdmutils libc++
LOCAL_SRC_FILES := hwc_session.cpp \
hwc_display.cpp \
hwc_display_primary.cpp \
hwc_display_external.cpp \
hwc_display_virtual.cpp \
../hwc/hwc_debugger.cpp \
../hwc/hwc_buffer_allocator.cpp \
../hwc/hwc_buffer_sync_handler.cpp \
hwc_color_manager.cpp \
hwc_layers.cpp \
hwc_callbacks.cpp \
../hwc/blit_engine_c2d.cpp \
../hwc/cpuhint.cpp
include $(BUILD_SHARED_LIBRARY)
endif

View File

@ -0,0 +1,76 @@
/*
* Copyright (c) 2016, The Linux Foundation. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following
* disclaimer in the documentation and/or other materials provided
* with the distribution.
* * Neither the name of The Linux Foundation. nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
* OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
* IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <utils/constants.h>
#include <utils/debug.h>
#include "hwc_callbacks.h"
#define __CLASS__ "HWCCallbacks"
namespace sdm {
void HWCCallbacks::Hotplug(hwc2_display_t display, HWC2::Connection state) {
if (hotplug_) {
hotplug_(hotplug_data_, display, INT32(state));
}
}
void HWCCallbacks::Refresh(hwc2_display_t display) {
if (refresh_) {
refresh_(refresh_data_, display);
}
}
void HWCCallbacks::Vsync(hwc2_display_t display, int64_t timestamp) {
if (vsync_) {
vsync_(vsync_data_, display, timestamp);
}
}
HWC2::Error HWCCallbacks::Register(HWC2::Callback descriptor, hwc2_callback_data_t callback_data,
hwc2_function_pointer_t pointer) {
switch (descriptor) {
case HWC2::Callback::Hotplug:
hotplug_data_ = callback_data;
hotplug_ = reinterpret_cast<HWC2_PFN_HOTPLUG>(pointer);
break;
case HWC2::Callback::Refresh:
refresh_data_ = callback_data;
refresh_ = reinterpret_cast<HWC2_PFN_REFRESH>(pointer);
break;
case HWC2::Callback::Vsync:
vsync_data_ = callback_data;
vsync_ = reinterpret_cast<HWC2_PFN_VSYNC>(pointer);
break;
default:
return HWC2::Error::BadParameter;
}
return HWC2::Error::None;
}
} // namespace sdm

View File

@ -0,0 +1,61 @@
/*
* Copyright (c) 2016, 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_CALLBACKS_H__
#define __HWC_CALLBACKS_H__
#define HWC2_INCLUDE_STRINGIFICATION
#define HWC2_USE_CPP11
#include <hardware/hwcomposer2.h>
#undef HWC2_INCLUDE_STRINGIFICATION
#undef HWC2_USE_CPP11
namespace sdm {
class HWCCallbacks {
public:
void Hotplug(hwc2_display_t display, HWC2::Connection state);
void Refresh(hwc2_display_t display);
void Vsync(hwc2_display_t display, int64_t timestamp);
HWC2::Error Register(HWC2::Callback, hwc2_callback_data_t callback_data,
hwc2_function_pointer_t pointer);
private:
hwc2_callback_data_t hotplug_data_ = nullptr;
hwc2_callback_data_t refresh_data_ = nullptr;
hwc2_callback_data_t vsync_data_ = nullptr;
HWC2_PFN_HOTPLUG hotplug_ = nullptr;
HWC2_PFN_REFRESH refresh_ = nullptr;
HWC2_PFN_VSYNC vsync_ = nullptr;
};
} // namespace sdm
#endif // __HWC_CALLBACKS_H__

View File

@ -0,0 +1,564 @@
/*
* Copyright (c) 2015 - 2016, 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 <dlfcn.h>
#include <powermanager/IPowerManager.h>
#include <cutils/sockets.h>
#include <cutils/native_handle.h>
#include <utils/String16.h>
#include <binder/Parcel.h>
#include <gralloc_priv.h>
#include <hardware/hwcomposer.h>
#include <hardware/hwcomposer_defs.h>
#include <QService.h>
#include <core/dump_interface.h>
#include <utils/constants.h>
#include <utils/debug.h>
#include <core/buffer_allocator.h>
#include <private/color_params.h>
#include "hwc_buffer_allocator.h"
#include "hwc_buffer_sync_handler.h"
#include "hwc_session.h"
#include "hwc_debugger.h"
#define __CLASS__ "HWCColorManager"
namespace sdm {
uint32_t HWCColorManager::Get8BitsARGBColorValue(const PPColorFillParams &params) {
uint32_t argb_color = ((params.color.r << 16) & 0xff0000) | ((params.color.g) & 0xff) |
((params.color.b << 8) & 0xff00);
return argb_color;
}
int HWCColorManager::CreatePayloadFromParcel(const android::Parcel &in, uint32_t *disp_id,
PPDisplayAPIPayload *sink) {
int ret = 0;
uint32_t id(0);
uint32_t size(0);
id = UINT32(in.readInt32());
size = UINT32(in.readInt32());
if (size > 0 && size == in.dataAvail()) {
const void *data = in.readInplace(size);
const uint8_t *temp = reinterpret_cast<const uint8_t *>(data);
sink->size = size;
sink->payload = const_cast<uint8_t *>(temp);
*disp_id = id;
} else {
DLOGW("Failing size checking, size = %d", size);
ret = -EINVAL;
}
return ret;
}
void HWCColorManager::MarshallStructIntoParcel(const PPDisplayAPIPayload &data,
android::Parcel *out_parcel) {
out_parcel->writeInt32(INT32(data.size));
if (data.payload)
out_parcel->write(data.payload, data.size);
}
HWCColorManager *HWCColorManager::CreateColorManager() {
HWCColorManager *color_mgr = new HWCColorManager();
if (color_mgr) {
void *&color_lib = color_mgr->color_apis_lib_;
// Load display API interface library. And retrieve color API function tables.
color_lib = ::dlopen(DISPLAY_API_INTERFACE_LIBRARY_NAME, RTLD_NOW);
if (color_lib) {
color_mgr->color_apis_ = ::dlsym(color_lib, DISPLAY_API_FUNC_TABLES);
if (!color_mgr->color_apis_) {
DLOGE("Fail to retrieve = %s from %s", DISPLAY_API_FUNC_TABLES,
DISPLAY_API_INTERFACE_LIBRARY_NAME);
::dlclose(color_lib);
delete color_mgr;
return NULL;
}
} else {
DLOGW("Unable to load = %s", DISPLAY_API_INTERFACE_LIBRARY_NAME);
delete color_mgr;
return NULL;
}
DLOGI("Successfully loaded %s", DISPLAY_API_INTERFACE_LIBRARY_NAME);
// Load diagclient library and invokes its entry point to pass in display APIs.
void *&diag_lib = color_mgr->diag_client_lib_;
diag_lib = ::dlopen(QDCM_DIAG_CLIENT_LIBRARY_NAME, RTLD_NOW);
if (diag_lib) {
*(reinterpret_cast<void **>(&color_mgr->qdcm_diag_init_)) =
::dlsym(diag_lib, INIT_QDCM_DIAG_CLIENT_NAME);
*(reinterpret_cast<void **>(&color_mgr->qdcm_diag_deinit_)) =
::dlsym(diag_lib, DEINIT_QDCM_DIAG_CLIENT_NAME);
if (!color_mgr->qdcm_diag_init_ || !color_mgr->qdcm_diag_deinit_) {
DLOGE("Fail to retrieve = %s from %s", INIT_QDCM_DIAG_CLIENT_NAME,
QDCM_DIAG_CLIENT_LIBRARY_NAME);
::dlclose(diag_lib);
} else {
// invoke Diag Client entry point to initialize.
color_mgr->qdcm_diag_init_(color_mgr->color_apis_);
DLOGI("Successfully loaded %s and %s and diag_init'ed", DISPLAY_API_INTERFACE_LIBRARY_NAME,
QDCM_DIAG_CLIENT_LIBRARY_NAME);
}
} else {
DLOGW("Unable to load = %s", QDCM_DIAG_CLIENT_LIBRARY_NAME);
// only QDCM Diag client failed to be loaded and system still should function.
}
} else {
DLOGE("Unable to create HWCColorManager");
return NULL;
}
return color_mgr;
}
HWCColorManager::~HWCColorManager() {
}
void HWCColorManager::DestroyColorManager() {
if (qdcm_mode_mgr_) {
delete qdcm_mode_mgr_;
}
if (qdcm_diag_deinit_) {
qdcm_diag_deinit_();
}
if (diag_client_lib_) {
::dlclose(diag_client_lib_);
}
if (color_apis_lib_) {
::dlclose(color_apis_lib_);
}
delete this;
}
int HWCColorManager::EnableQDCMMode(bool enable, HWCDisplay *hwc_display) {
int ret = 0;
if (!qdcm_mode_mgr_) {
qdcm_mode_mgr_ = HWCQDCMModeManager::CreateQDCMModeMgr();
if (!qdcm_mode_mgr_) {
DLOGE("Unable to create QDCM operating mode manager.");
ret = -EFAULT;
}
}
if (qdcm_mode_mgr_) {
ret = qdcm_mode_mgr_->EnableQDCMMode(enable, hwc_display);
}
return ret;
}
bool HWCColorManager::SolidFillLayersPrepare(hwc_display_contents_1_t **displays,
HWCDisplay *hwc_display) {
SCOPE_LOCK(locker_);
// Query HWCColorManager if QDCM tool requesting SOLID_FILL mode.
uint32_t solid_fill_color = Get8BitsARGBColorValue(solid_fill_params_);
hwc_display_contents_1_t *layer_list = displays[HWC_DISPLAY_PRIMARY];
if (solid_fill_enable_ && solid_fill_layers_ && layer_list) {
// 1. shallow copy HWC_FRAMEBUFFER_TARGET layer info solid fill layer list.
solid_fill_layers_->hwLayers[1] = layer_list->hwLayers[layer_list->numHwLayers - 1];
// 2. continue the prepare<> on solid_fill_layers.
hwc_display->Perform(HWCDisplayPrimary::SET_QDCM_SOLID_FILL_INFO, solid_fill_color);
// TODO(user): Remove the display_contents generated here and
// use the solid fill layer support in HWC2 to set this up
// hwc_display->Prepare(solid_fill_layers_); // RECT info included.
// 3. Set HWC_OVERLAY to all SF layers before returning to framework.
for (size_t i = 0; i < (layer_list->numHwLayers - 1); i++) {
hwc_layer_1_t *layer = &layer_list->hwLayers[i];
layer->compositionType = HWC_OVERLAY;
}
return true;
} else if (!solid_fill_enable_) {
hwc_display->Perform(HWCDisplayPrimary::UNSET_QDCM_SOLID_FILL_INFO, 0);
}
return false;
}
bool HWCColorManager::SolidFillLayersSet(hwc_display_contents_1_t **displays,
HWCDisplay *hwc_display) {
// Query HWCColorManager if QDCM tool requesting SOLID_FILL mode.
SCOPE_LOCK(locker_);
hwc_display_contents_1_t *layer_list = displays[HWC_DISPLAY_PRIMARY];
if (solid_fill_enable_ && solid_fill_layers_ && layer_list) {
// TODO(user): Present solid fill
// hwc_display->Commit(solid_fill_layers_);
// SurfaceFlinger layer stack is dropped in solid fill case and replaced with local layer stack
// Close acquire fence fds associated with SF layer stack
// Close release/retire fence fds returned along with local layer stack
for (size_t i = 0; i < (layer_list->numHwLayers - 1); i++) {
int &fence_fd = layer_list->hwLayers[i].acquireFenceFd;
if (fence_fd >= 0) {
close(fence_fd);
fence_fd = -1;
}
}
for (size_t i = 0; i < (solid_fill_layers_->numHwLayers - 1); i++) {
int &fence_fd = solid_fill_layers_->hwLayers[i].releaseFenceFd;
if (fence_fd >= 0) {
close(fence_fd);
fence_fd = -1;
}
}
if (solid_fill_layers_->retireFenceFd >= 0) {
close(solid_fill_layers_->retireFenceFd);
solid_fill_layers_->retireFenceFd = -1;
}
return true;
}
return false;
}
int HWCColorManager::CreateSolidFillLayers(HWCDisplay *hwc_display) {
int ret = 0;
if (!solid_fill_layers_) {
uint32_t size = sizeof(hwc_display_contents_1) + kNumSolidFillLayers * sizeof(hwc_layer_1_t);
uint32_t primary_width = 0;
uint32_t primary_height = 0;
hwc_display->GetPanelResolution(&primary_width, &primary_height);
uint8_t *buf = new uint8_t[size]();
// handle for solid fill layer with fd = -1.
private_handle_t *handle = new private_handle_t(-1, 0, private_handle_t::PRIV_FLAGS_FRAMEBUFFER,
BUFFER_TYPE_UI, HAL_PIXEL_FORMAT_RGBA_8888,
INT32(primary_width), INT32(primary_height));
if (!buf || !handle) {
DLOGE("Failed to allocate memory.");
if (buf)
delete[] buf;
if (handle)
delete handle;
return -ENOMEM;
}
solid_fill_layers_ = reinterpret_cast<hwc_display_contents_1 *>(buf);
hwc_layer_1_t &layer = solid_fill_layers_->hwLayers[0];
layer.handle = handle;
}
solid_fill_layers_->flags = HWC_GEOMETRY_CHANGED;
solid_fill_layers_->numHwLayers = kNumSolidFillLayers;
solid_fill_layers_->retireFenceFd = -1;
solid_fill_layers_->outbuf = NULL;
solid_fill_layers_->outbufAcquireFenceFd = -1;
hwc_layer_1_t &layer = solid_fill_layers_->hwLayers[0];
hwc_rect_t solid_fill_rect = {
INT(solid_fill_params_.rect.x), INT(solid_fill_params_.rect.y),
solid_fill_params_.rect.x + INT(solid_fill_params_.rect.width),
solid_fill_params_.rect.y + INT(solid_fill_params_.rect.height),
};
layer.compositionType = HWC_FRAMEBUFFER;
layer.blending = HWC_BLENDING_PREMULT;
layer.sourceCropf.left = solid_fill_params_.rect.x;
layer.sourceCropf.top = solid_fill_params_.rect.y;
layer.sourceCropf.right = UINT32(solid_fill_params_.rect.x) + solid_fill_params_.rect.width;
layer.sourceCropf.bottom = UINT32(solid_fill_params_.rect.y) + solid_fill_params_.rect.height;
layer.acquireFenceFd = -1;
layer.releaseFenceFd = -1;
layer.flags = 0;
layer.transform = 0;
layer.hints = 0;
layer.planeAlpha = 0xff;
layer.displayFrame = solid_fill_rect;
layer.visibleRegionScreen.numRects = 1;
layer.visibleRegionScreen.rects = &layer.displayFrame;
layer.surfaceDamage.numRects = 0;
return ret;
}
void HWCColorManager::DestroySolidFillLayers() {
if (solid_fill_layers_) {
hwc_layer_1_t &layer = solid_fill_layers_->hwLayers[0];
uint8_t *buf = reinterpret_cast<uint8_t *>(solid_fill_layers_);
private_handle_t const *hnd = reinterpret_cast<private_handle_t const *>(layer.handle);
if (hnd)
delete hnd;
if (buf)
delete[] buf;
solid_fill_layers_ = NULL;
}
}
int HWCColorManager::SetSolidFill(const void *params, bool enable, HWCDisplay *hwc_display) {
SCOPE_LOCK(locker_);
int ret = 0;
if (params) {
solid_fill_params_ = *reinterpret_cast<const PPColorFillParams *>(params);
} else {
solid_fill_params_ = PPColorFillParams();
}
if (enable) {
// will create solid fill layers for rendering if not present.
ret = CreateSolidFillLayers(hwc_display);
} else {
DestroySolidFillLayers();
}
solid_fill_enable_ = enable;
return ret;
}
int HWCColorManager::SetFrameCapture(void *params, bool enable, HWCDisplay *hwc_display) {
SCOPE_LOCK(locker_);
int ret = 0;
PPFrameCaptureData *frame_capture_data = reinterpret_cast<PPFrameCaptureData *>(params);
if (enable) {
std::memset(&buffer_info, 0x00, sizeof(buffer_info));
hwc_display->GetFrameBufferResolution(&buffer_info.buffer_config.width,
&buffer_info.buffer_config.height);
if (frame_capture_data->input_params.out_pix_format == PP_PIXEL_FORMAT_RGB_888) {
buffer_info.buffer_config.format = kFormatRGB888;
} else if (frame_capture_data->input_params.out_pix_format == PP_PIXEL_FORMAT_RGB_2101010) {
// TODO(user): Complete the implementation
DLOGE("RGB 10-bit format NOT supported");
return -EFAULT;
} else {
DLOGE("Pixel-format: %d NOT support.", frame_capture_data->input_params.out_pix_format);
return -EFAULT;
}
buffer_info.buffer_config.buffer_count = 1;
buffer_info.alloc_buffer_info.fd = -1;
buffer_info.alloc_buffer_info.stride = 0;
buffer_info.alloc_buffer_info.size = 0;
buffer_allocator_ = new HWCBufferAllocator();
if (buffer_allocator_ == NULL) {
DLOGE("Memory allocation for buffer_allocator_ FAILED");
return -ENOMEM;
}
ret = buffer_allocator_->AllocateBuffer(&buffer_info);
if (ret != 0) {
DLOGE("Buffer allocation failed. ret: %d", ret);
delete[] buffer_allocator_;
buffer_allocator_ = NULL;
return -ENOMEM;
} else {
void *buffer = 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);
frame_capture_data->buffer = NULL;
ret = buffer_allocator_->FreeBuffer(&buffer_info);
delete[] buffer_allocator_;
buffer_allocator_ = NULL;
return -EFAULT;
} else {
frame_capture_data->buffer = reinterpret_cast<uint8_t *>(buffer);
frame_capture_data->buffer_stride = buffer_info.alloc_buffer_info.stride;
frame_capture_data->buffer_size = buffer_info.alloc_buffer_info.size;
}
// TODO(user): Call HWC interface to provide the buffer and rectangle information
}
} else {
if (frame_capture_data->buffer != NULL) {
if (munmap(frame_capture_data->buffer, buffer_info.alloc_buffer_info.size) != 0) {
DLOGE("munmap failed. err = %d", errno);
}
}
if (buffer_allocator_ != NULL) {
std::memset(frame_capture_data, 0x00, sizeof(PPFrameCaptureData));
ret = buffer_allocator_->FreeBuffer(&buffer_info);
if (ret != 0) {
DLOGE("FreeBuffer failed. ret = %d", ret);
}
delete[] buffer_allocator_;
buffer_allocator_ = NULL;
}
}
return ret;
}
const HWCQDCMModeManager::ActiveFeatureCMD HWCQDCMModeManager::kActiveFeatureCMD[] = {
HWCQDCMModeManager::ActiveFeatureCMD("cabl:on", "cabl:off", "cabl:status", "running"),
HWCQDCMModeManager::ActiveFeatureCMD("ad:on", "ad:off", "ad:query:status", "running"),
HWCQDCMModeManager::ActiveFeatureCMD("svi:on", "svi:off", "svi:status", "running"),
};
const char *const HWCQDCMModeManager::kSocketName = "pps";
const char *const HWCQDCMModeManager::kTagName = "surfaceflinger";
const char *const HWCQDCMModeManager::kPackageName = "colormanager";
HWCQDCMModeManager *HWCQDCMModeManager::CreateQDCMModeMgr() {
HWCQDCMModeManager *mode_mgr = new HWCQDCMModeManager();
if (!mode_mgr) {
DLOGW("No memory to create HWCQDCMModeManager.");
return NULL;
} else {
mode_mgr->socket_fd_ =
::socket_local_client(kSocketName, ANDROID_SOCKET_NAMESPACE_RESERVED, SOCK_STREAM);
if (mode_mgr->socket_fd_ < 0) {
// it should not be disastrous and we still can grab wakelock in QDCM mode.
DLOGW("Unable to connect to dpps socket!");
}
// retrieve system GPU idle timeout value for later to recover.
mode_mgr->entry_timeout_ = UINT32(HWCDebugHandler::GetIdleTimeoutMs());
// acquire the binder handle to Android system PowerManager for later use.
android::sp<android::IBinder> binder =
android::defaultServiceManager()->checkService(android::String16("power"));
if (binder == NULL) {
DLOGW("Application can't connect to power manager service");
delete mode_mgr;
mode_mgr = NULL;
} else {
mode_mgr->power_mgr_ = android::interface_cast<android::IPowerManager>(binder);
}
}
return mode_mgr;
}
HWCQDCMModeManager::~HWCQDCMModeManager() {
if (socket_fd_ >= 0)
::close(socket_fd_);
}
int HWCQDCMModeManager::AcquireAndroidWakeLock(bool enable) {
int ret = 0;
if (enable) {
if (wakelock_token_ == NULL) {
android::sp<android::IBinder> binder = new android::BBinder();
android::status_t status = power_mgr_->acquireWakeLock(
(kFullWakeLock | kAcquireCauseWakeup | kONAfterRelease), binder,
android::String16(kTagName), android::String16(kPackageName));
if (status == android::NO_ERROR) {
wakelock_token_ = binder;
}
}
} else {
if (wakelock_token_ != NULL && power_mgr_ != NULL) {
power_mgr_->releaseWakeLock(wakelock_token_, 0);
wakelock_token_.clear();
wakelock_token_ = NULL;
}
}
return ret;
}
int HWCQDCMModeManager::EnableActiveFeatures(bool enable,
const HWCQDCMModeManager::ActiveFeatureCMD &cmds,
bool *was_running) {
int ret = 0;
ssize_t size = 0;
char response[kSocketCMDMaxLength] = {
0,
};
if (socket_fd_ < 0) {
DLOGW("No socket connection available!");
return -EFAULT;
}
if (!enable) { // if client requesting to disable it.
// query CABL status, if off, no action. keep the status.
size = ::write(socket_fd_, cmds.cmd_query_status, strlen(cmds.cmd_query_status));
if (size < 0) {
DLOGW("Unable to send data over socket %s", ::strerror(errno));
ret = -EFAULT;
} else {
size = ::read(socket_fd_, response, kSocketCMDMaxLength);
if (size < 0) {
DLOGW("Unable to read data over socket %s", ::strerror(errno));
ret = -EFAULT;
} else if (!strncmp(response, cmds.running, strlen(cmds.running))) {
*was_running = true;
}
}
if (*was_running) { // if was running, it's requested to disable it.
size = ::write(socket_fd_, cmds.cmd_off, strlen(cmds.cmd_off));
if (size < 0) {
DLOGW("Unable to send data over socket %s", ::strerror(errno));
ret = -EFAULT;
}
}
} else { // if was running, need enable it back.
if (*was_running) {
size = ::write(socket_fd_, cmds.cmd_on, strlen(cmds.cmd_on));
if (size < 0) {
DLOGW("Unable to send data over socket %s", ::strerror(errno));
ret = -EFAULT;
}
}
}
return ret;
}
int HWCQDCMModeManager::EnableQDCMMode(bool enable, HWCDisplay *hwc_display) {
int ret = 0;
ret = EnableActiveFeatures((enable ? false : true), kActiveFeatureCMD[kCABLFeature],
&cabl_was_running_);
ret = AcquireAndroidWakeLock(enable);
// if enter QDCM mode, disable GPU fallback idle timeout.
if (hwc_display) {
uint32_t timeout = enable ? 0 : entry_timeout_;
hwc_display->SetIdleTimeoutMs(timeout);
}
return ret;
}
} // namespace sdm

File diff suppressed because it is too large Load Diff

215
sdm/libs/hwc2/hwc_display.h Normal file
View File

@ -0,0 +1,215 @@
/*
* Copyright (c) 2014-2016, The Linux Foundation. All rights reserved.
* Not a Contribution.
*
* Copyright 2015 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef __HWC_DISPLAY_H__
#define __HWC_DISPLAY_H__
#include <hardware/hwcomposer.h>
#include <core/core_interface.h>
#include <qdMetaData.h>
#include <QService.h>
#include <private/color_params.h>
#include <map>
#include <set>
#include <queue>
#include <utility>
#include "hwc_callbacks.h"
#include "hwc_layers.h"
namespace sdm {
class BlitEngine;
// Subclasses set this to their type. This has to be different from DisplayType.
// This is to avoid RTTI and dynamic_cast
enum DisplayClass {
DISPLAY_CLASS_PRIMARY,
DISPLAY_CLASS_EXTERNAL,
DISPLAY_CLASS_VIRTUAL,
DISPLAY_CLASS_NULL
};
class HWCDisplay : public DisplayEventHandler {
public:
virtual ~HWCDisplay() {}
virtual int Init();
virtual int Deinit();
// Framebuffer configurations
virtual void SetIdleTimeoutMs(uint32_t timeout_ms);
virtual void SetFrameDumpConfig(uint32_t count, uint32_t bit_mask_layer_type);
virtual DisplayError SetMaxMixerStages(uint32_t max_mixer_stages);
virtual DisplayError ControlPartialUpdate(bool enable, uint32_t *pending);
virtual HWC2::PowerMode GetLastPowerMode();
virtual int SetFrameBufferResolution(uint32_t x_pixels, uint32_t y_pixels);
virtual void GetFrameBufferResolution(uint32_t *x_pixels, uint32_t *y_pixels);
virtual void GetPanelResolution(uint32_t *x_pixels, uint32_t *y_pixels);
virtual int SetDisplayStatus(uint32_t display_status);
virtual int OnMinHdcpEncryptionLevelChange(uint32_t min_enc_level);
virtual int Perform(uint32_t operation, ...);
virtual void SetSecureDisplay(bool secure_display_active);
// Captures frame output in the buffer specified by output_buffer_info. The API is
// non-blocking and the client is expected to check operation status later on.
// Returns -1 if the input is invalid.
virtual int FrameCaptureAsync(const BufferInfo &output_buffer_info, bool post_processed) {
return -1;
}
// Returns the status of frame capture operation requested with FrameCaptureAsync().
// -EAGAIN : No status obtain yet, call API again after another frame.
// < 0 : Operation happened but failed.
// 0 : Success.
virtual int GetFrameCaptureStatus() { return -EAGAIN; }
// Display Configurations
virtual int SetActiveDisplayConfig(int config);
virtual int GetActiveDisplayConfig(uint32_t *config);
virtual int GetDisplayConfigCount(uint32_t *count);
virtual int GetDisplayAttributesForConfig(int config, DisplayConfigVariableInfo *attributes);
int SetPanelBrightness(int level);
int GetPanelBrightness(int *level);
int ToggleScreenUpdates(bool enable);
int ColorSVCRequestRoute(const PPDisplayAPIPayload &in_payload, PPDisplayAPIPayload *out_payload,
PPPendingParams *pending_action);
DisplayClass GetDisplayClass();
int GetVisibleDisplayRect(hwc_rect_t *rect);
void BuildLayerStack(void);
HWCLayer *GetHWCLayer(hwc2_layer_t layer);
// HWC2 APIs
virtual HWC2::Error AcceptDisplayChanges(void);
virtual HWC2::Error GetActiveConfig(hwc2_config_t *out_config);
virtual HWC2::Error SetActiveConfig(hwc2_config_t config);
virtual HWC2::Error SetClientTarget(buffer_handle_t target, int32_t acquire_fence,
int32_t dataspace);
virtual HWC2::Error GetDisplayConfigs(uint32_t *out_num_configs, hwc2_config_t *out_configs);
virtual HWC2::Error GetDisplayAttribute(hwc2_config_t config, HWC2::Attribute attribute,
int32_t *out_value);
virtual HWC2::Error GetClientTargetSupport(uint32_t width, uint32_t height, int32_t format,
int32_t dataspace);
virtual HWC2::Error GetChangedCompositionTypes(uint32_t *out_num_elements,
hwc2_layer_t *out_layers, int32_t *out_types);
virtual HWC2::Error GetDisplayRequests(int32_t *out_display_requests, uint32_t *out_num_elements,
hwc2_layer_t *out_layers, int32_t *out_layer_requests);
virtual HWC2::Error GetDisplayName(uint32_t *out_size, char *out_name);
virtual HWC2::Error GetDisplayType(int32_t *out_type);
virtual HWC2::Error SetCursorPosition(hwc2_layer_t layer, int x, int y);
virtual HWC2::Error SetVsyncEnabled(HWC2::Vsync enabled);
virtual HWC2::Error SetPowerMode(HWC2::PowerMode mode);
virtual HWC2::Error CreateLayer(hwc2_layer_t *out_layer_id);
virtual HWC2::Error DestroyLayer(hwc2_layer_t layer_id);
virtual HWC2::Error SetLayerZOrder(hwc2_layer_t layer_id, uint32_t z);
virtual HWC2::Error Validate(uint32_t *out_num_types, uint32_t *out_num_requests) = 0;
virtual HWC2::Error GetReleaseFences(uint32_t *out_num_elements, hwc2_layer_t *out_layers,
int32_t *out_fences);
virtual HWC2::Error Present(int32_t *out_retire_fence) = 0;
protected:
enum DisplayStatus {
kDisplayStatusOffline = 0,
kDisplayStatusOnline,
kDisplayStatusPause,
kDisplayStatusResume,
};
// Maximum number of layers supported by display manager.
static const uint32_t kMaxLayerCount = 32;
HWCDisplay(CoreInterface *core_intf, HWCCallbacks *callbacks, DisplayType type, hwc2_display_t id,
bool needs_blit, qService::QService *qservice, DisplayClass display_class);
// DisplayEventHandler methods
virtual DisplayError VSync(const DisplayEventVSync &vsync);
virtual DisplayError Refresh();
virtual DisplayError CECMessage(char *message);
virtual void DumpOutputBuffer(const BufferInfo &buffer_info, void *base, int fence);
virtual HWC2::Error PrepareLayerStack(uint32_t *out_num_types, uint32_t *out_num_requests);
virtual HWC2::Error CommitLayerStack(void);
virtual HWC2::Error PostCommitLayerStack(int32_t *out_retire_fence);
LayerBufferFormat GetSDMFormat(const int32_t &source, const int flags);
const char *GetHALPixelFormatString(int format);
const char *GetDisplayString();
void ScaleDisplayFrame(hwc_rect_t *display_frame);
void MarkLayersForGPUBypass(void);
virtual void ApplyScanAdjustment(hwc_rect_t *display_frame);
bool NeedsFrameBufferRefresh(void);
bool SingleLayerUpdating(void);
uint32_t SanitizeRefreshRate(uint32_t req_refresh_rate);
virtual void CloseAcquireFds();
enum {
INPUT_LAYER_DUMP,
OUTPUT_LAYER_DUMP,
};
CoreInterface *core_intf_;
HWCCallbacks *callbacks_;
DisplayType type_;
hwc2_display_t id_;
bool needs_blit_ = false;
DisplayInterface *display_intf_ = NULL;
LayerStack layer_stack_;
HWCLayer *client_target_; // Also known as framebuffer target
std::map<hwc2_layer_t, HWCLayer *> layer_map_; // Look up by Id - TODO
std::multiset<HWCLayer *, SortLayersByZ> layer_set_; // Maintain a set sorted by Z
std::map<hwc2_layer_t, HWC2::Composition> layer_changes_;
std::map<hwc2_layer_t, HWC2::LayerRequest> layer_requests_;
bool flush_on_error_ = false;
bool flush_ = false;
uint32_t dump_frame_count_ = 0;
uint32_t dump_frame_index_ = 0;
bool dump_input_layers_ = false;
HWC2::PowerMode last_power_mode_;
bool swap_interval_zero_ = false;
DisplayConfigVariableInfo *framebuffer_config_ = NULL;
bool display_paused_ = false;
uint32_t min_refresh_rate_ = 0;
uint32_t max_refresh_rate_ = 0;
uint32_t current_refresh_rate_ = 0;
bool use_metadata_refresh_rate_ = false;
uint32_t metadata_refresh_rate_ = 0;
uint32_t force_refresh_rate_ = 0;
bool boot_animation_completed_ = false;
bool shutdown_pending_ = false;
bool use_blit_comp_ = false;
bool secure_display_active_ = false;
bool skip_prepare_ = false;
bool solid_fill_enable_ = false;
uint32_t solid_fill_color_ = 0;
LayerRect display_rect_;
bool validated_ = false;
private:
bool IsFrameBufferScaled();
void DumpInputBuffers(void);
BlitEngine *blit_engine_ = NULL;
qService::QService *qservice_ = NULL;
DisplayClass display_class_;
int32_t stored_retire_fence_;
uint32_t geometry_changes_ = GeometryChanges::kNone;
};
inline int HWCDisplay::Perform(uint32_t operation, ...) {
return 0;
}
} // namespace sdm
#endif // __HWC_DISPLAY_H__

View File

@ -0,0 +1,206 @@
/*
* Copyright (c) 2014 - 2016, 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 <utils/constants.h>
#include <utils/debug.h>
#include "hwc_display_external.h"
#include "hwc_debugger.h"
#define __CLASS__ "HWCDisplayExternal"
namespace sdm {
int HWCDisplayExternal::Create(CoreInterface *core_intf, HWCCallbacks *callbacks,
qService::QService *qservice, HWCDisplay **hwc_display) {
return Create(core_intf, callbacks, 0, 0, qservice, false, hwc_display);
}
int HWCDisplayExternal::Create(CoreInterface *core_intf, HWCCallbacks *callbacks,
uint32_t primary_width, uint32_t primary_height,
qService::QService *qservice, bool use_primary_res,
HWCDisplay **hwc_display) {
uint32_t external_width = 0;
uint32_t external_height = 0;
HWCDisplay *hwc_display_external = new HWCDisplayExternal(core_intf, callbacks, qservice);
int status = hwc_display_external->Init();
if (status) {
delete hwc_display_external;
return status;
}
hwc_display_external->GetPanelResolution(&external_width, &external_height);
if (primary_width && primary_height) {
// use_primary_res means HWCDisplayExternal should directly set framebuffer resolution to the
// provided primary_width and primary_height
if (use_primary_res) {
external_width = primary_width;
external_height = primary_height;
} else {
int downscale_enabled = 0;
HWCDebugHandler::Get()->GetProperty("sdm.debug.downscale_external", &downscale_enabled);
if (downscale_enabled) {
GetDownscaleResolution(primary_width, primary_height, &external_width, &external_height);
}
}
}
status = hwc_display_external->SetFrameBufferResolution(external_width, external_height);
if (status) {
Destroy(hwc_display_external);
return status;
}
*hwc_display = hwc_display_external;
return status;
}
void HWCDisplayExternal::Destroy(HWCDisplay *hwc_display) {
hwc_display->Deinit();
delete hwc_display;
}
HWCDisplayExternal::HWCDisplayExternal(CoreInterface *core_intf, HWCCallbacks *callbacks,
qService::QService *qservice)
: HWCDisplay(core_intf, callbacks, kHDMI, HWC_DISPLAY_EXTERNAL, false, qservice,
DISPLAY_CLASS_EXTERNAL) {
}
HWC2::Error HWCDisplayExternal::Validate(uint32_t *out_num_types, uint32_t *out_num_requests) {
auto status = HWC2::Error::None;
if (secure_display_active_) {
MarkLayersForGPUBypass();
return status;
}
BuildLayerStack();
if (layer_set_.empty()) {
flush_ = true;
return status;
}
status = PrepareLayerStack(out_num_types, out_num_requests);
return status;
}
HWC2::Error HWCDisplayExternal::Present(int32_t *out_retire_fence) {
auto status = HWC2::Error::None;
if (!secure_display_active_) {
status = HWCDisplay::CommitLayerStack();
if (status == HWC2::Error::None) {
status = HWCDisplay::PostCommitLayerStack(out_retire_fence);
}
}
CloseAcquireFds();
return status;
}
void HWCDisplayExternal::ApplyScanAdjustment(hwc_rect_t *display_frame) {
if (display_intf_->IsUnderscanSupported()) {
return;
}
// Read user defined width and height ratio
int width = 0, height = 0;
HWCDebugHandler::Get()->GetProperty("sdm.external_action_safe_width", &width);
float width_ratio = FLOAT(width) / 100.0f;
HWCDebugHandler::Get()->GetProperty("sdm.external_action_safe_height", &height);
float height_ratio = FLOAT(height) / 100.0f;
if (width_ratio == 0.0f || height_ratio == 0.0f) {
return;
}
uint32_t panel_width = 0;
uint32_t panel_height = 0;
GetPanelResolution(&panel_width, &panel_height);
if (panel_width == 0 || panel_height == 0) {
DLOGV("Invalid panel dimensions (%d, %d)", panel_width, panel_height);
return;
}
uint32_t new_panel_width = UINT32(panel_width * FLOAT(1.0f - width_ratio));
uint32_t new_panel_height = UINT32(panel_height * FLOAT(1.0f - height_ratio));
int x_offset = INT((FLOAT(panel_width) * width_ratio) / 2.0f);
int y_offset = INT((FLOAT(panel_height) * height_ratio) / 2.0f);
display_frame->left =
(display_frame->left * INT32(new_panel_width) / INT32(panel_width)) + x_offset;
display_frame->top =
(display_frame->top * INT32(new_panel_height) / INT32(panel_height)) + y_offset;
display_frame->right =
((display_frame->right * INT32(new_panel_width)) / INT32(panel_width)) + x_offset;
display_frame->bottom =
((display_frame->bottom * INT32(new_panel_height)) / INT32(panel_height)) + y_offset;
}
void HWCDisplayExternal::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;
}
static void AdjustSourceResolution(uint32_t dst_width, uint32_t dst_height, uint32_t *src_width,
uint32_t *src_height) {
*src_height = (dst_width * (*src_height)) / (*src_width);
*src_width = dst_width;
}
void HWCDisplayExternal::GetDownscaleResolution(uint32_t primary_width, uint32_t primary_height,
uint32_t *non_primary_width,
uint32_t *non_primary_height) {
uint32_t primary_area = primary_width * primary_height;
uint32_t non_primary_area = (*non_primary_width) * (*non_primary_height);
if (primary_area > non_primary_area) {
if (primary_height > primary_width) {
Swap(primary_height, primary_width);
}
AdjustSourceResolution(primary_width, primary_height, non_primary_width, non_primary_height);
}
}
} // namespace sdm

View File

@ -0,0 +1,59 @@
/*
* Copyright (c) 2014-2016, 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_H__
#define __HWC_DISPLAY_EXTERNAL_H__
#include "hwc_display.h"
namespace sdm {
class HWCDisplayExternal : public HWCDisplay {
public:
static int Create(CoreInterface *core_intf, HWCCallbacks *callbacks, uint32_t primary_width,
uint32_t primary_height, qService::QService *qservice, bool use_primary_res,
HWCDisplay **hwc_display);
static int Create(CoreInterface *core_intf, HWCCallbacks *callbacks, qService::QService *qservice,
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);
private:
HWCDisplayExternal(CoreInterface *core_intf, HWCCallbacks *callbacks,
qService::QService *qservice);
void ApplyScanAdjustment(hwc_rect_t *display_frame);
static void GetDownscaleResolution(uint32_t primary_width, uint32_t primary_height,
uint32_t *virtual_width, uint32_t *virtual_height);
};
} // namespace sdm
#endif // __HWC_DISPLAY_EXTERNAL_H__

View File

@ -0,0 +1,471 @@
/*
* Copyright (c) 2014 - 2016, 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 <sync/sync.h>
#include <utils/constants.h>
#include <utils/debug.h>
#include <stdarg.h>
#include <sys/mman.h>
#include "hwc_display_primary.h"
#include "hwc_debugger.h"
#define __CLASS__ "HWCDisplayPrimary"
namespace sdm {
int HWCDisplayPrimary::Create(CoreInterface *core_intf, BufferAllocator *buffer_allocator,
HWCCallbacks *callbacks, qService::QService *qservice,
HWCDisplay **hwc_display) {
int status = 0;
uint32_t primary_width = 0;
uint32_t primary_height = 0;
HWCDisplay *hwc_display_primary =
new HWCDisplayPrimary(core_intf, buffer_allocator, callbacks, qservice);
status = hwc_display_primary->Init();
if (status) {
delete hwc_display_primary;
return status;
}
hwc_display_primary->GetPanelResolution(&primary_width, &primary_height);
int width = 0, height = 0;
HWCDebugHandler::Get()->GetProperty("sdm.fb_size_width", &width);
HWCDebugHandler::Get()->GetProperty("sdm.fb_size_height", &height);
if (width > 0 && height > 0) {
primary_width = UINT32(width);
primary_height = UINT32(height);
}
status = hwc_display_primary->SetFrameBufferResolution(primary_width, primary_height);
if (status) {
Destroy(hwc_display_primary);
return status;
}
*hwc_display = hwc_display_primary;
return status;
}
void HWCDisplayPrimary::Destroy(HWCDisplay *hwc_display) {
hwc_display->Deinit();
delete hwc_display;
}
HWCDisplayPrimary::HWCDisplayPrimary(CoreInterface *core_intf, BufferAllocator *buffer_allocator,
HWCCallbacks *callbacks, qService::QService *qservice)
: HWCDisplay(core_intf, callbacks, kPrimary, HWC_DISPLAY_PRIMARY, true, qservice,
DISPLAY_CLASS_PRIMARY),
buffer_allocator_(buffer_allocator),
cpu_hint_(NULL) {
}
int HWCDisplayPrimary::Init() {
cpu_hint_ = new CPUHint();
if (cpu_hint_->Init(static_cast<HWCDebugHandler *>(HWCDebugHandler::Get())) != kErrorNone) {
delete cpu_hint_;
cpu_hint_ = NULL;
}
use_metadata_refresh_rate_ = true;
int disable_metadata_dynfps = 0;
HWCDebugHandler::Get()->GetProperty("persist.metadata_dynfps.disable", &disable_metadata_dynfps);
if (disable_metadata_dynfps) {
use_metadata_refresh_rate_ = false;
}
return HWCDisplay::Init();
}
void HWCDisplayPrimary::ProcessBootAnimCompleted() {
uint32_t numBootUpLayers = 0;
// TODO(user): Remove this hack
numBootUpLayers = static_cast<uint32_t>(Debug::GetBootAnimLayerCount());
if (numBootUpLayers == 0) {
numBootUpLayers = 2;
}
/* All other checks namely "init.svc.bootanim" or
* HWC_GEOMETRY_CHANGED fail in correctly identifying the
* exact bootup transition to homescreen
*/
char cryptoState[PROPERTY_VALUE_MAX];
char voldDecryptState[PROPERTY_VALUE_MAX];
bool isEncrypted = false;
bool main_class_services_started = false;
if (property_get("ro.crypto.state", cryptoState, "unencrypted")) {
if (!strcmp(cryptoState, "encrypted")) {
isEncrypted = true;
if (property_get("vold.decrypt", voldDecryptState, "") &&
!strcmp(voldDecryptState, "trigger_restart_framework"))
main_class_services_started = true;
}
}
if ((!isEncrypted || (isEncrypted && main_class_services_started)) &&
(layer_set_.size() > numBootUpLayers)) {
boot_animation_completed_ = true;
// Applying default mode after bootanimation is finished And
// If Data is Encrypted, it is ready for access.
if (display_intf_)
display_intf_->ApplyDefaultDisplayMode();
}
}
HWC2::Error HWCDisplayPrimary::Validate(uint32_t *out_num_types, uint32_t *out_num_requests) {
auto status = HWC2::Error::None;
DisplayError error = kErrorNone;
if (!boot_animation_completed_)
ProcessBootAnimCompleted();
if (display_paused_) {
MarkLayersForGPUBypass();
return status;
}
// Fill in the remaining blanks in the layers and add them to the SDM layerstack
BuildLayerStack();
bool pending_output_dump = dump_frame_count_ && dump_output_to_file_;
if (frame_capture_buffer_queued_ || pending_output_dump) {
// RHS values were set in FrameCaptureAsync() called from a binder thread. They are picked up
// here in a subsequent draw round.
layer_stack_.output_buffer = &output_buffer_;
layer_stack_.flags.post_processed_output = post_processed_output_;
}
bool one_updating_layer = SingleLayerUpdating();
ToggleCPUHint(one_updating_layer);
uint32_t refresh_rate = GetOptimalRefreshRate(one_updating_layer);
if (current_refresh_rate_ != refresh_rate) {
error = display_intf_->SetRefreshRate(refresh_rate);
}
if (error == kErrorNone) {
// On success, set current refresh rate to new refresh rate
current_refresh_rate_ = refresh_rate;
}
if (handle_idle_timeout_) {
handle_idle_timeout_ = false;
}
// TODO(user): Validate this
if (layer_set_.empty()) {
flush_ = true;
return status;
}
status = PrepareLayerStack(out_num_types, out_num_requests);
return status;
}
HWC2::Error HWCDisplayPrimary::Present(int32_t *out_retire_fence) {
auto status = HWC2::Error::None;
if (display_paused_) {
// TODO(user): From old HWC implementation
// If we do not handle the frame set retireFenceFd to outbufAcquireFenceFd
// Revisit this when validating display_paused
DisplayError error = display_intf_->Flush();
if (error != kErrorNone) {
DLOGE("Flush failed. Error = %d", error);
}
} else {
status = HWCDisplay::CommitLayerStack();
if (status == HWC2::Error::None) {
HandleFrameOutput();
status = HWCDisplay::PostCommitLayerStack(out_retire_fence);
}
}
CloseAcquireFds();
return status;
}
int HWCDisplayPrimary::Perform(uint32_t operation, ...) {
va_list args;
va_start(args, operation);
int val = va_arg(args, int32_t);
va_end(args);
switch (operation) {
case SET_METADATA_DYN_REFRESH_RATE:
SetMetaDataRefreshRateFlag(val);
break;
case SET_BINDER_DYN_REFRESH_RATE:
ForceRefreshRate(UINT32(val));
break;
case SET_DISPLAY_MODE:
SetDisplayMode(UINT32(val));
break;
case SET_QDCM_SOLID_FILL_INFO:
SetQDCMSolidFillInfo(true, UINT32(val));
break;
case UNSET_QDCM_SOLID_FILL_INFO:
SetQDCMSolidFillInfo(false, UINT32(val));
break;
default:
DLOGW("Invalid operation %d", operation);
return -EINVAL;
}
return 0;
}
DisplayError HWCDisplayPrimary::SetDisplayMode(uint32_t mode) {
DisplayError error = kErrorNone;
if (display_intf_) {
error = display_intf_->SetDisplayMode(mode);
}
return error;
}
void HWCDisplayPrimary::SetMetaDataRefreshRateFlag(bool enable) {
int disable_metadata_dynfps = 0;
HWCDebugHandler::Get()->GetProperty("persist.metadata_dynfps.disable", &disable_metadata_dynfps);
if (disable_metadata_dynfps) {
return;
}
use_metadata_refresh_rate_ = enable;
}
void HWCDisplayPrimary::SetQDCMSolidFillInfo(bool enable, uint32_t color) {
solid_fill_enable_ = enable;
solid_fill_color_ = color;
}
void HWCDisplayPrimary::ToggleCPUHint(bool set) {
if (!cpu_hint_) {
return;
}
if (set) {
cpu_hint_->Set();
} else {
cpu_hint_->Reset();
}
}
void HWCDisplayPrimary::SetSecureDisplay(bool secure_display_active) {
if (secure_display_active_ != secure_display_active) {
// Skip Prepare and call Flush for null commit
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;
}
void HWCDisplayPrimary::ForceRefreshRate(uint32_t refresh_rate) {
if ((refresh_rate && (refresh_rate < min_refresh_rate_ || refresh_rate > max_refresh_rate_)) ||
force_refresh_rate_ == refresh_rate) {
// Cannot honor force refresh rate, as its beyond the range or new request is same
return;
}
force_refresh_rate_ = refresh_rate;
callbacks_->Refresh(HWC_DISPLAY_PRIMARY);
return;
}
uint32_t HWCDisplayPrimary::GetOptimalRefreshRate(bool one_updating_layer) {
if (force_refresh_rate_) {
return force_refresh_rate_;
} else if (handle_idle_timeout_) {
return min_refresh_rate_;
} else if (use_metadata_refresh_rate_ && one_updating_layer && metadata_refresh_rate_) {
return metadata_refresh_rate_;
}
return max_refresh_rate_;
}
DisplayError HWCDisplayPrimary::Refresh() {
DisplayError error = kErrorNone;
callbacks_->Refresh(HWC_DISPLAY_PRIMARY);
handle_idle_timeout_ = true;
return error;
}
void HWCDisplayPrimary::SetIdleTimeoutMs(uint32_t timeout_ms) {
display_intf_->SetIdleTimeoutMs(timeout_ms);
}
static void SetLayerBuffer(const BufferInfo &output_buffer_info, LayerBuffer *output_buffer) {
output_buffer->width = output_buffer_info.buffer_config.width;
output_buffer->height = output_buffer_info.buffer_config.height;
output_buffer->format = output_buffer_info.buffer_config.format;
output_buffer->planes[0].fd = output_buffer_info.alloc_buffer_info.fd;
output_buffer->planes[0].stride = output_buffer_info.alloc_buffer_info.stride;
}
void HWCDisplayPrimary::HandleFrameOutput() {
if (frame_capture_buffer_queued_) {
HandleFrameCapture();
} else if (dump_output_to_file_) {
HandleFrameDump();
}
}
void HWCDisplayPrimary::HandleFrameCapture() {
if (output_buffer_.release_fence_fd >= 0) {
frame_capture_status_ = sync_wait(output_buffer_.release_fence_fd, 1000);
::close(output_buffer_.release_fence_fd);
output_buffer_.release_fence_fd = -1;
}
frame_capture_buffer_queued_ = false;
post_processed_output_ = false;
output_buffer_ = {};
uint32_t pending = 0; // Just a temporary to satisfy the API
ControlPartialUpdate(true /* enable */, &pending);
}
void HWCDisplayPrimary::HandleFrameDump() {
if (dump_frame_count_ && output_buffer_.release_fence_fd >= 0) {
int ret = sync_wait(output_buffer_.release_fence_fd, 1000);
::close(output_buffer_.release_fence_fd);
output_buffer_.release_fence_fd = -1;
if (ret < 0) {
DLOGE("sync_wait error errno = %d, desc = %s", errno, strerror(errno));
} else {
DumpOutputBuffer(output_buffer_info_, output_buffer_base_, layer_stack_.retire_fence_fd);
}
}
if (0 == dump_frame_count_) {
dump_output_to_file_ = false;
// Unmap and Free buffer
if (munmap(output_buffer_base_, output_buffer_info_.alloc_buffer_info.size) != 0) {
DLOGE("unmap failed with err %d", errno);
}
if (buffer_allocator_->FreeBuffer(&output_buffer_info_) != 0) {
DLOGE("FreeBuffer failed");
}
post_processed_output_ = false;
output_buffer_ = {};
output_buffer_info_ = {};
output_buffer_base_ = nullptr;
uint32_t pending = 0; // Just a temporary to satisfy the API
ControlPartialUpdate(true /* enable */, &pending);
}
}
void HWCDisplayPrimary::SetFrameDumpConfig(uint32_t count, uint32_t bit_mask_layer_type) {
HWCDisplay::SetFrameDumpConfig(count, bit_mask_layer_type);
dump_output_to_file_ = bit_mask_layer_type & (1 << OUTPUT_LAYER_DUMP);
DLOGI("output_layer_dump_enable %d", dump_output_to_file_);
if (!count || !dump_output_to_file_) {
return;
}
// Allocate and map output buffer
output_buffer_info_ = {};
// Since we dump DSPP output use Panel resolution.
GetPanelResolution(&output_buffer_info_.buffer_config.width,
&output_buffer_info_.buffer_config.height);
output_buffer_info_.buffer_config.format = kFormatRGB888;
output_buffer_info_.buffer_config.buffer_count = 1;
if (buffer_allocator_->AllocateBuffer(&output_buffer_info_) != 0) {
DLOGE("Buffer allocation failed");
output_buffer_info_ = {};
return;
}
void *buffer = mmap(NULL, output_buffer_info_.alloc_buffer_info.size, PROT_READ | PROT_WRITE,
MAP_SHARED, output_buffer_info_.alloc_buffer_info.fd, 0);
if (buffer == MAP_FAILED) {
DLOGE("mmap failed with err %d", errno);
buffer_allocator_->FreeBuffer(&output_buffer_info_);
output_buffer_info_ = {};
return;
}
output_buffer_base_ = buffer;
post_processed_output_ = true;
uint32_t pending = 0; // Just a temporary to satisfy the API
ControlPartialUpdate(false /* enable */, &pending);
}
int HWCDisplayPrimary::FrameCaptureAsync(const BufferInfo &output_buffer_info,
bool post_processed_output) {
// Note: This function is called in context of a binder thread and a lock is already held
if (output_buffer_info.alloc_buffer_info.fd < 0) {
DLOGE("Invalid fd %d", output_buffer_info.alloc_buffer_info.fd);
return -1;
}
auto panel_width = 0u;
auto panel_height = 0u;
auto fb_width = 0u;
auto fb_height = 0u;
GetPanelResolution(&panel_width, &panel_height);
GetFrameBufferResolution(&fb_width, &fb_height);
if (post_processed_output && (output_buffer_info_.buffer_config.width < panel_width ||
output_buffer_info_.buffer_config.height < panel_height)) {
DLOGE("Buffer dimensions should not be less than panel resolution");
return -1;
} else if (!post_processed_output && (output_buffer_info_.buffer_config.width < fb_width ||
output_buffer_info_.buffer_config.height < fb_height)) {
DLOGE("Buffer dimensions should not be less than FB resolution");
return -1;
}
SetLayerBuffer(output_buffer_info, &output_buffer_);
post_processed_output_ = post_processed_output;
frame_capture_buffer_queued_ = true;
// Status is only cleared on a new call to dump and remains valid otherwise
frame_capture_status_ = -EAGAIN;
uint32_t pending = 0; // Just a temporary to satisfy the API
ControlPartialUpdate(false /* enable */, &pending);
return 0;
}
} // namespace sdm

View File

@ -0,0 +1,97 @@
/*
* Copyright (c) 2014-2016, 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_PRIMARY_H__
#define __HWC_DISPLAY_PRIMARY_H__
#include "cpuhint.h"
#include "hwc_display.h"
namespace sdm {
class HWCDisplayPrimary : public HWCDisplay {
public:
enum {
SET_METADATA_DYN_REFRESH_RATE,
SET_BINDER_DYN_REFRESH_RATE,
SET_DISPLAY_MODE,
SET_QDCM_SOLID_FILL_INFO,
UNSET_QDCM_SOLID_FILL_INFO,
};
static int Create(CoreInterface *core_intf, BufferAllocator *buffer_allocator,
HWCCallbacks *callbacks, qService::QService *qservice,
HWCDisplay **hwc_display);
static void Destroy(HWCDisplay *hwc_display);
virtual int Init();
virtual HWC2::Error Validate(uint32_t *out_num_types, uint32_t *out_num_requests);
virtual HWC2::Error Present(int32_t *out_retire_fence);
virtual int Perform(uint32_t operation, ...);
virtual void SetSecureDisplay(bool secure_display_active);
virtual DisplayError Refresh();
virtual void SetIdleTimeoutMs(uint32_t timeout_ms);
virtual void SetFrameDumpConfig(uint32_t count, uint32_t bit_mask_layer_type);
virtual int FrameCaptureAsync(const BufferInfo &output_buffer_info, bool post_processed);
virtual int GetFrameCaptureStatus() { return frame_capture_status_; }
private:
HWCDisplayPrimary(CoreInterface *core_intf, BufferAllocator *buffer_allocator,
HWCCallbacks *callbacks, qService::QService *qservice);
void SetMetaDataRefreshRateFlag(bool enable);
virtual DisplayError SetDisplayMode(uint32_t mode);
void ProcessBootAnimCompleted(void);
void SetQDCMSolidFillInfo(bool enable, uint32_t color);
void ToggleCPUHint(bool set);
void ForceRefreshRate(uint32_t refresh_rate);
uint32_t GetOptimalRefreshRate(bool one_updating_layer);
void HandleFrameOutput();
void HandleFrameCapture();
void HandleFrameDump();
BufferAllocator *buffer_allocator_ = nullptr;
CPUHint *cpu_hint_ = nullptr;
bool handle_idle_timeout_ = false;
// Primary output buffer configuration
LayerBuffer output_buffer_ = {};
bool post_processed_output_ = false;
// Members for 1 frame capture in a client provided buffer
bool frame_capture_buffer_queued_ = false;
int frame_capture_status_ = -EAGAIN;
// Members for N frame output dump to file
bool dump_output_to_file_ = false;
BufferInfo output_buffer_info_ = {};
void *output_buffer_base_ = nullptr;
};
} // namespace sdm
#endif // __HWC_DISPLAY_PRIMARY_H__

View File

@ -0,0 +1,194 @@
/*
* Copyright (c) 2014 - 2016, The Linux Foundation. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following
* disclaimer in the documentation and/or other materials provided
* with the distribution.
* * Neither the name of The Linux Foundation nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
* OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
* IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <utils/constants.h>
#include <utils/debug.h>
#include <sync/sync.h>
#include <stdarg.h>
#include <gr.h>
#include "hwc_display_virtual.h"
#include "hwc_debugger.h"
#define __CLASS__ "HWCDisplayVirtual"
namespace sdm {
int HWCDisplayVirtual::Create(CoreInterface *core_intf, HWCCallbacks *callbacks, uint32_t width,
uint32_t height, HWCDisplay **hwc_display) {
int status = 0;
HWCDisplayVirtual *hwc_display_virtual = new HWCDisplayVirtual(core_intf, callbacks);
uint32_t virtual_width = 0, virtual_height = 0;
status = hwc_display_virtual->Init();
if (status) {
delete hwc_display_virtual;
return status;
}
status = INT32(hwc_display_virtual->SetPowerMode(HWC2::PowerMode::On));
if (status) {
Destroy(hwc_display_virtual);
return status;
}
hwc_display_virtual->GetPanelResolution(&virtual_width, &virtual_height);
status = hwc_display_virtual->SetFrameBufferResolution(width, height);
if (status) {
Destroy(hwc_display_virtual);
return status;
}
*hwc_display = static_cast<HWCDisplay *>(hwc_display_virtual);
return 0;
}
void HWCDisplayVirtual::Destroy(HWCDisplay *hwc_display) {
hwc_display->Deinit();
delete hwc_display;
}
HWCDisplayVirtual::HWCDisplayVirtual(CoreInterface *core_intf, HWCCallbacks *callbacks)
: HWCDisplay(core_intf, callbacks, kVirtual, HWC_DISPLAY_VIRTUAL, false, NULL,
DISPLAY_CLASS_VIRTUAL) {
}
int HWCDisplayVirtual::Init() {
return HWCDisplay::Init();
}
int HWCDisplayVirtual::Deinit() {
int status = 0;
status = HWCDisplay::Deinit();
return status;
}
HWC2::Error HWCDisplayVirtual::Validate(uint32_t *out_num_types, uint32_t *out_num_requests) {
auto status = HWC2::Error::None;
if (display_paused_) {
MarkLayersForGPUBypass();
return status;
}
BuildLayerStack();
status = PrepareLayerStack(out_num_types, out_num_requests);
return status;
}
HWC2::Error HWCDisplayVirtual::Present(int32_t *out_retire_fence) {
auto status = HWC2::Error::None;
if (display_paused_) {
DisplayError error = display_intf_->Flush();
if (error != kErrorNone) {
DLOGE("Flush failed. Error = %d", error);
}
} else {
status = HWCDisplay::CommitLayerStack();
if (status == HWC2::Error::None) {
if (dump_frame_count_ && !flush_ && dump_output_layer_) {
if (output_handle_ && output_handle_->base) {
BufferInfo buffer_info;
const private_handle_t *output_handle =
reinterpret_cast<const private_handle_t *>(output_buffer_->buffer_id);
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 =
GetSDMFormat(output_handle->format, output_handle->flags);
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);
}
}
status = HWCDisplay::PostCommitLayerStack(out_retire_fence);
}
}
CloseAcquireFds();
return status;
}
HWC2::Error HWCDisplayVirtual::SetOutputBuffer(buffer_handle_t buf, int32_t release_fence) {
const private_handle_t *output_handle = static_cast<const private_handle_t *>(buf);
// Fill output buffer parameters (width, height, format, plane information, fence)
output_buffer_->acquire_fence_fd = dup(release_fence);
if (output_handle) {
output_buffer_->buffer_id = reinterpret_cast<uint64_t>(output_handle);
int output_handle_format = output_handle->format;
if (output_handle_format == HAL_PIXEL_FORMAT_RGBA_8888) {
output_handle_format = HAL_PIXEL_FORMAT_RGBX_8888;
}
output_buffer_->format = GetSDMFormat(output_handle_format, output_handle->flags);
if (output_buffer_->format == kFormatInvalid) {
return HWC2::Error::BadParameter;
}
int output_buffer_width, output_buffer_height;
AdrenoMemInfo::getInstance().getAlignedWidthAndHeight(output_handle, output_buffer_width,
output_buffer_height);
output_buffer_->width = UINT32(output_buffer_width);
output_buffer_->height = UINT32(output_buffer_height);
// TODO(mkavm): Handle DRC and metadata changes
output_buffer_->flags.secure = 0;
output_buffer_->flags.video = 0;
// TZ Protected Buffer - L1
if (output_handle->flags & private_handle_t::PRIV_FLAGS_SECURE_BUFFER) {
output_buffer_->flags.secure = 1;
}
// ToDo: Need to extend for non-RGB formats
output_buffer_->planes[0].fd = output_handle->fd;
output_buffer_->planes[0].offset = output_handle->offset;
output_buffer_->planes[0].stride = UINT32(output_handle->width);
}
layer_stack_.output_buffer = output_buffer_;
return HWC2::Error::None;
}
void HWCDisplayVirtual::SetFrameDumpConfig(uint32_t count, uint32_t bit_mask_layer_type) {
HWCDisplay::SetFrameDumpConfig(count, bit_mask_layer_type);
dump_output_layer_ = ((bit_mask_layer_type & (1 << OUTPUT_LAYER_DUMP)) != 0);
DLOGI("output_layer_dump_enable %d", dump_output_layer_);
}
} // namespace sdm

View File

@ -0,0 +1,61 @@
/*
* Copyright (c) 2014-2016, 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_VIRTUAL_H__
#define __HWC_DISPLAY_VIRTUAL_H__
#include <qdMetaData.h>
#include <gralloc_priv.h>
#include "hwc_display.h"
namespace sdm {
class HWCDisplayVirtual : public HWCDisplay {
public:
static int Create(CoreInterface *core_intf, HWCCallbacks *callbacks, uint32_t primary_width,
uint32_t primary_height, HWCDisplay **hwc_display);
static void Destroy(HWCDisplay *hwc_display);
virtual int Init();
virtual int Deinit();
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 SetFrameDumpConfig(uint32_t count, uint32_t bit_mask_layer_type);
HWC2::Error SetOutputBuffer(buffer_handle_t buf, int32_t release_fence);
private:
HWCDisplayVirtual(CoreInterface *core_intf, HWCCallbacks *callbacks);
bool dump_output_layer_ = false;
LayerBuffer *output_buffer_ = NULL;
const private_handle_t *output_handle_ = nullptr;
};
} // namespace sdm
#endif // __HWC_DISPLAY_VIRTUAL_H__

View File

@ -0,0 +1,500 @@
/*
* Copyright (c) 2014-2016, The Linux Foundation. All rights reserved.
* Not a Contribution.
*
* Copyright 2015 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "hwc_layers.h"
#include <gr.h>
#include <utils/debug.h>
#include <cmath>
#define __CLASS__ "HWCLayer"
namespace sdm {
bool SortLayersByZ::operator()(const HWCLayer *lhs, const HWCLayer *rhs) {
return lhs->GetZ() < rhs->GetZ();
}
std::atomic<hwc2_layer_t> HWCLayer::next_id_(1);
// Layer operations
HWCLayer::HWCLayer(hwc2_display_t display_id) : id_(next_id_++), display_id_(display_id) {
layer_ = new Layer();
layer_->input_buffer = new LayerBuffer();
// Fences are deferred, so the first time this layer is presented, return -1
// TODO(user): Verify that fences are properly obtained on suspend/resume
release_fences_.push(-1);
}
HWCLayer::~HWCLayer() {
// Close any fences left for this layer
while (!release_fences_.empty()) {
close(release_fences_.front());
release_fences_.pop();
}
if (layer_) {
if (layer_->input_buffer) {
delete (layer_->input_buffer);
}
delete layer_;
}
}
HWC2::Error HWCLayer::SetLayerBuffer(buffer_handle_t buffer, int32_t acquire_fence) {
if (!buffer) {
DLOGE("Invalid buffer handle: %p on layer: %d", buffer, id_);
return HWC2::Error::BadParameter;
}
const private_handle_t *handle = static_cast<const private_handle_t *>(buffer);
LayerBuffer *layer_buffer = layer_->input_buffer;
layer_buffer->width = UINT32(handle->width);
layer_buffer->height = UINT32(handle->height);
layer_buffer->format = GetSDMFormat(handle->format, handle->flags);
if (SetMetaData(handle, layer_) != kErrorNone) {
return HWC2::Error::BadLayer;
}
if (handle->bufferType == BUFFER_TYPE_VIDEO) {
layer_buffer->flags.video = true;
}
// TZ Protected Buffer - L1
if (handle->flags & private_handle_t::PRIV_FLAGS_SECURE_BUFFER) {
layer_buffer->flags.secure = true;
}
if (handle->flags & private_handle_t::PRIV_FLAGS_SECURE_DISPLAY) {
layer_buffer->flags.secure_display = true;
}
layer_buffer->planes[0].fd = handle->fd;
layer_buffer->planes[0].offset = handle->offset;
layer_buffer->planes[0].stride = UINT32(handle->width);
layer_buffer->acquire_fence_fd = acquire_fence;
layer_buffer->buffer_id = reinterpret_cast<uint64_t>(handle);
return HWC2::Error::None;
}
HWC2::Error HWCLayer::SetLayerSurfaceDamage(hwc_region_t damage) {
auto num_dirty_rects = damage.numRects;
if (num_dirty_rects > 0) {
for (uint32_t i = 0; i <= damage.numRects; i++) {
LayerRect rect;
SetRect(damage.rects[i], &rect);
layer_->dirty_regions.push_back(rect);
}
}
return HWC2::Error::None;
}
HWC2::Error HWCLayer::SetLayerBlendMode(HWC2::BlendMode mode) {
switch (mode) {
case HWC2::BlendMode::Coverage:
layer_->blending = kBlendingCoverage;
break;
case HWC2::BlendMode::Premultiplied:
layer_->blending = kBlendingPremultiplied;
break;
case HWC2::BlendMode::None:
layer_->blending = kBlendingOpaque;
break;
default:
return HWC2::Error::BadParameter;
}
geometry_changes_ |= kBlendMode;
return HWC2::Error::None;
}
HWC2::Error HWCLayer::SetLayerColor(hwc_color_t color) {
layer_->solid_fill_color = GetUint32Color(color);
layer_->input_buffer->format = kFormatARGB8888;
DLOGD("Layer color set to: %u", layer_->solid_fill_color);
DLOGD("[%" PRIu64 "][%" PRIu64 "] Layer color set to %u %" PRIu64, display_id_, id_,
layer_->solid_fill_color);
return HWC2::Error::None;
}
HWC2::Error HWCLayer::SetLayerCompositionType(HWC2::Composition type) {
layer_->flags = {}; // Reset earlier flags
composition_ = type; // Used to compute changes
switch (type) {
case HWC2::Composition::Client:
layer_->flags.skip = true;
break;
case HWC2::Composition::Device:
// We try and default to this in SDM
break;
case HWC2::Composition::SolidColor:
layer_->flags.solid_fill = true;
break;
case HWC2::Composition::Cursor:
layer_->flags.cursor = true;
break;
case HWC2::Composition::Invalid:
return HWC2::Error::BadParameter;
default:
return HWC2::Error::Unsupported;
}
// TODO(user): Check if this should be set here or somewhere else
layer_->flags.updating = true;
return HWC2::Error::None;
}
HWC2::Error HWCLayer::SetLayerDataspace(int32_t dataspace) {
// TODO(user): Implement later
geometry_changes_ |= kDataspace;
return HWC2::Error::None;
}
HWC2::Error HWCLayer::SetLayerDisplayFrame(hwc_rect_t frame) {
SetRect(frame, &layer_->dst_rect);
geometry_changes_ |= kDisplayFrame;
return HWC2::Error::None;
}
HWC2::Error HWCLayer::SetLayerPlaneAlpha(float alpha) {
// Conversion of float alpha in range 0.0 to 1.0 similar to the HWC Adapter
layer_->plane_alpha = static_cast<uint8_t>(255.0f * alpha + 0.5f);
geometry_changes_ |= kPlaneAlpha;
return HWC2::Error::None;
}
HWC2::Error HWCLayer::SetLayerSourceCrop(hwc_frect_t crop) {
SetRect(crop, &layer_->src_rect);
geometry_changes_ |= kSourceCrop;
return HWC2::Error::None;
}
HWC2::Error HWCLayer::SetLayerTransform(HWC2::Transform transform) {
switch (transform) {
case HWC2::Transform::FlipH:
layer_->transform.flip_horizontal = true;
break;
case HWC2::Transform::FlipV:
layer_->transform.flip_vertical = true;
break;
case HWC2::Transform::Rotate90:
layer_->transform.rotation = 90.0f;
break;
case HWC2::Transform::Rotate180:
layer_->transform.rotation = 180.0f;
break;
case HWC2::Transform::Rotate270:
layer_->transform.rotation = 270.0f;
break;
case HWC2::Transform::FlipHRotate90:
layer_->transform.rotation = 90.0f;
layer_->transform.flip_horizontal = true;
break;
case HWC2::Transform::FlipVRotate90:
layer_->transform.rotation = 90.0f;
layer_->transform.flip_vertical = true;
break;
default:
layer_->transform.rotation = 0.0f;
layer_->transform.flip_horizontal = false;
layer_->transform.flip_vertical = false;
}
geometry_changes_ |= kTransform;
return HWC2::Error::None;
}
HWC2::Error HWCLayer::SetLayerVisibleRegion(hwc_region_t visible) {
auto num_dirty_rects = visible.numRects;
if (num_dirty_rects > 0) {
for (uint32_t i = 0; i <= visible.numRects; i++) {
LayerRect rect;
SetRect(visible.rects[i], &rect);
layer_->visible_regions.push_back(rect);
}
}
return HWC2::Error::None;
}
HWC2::Error HWCLayer::SetLayerZOrder(uint32_t z) {
z_ = z;
geometry_changes_ |= kZOrder;
return HWC2::Error::None;
}
void HWCLayer::SetRect(const hwc_rect_t &source, LayerRect *target) {
target->left = FLOAT(source.left);
target->top = FLOAT(source.top);
target->right = FLOAT(source.right);
target->bottom = FLOAT(source.bottom);
}
void HWCLayer::SetRect(const hwc_frect_t &source, LayerRect *target) {
// Recommended way of rounding as in hwcomposer2.h - SetLayerSourceCrop
target->left = std::ceil(source.left);
target->top = std::ceil(source.top);
target->right = std::floor(source.right);
target->bottom = std::floor(source.bottom);
}
uint32_t HWCLayer::GetUint32Color(const hwc_color_t &source) {
// Returns 32 bit ARGB
uint32_t a = UINT32(source.a) << 24;
uint32_t r = UINT32(source.r) << 16;
uint32_t g = UINT32(source.g) << 8;
uint32_t b = UINT32(source.b);
uint32_t color = a & r & g & b;
return color;
}
LayerBufferFormat HWCLayer::GetSDMFormat(const int32_t &source, const int flags) {
LayerBufferFormat format = kFormatInvalid;
if (flags & private_handle_t::PRIV_FLAGS_UBWC_ALIGNED) {
switch (source) {
case HAL_PIXEL_FORMAT_RGBA_8888:
format = kFormatRGBA8888Ubwc;
break;
case HAL_PIXEL_FORMAT_RGBX_8888:
format = kFormatRGBX8888Ubwc;
break;
case HAL_PIXEL_FORMAT_BGR_565:
format = kFormatBGR565Ubwc;
break;
case HAL_PIXEL_FORMAT_YCbCr_420_SP_VENUS:
case HAL_PIXEL_FORMAT_YCbCr_420_SP_VENUS_UBWC:
case HAL_PIXEL_FORMAT_NV12_ENCODEABLE:
format = kFormatYCbCr420SPVenusUbwc;
break;
default:
DLOGE("Unsupported format type for UBWC %d", source);
return kFormatInvalid;
}
return format;
}
switch (source) {
case HAL_PIXEL_FORMAT_RGBA_8888:
format = kFormatRGBA8888;
break;
case HAL_PIXEL_FORMAT_RGBA_5551:
format = kFormatRGBA5551;
break;
case HAL_PIXEL_FORMAT_RGBA_4444:
format = kFormatRGBA4444;
break;
case HAL_PIXEL_FORMAT_BGRA_8888:
format = kFormatBGRA8888;
break;
case HAL_PIXEL_FORMAT_RGBX_8888:
format = kFormatRGBX8888;
break;
case HAL_PIXEL_FORMAT_BGRX_8888:
format = kFormatBGRX8888;
break;
case HAL_PIXEL_FORMAT_RGB_888:
format = kFormatRGB888;
break;
case HAL_PIXEL_FORMAT_RGB_565:
format = kFormatRGB565;
break;
case HAL_PIXEL_FORMAT_BGR_565:
format = kFormatBGR565;
break;
case HAL_PIXEL_FORMAT_NV12_ENCODEABLE:
case HAL_PIXEL_FORMAT_YCbCr_420_SP_VENUS:
format = kFormatYCbCr420SemiPlanarVenus;
break;
case HAL_PIXEL_FORMAT_YCrCb_420_SP_VENUS:
format = kFormatYCrCb420SemiPlanarVenus;
break;
case HAL_PIXEL_FORMAT_YCbCr_420_SP_VENUS_UBWC:
format = kFormatYCbCr420SPVenusUbwc;
break;
case HAL_PIXEL_FORMAT_YV12:
format = kFormatYCrCb420PlanarStride16;
break;
case HAL_PIXEL_FORMAT_YCrCb_420_SP:
format = kFormatYCrCb420SemiPlanar;
break;
case HAL_PIXEL_FORMAT_YCbCr_420_SP:
format = kFormatYCbCr420SemiPlanar;
break;
case HAL_PIXEL_FORMAT_YCbCr_422_SP:
format = kFormatYCbCr422H2V1SemiPlanar;
break;
case HAL_PIXEL_FORMAT_YCbCr_422_I:
format = kFormatYCbCr422H2V1Packed;
break;
default:
DLOGW("Unsupported format type = %d", source);
return kFormatInvalid;
}
return format;
}
LayerBufferS3DFormat HWCLayer::GetS3DFormat(uint32_t s3d_format) {
LayerBufferS3DFormat sdm_s3d_format = kS3dFormatNone;
switch (s3d_format) {
case HAL_NO_3D:
sdm_s3d_format = kS3dFormatNone;
break;
case HAL_3D_SIDE_BY_SIDE_L_R:
sdm_s3d_format = kS3dFormatLeftRight;
break;
case HAL_3D_SIDE_BY_SIDE_R_L:
sdm_s3d_format = kS3dFormatRightLeft;
break;
case HAL_3D_TOP_BOTTOM:
sdm_s3d_format = kS3dFormatTopBottom;
break;
default:
DLOGW("Invalid S3D format %d", s3d_format);
}
return sdm_s3d_format;
}
DisplayError HWCLayer::SetMetaData(const private_handle_t *pvt_handle, Layer *layer) {
const MetaData_t *meta_data = reinterpret_cast<MetaData_t *>(pvt_handle->base_metadata);
LayerBuffer *layer_buffer = layer->input_buffer;
if (!meta_data) {
return kErrorNone;
}
if (meta_data->operation & UPDATE_COLOR_SPACE) {
if (SetCSC(meta_data->colorSpace, &layer->csc) != kErrorNone) {
return kErrorNotSupported;
}
}
if (meta_data->operation & SET_IGC) {
if (SetIGC(meta_data->igc, &layer->igc) != kErrorNone) {
return kErrorNotSupported;
}
}
if (meta_data->operation & UPDATE_REFRESH_RATE) {
layer->frame_rate = RoundToStandardFPS(meta_data->refreshrate);
}
if ((meta_data->operation & PP_PARAM_INTERLACED) && meta_data->interlaced) {
layer_buffer->flags.interlace = true;
}
if (meta_data->operation & LINEAR_FORMAT) {
layer_buffer->format = GetSDMFormat(INT32(meta_data->linearFormat), 0);
}
if (meta_data->operation & UPDATE_BUFFER_GEOMETRY) {
int actual_width = pvt_handle->width;
int actual_height = pvt_handle->height;
AdrenoMemInfo::getInstance().getAlignedWidthAndHeight(pvt_handle, actual_width, actual_height);
layer_buffer->width = UINT32(actual_width);
layer_buffer->height = UINT32(actual_height);
}
if (meta_data->operation & S3D_FORMAT) {
layer_buffer->s3d_format = GetS3DFormat(meta_data->s3dFormat);
}
return kErrorNone;
}
DisplayError HWCLayer::SetCSC(ColorSpace_t source, LayerCSC *target) {
switch (source) {
case ITU_R_601:
*target = kCSCLimitedRange601;
break;
case ITU_R_601_FR:
*target = kCSCFullRange601;
break;
case ITU_R_709:
*target = kCSCLimitedRange709;
break;
default:
DLOGE("Unsupported CSC: %d", source);
return kErrorNotSupported;
}
return kErrorNone;
}
DisplayError HWCLayer::SetIGC(IGC_t source, LayerIGC *target) {
switch (source) {
case IGC_NotSpecified:
*target = kIGCNotSpecified;
break;
case IGC_sRGB:
*target = kIGCsRGB;
break;
default:
DLOGE("Unsupported IGC: %d", source);
return kErrorNotSupported;
}
return kErrorNone;
}
uint32_t HWCLayer::RoundToStandardFPS(uint32_t fps) {
static const uint32_t standard_fps[4] = {30, 24, 48, 60};
int count = INT(sizeof(standard_fps) / sizeof(standard_fps[0]));
for (int i = 0; i < count; i++) {
if ((standard_fps[i] - fps) < 2) {
// Most likely used for video, the fps can fluctuate
// Ex: b/w 29 and 30 for 30 fps clip
return standard_fps[i];
}
}
return fps;
}
void HWCLayer::SetComposition(const LayerComposition &source) {
auto composition = HWC2::Composition::Invalid;
switch (source) {
case kCompositionGPU:
composition = HWC2::Composition::Client;
break;
case kCompositionHWCursor:
composition = HWC2::Composition::Cursor;
break;
default:
composition = HWC2::Composition::Device;
break;
}
// Update solid fill composition
if (layer_->composition == kCompositionSDE && layer_->flags.solid_fill != 0) {
composition = HWC2::Composition::SolidColor;
}
if (composition != composition_) {
// Composition changed for this layer
composition_changed_ = true;
composition_ = composition;
}
}
void HWCLayer::PushReleaseFence(int32_t fence) {
release_fences_.push(fence);
}
int32_t HWCLayer::PopReleaseFence(void) {
if (release_fences_.empty())
return -1;
auto fence = release_fences_.front();
release_fences_.pop();
return fence;
}
} // namespace sdm

109
sdm/libs/hwc2/hwc_layers.h Normal file
View File

@ -0,0 +1,109 @@
/*
* Copyright (c) 2014-2016, The Linux Foundation. All rights reserved.
* Not a Contribution.
*
* Copyright 2015 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef __HWC_LAYERS_H__
#define __HWC_LAYERS_H__
/* This class translates HWC2 Layer functions to the SDM LayerStack
*/
#include <gralloc_priv.h>
#include <qdMetaData.h>
#include <core/layer_stack.h>
#define HWC2_INCLUDE_STRINGIFICATION
#define HWC2_USE_CPP11
#include <hardware/hwcomposer2.h>
#undef HWC2_INCLUDE_STRINGIFICATION
#undef HWC2_USE_CPP11
#include <set>
#include <map>
#include <queue>
namespace sdm {
enum GeometryChanges {
kNone = 0x00,
kBlendMode = 0x01,
kDataspace = 0x02,
kDisplayFrame = 0x04,
kPlaneAlpha = 0x08,
kSourceCrop = 0x0A,
kTransform = 0x10,
kZOrder = 0x12,
kAdded = 0x14,
kRemoved = 0x18,
};
class HWCLayer {
public:
explicit HWCLayer(hwc2_display_t display_id);
~HWCLayer();
uint32_t GetZ() const { return z_; }
hwc2_layer_t GetId() const { return id_; }
Layer *GetSDMLayer() { return layer_; }
HWC2::Error SetLayerBlendMode(HWC2::BlendMode mode);
HWC2::Error SetLayerBuffer(buffer_handle_t buffer, int32_t acquire_fence);
HWC2::Error SetLayerColor(hwc_color_t color);
HWC2::Error SetLayerCompositionType(HWC2::Composition type);
HWC2::Error SetLayerDataspace(int32_t dataspace);
HWC2::Error SetLayerDisplayFrame(hwc_rect_t frame);
HWC2::Error SetLayerPlaneAlpha(float alpha);
HWC2::Error SetLayerSourceCrop(hwc_frect_t crop);
HWC2::Error SetLayerSurfaceDamage(hwc_region_t damage);
HWC2::Error SetLayerTransform(HWC2::Transform transform);
HWC2::Error SetLayerVisibleRegion(hwc_region_t visible);
HWC2::Error SetLayerZOrder(uint32_t z);
void SetComposition(const LayerComposition &source);
bool CompositionChanged(void) { return composition_changed_; }
HWC2::Composition GetCompositionType() { return composition_; }
uint32_t GetGeometryChanges() { return geometry_changes_; }
void ResetGeometryChanges() { geometry_changes_ = GeometryChanges::kNone; }
void PushReleaseFence(int32_t fence);
int32_t PopReleaseFence(void);
private:
Layer *layer_ = nullptr;
uint32_t z_ = 0;
const hwc2_layer_t id_;
const hwc2_display_t display_id_;
static std::atomic<hwc2_layer_t> next_id_;
std::queue<int32_t> release_fences_;
HWC2::Composition composition_ = HWC2::Composition::Device;
bool composition_changed_ = false;
uint32_t geometry_changes_ = GeometryChanges::kNone;
void SetRect(const hwc_rect_t &source, LayerRect *target);
void SetRect(const hwc_frect_t &source, LayerRect *target);
uint32_t GetUint32Color(const hwc_color_t &source);
LayerBufferFormat GetSDMFormat(const int32_t &source, const int flags);
LayerBufferS3DFormat GetS3DFormat(uint32_t s3d_format);
DisplayError SetMetaData(const private_handle_t *pvt_handle, Layer *layer);
DisplayError SetCSC(ColorSpace_t source, LayerCSC *target);
DisplayError SetIGC(IGC_t source, LayerIGC *target);
uint32_t RoundToStandardFPS(uint32_t fps);
};
struct SortLayersByZ {
bool operator()(const HWCLayer *lhs, const HWCLayer *rhs);
};
} // namespace sdm
#endif // __HWC_LAYERS_H__

File diff suppressed because it is too large Load Diff

177
sdm/libs/hwc2/hwc_session.h Normal file
View File

@ -0,0 +1,177 @@
/*
* Copyright (c) 2014-2016, The Linux Foundation. All rights reserved.
* Not a Contribution.
*
* Copyright 2015 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef __HWC_SESSION_H__
#define __HWC_SESSION_H__
#include <core/core_interface.h>
#include <utils/locker.h>
#include "hwc_callbacks.h"
#include "hwc_layers.h"
#include "hwc_display.h"
#include "hwc_display_primary.h"
#include "hwc_display_external.h"
#include "hwc_display_virtual.h"
#include "hwc_color_manager.h"
namespace sdm {
class HWCSession : hwc2_device_t, public qClient::BnQClient {
public:
struct HWCModuleMethods : public hw_module_methods_t {
HWCModuleMethods() { hw_module_methods_t::open = HWCSession::Open; }
};
explicit HWCSession(const hw_module_t *module);
int Init();
int Deinit();
HWC2::Error CreateVirtualDisplayObject(uint32_t width, uint32_t height);
template <typename... Args>
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_DISPLAY;
}
HWCSession *hwc_session = static_cast<HWCSession *>(device);
auto status = HWC2::Error::BadDisplay;
if (hwc_session->hwc_display_[display]) {
auto hwc_display = hwc_session->hwc_display_[display];
status = (hwc_display->*member)(std::forward<Args>(args)...);
}
return INT32(status);
}
template <typename... Args>
static int32_t CallLayerFunction(hwc2_device_t *device, hwc2_display_t display,
hwc2_layer_t layer, HWC2::Error (HWCLayer::*member)(Args...),
Args... args) {
if (!device) {
return HWC2_ERROR_BAD_DISPLAY;
}
HWCSession *hwc_session = static_cast<HWCSession *>(device);
auto status = HWC2::Error::BadDisplay;
if (hwc_session->hwc_display_[display]) {
status = HWC2::Error::BadLayer;
auto hwc_layer = hwc_session->hwc_display_[display]->GetHWCLayer(layer);
if (hwc_layer != nullptr) {
status = (hwc_layer->*member)(std::forward<Args>(args)...);
}
}
return INT32(status);
}
// HWC2 Functions that require a concrete implementation in hwc session
// and hence need to be member functions
static int32_t CreateVirtualDisplay(hwc2_device_t *device, uint32_t width, uint32_t height,
hwc2_display_t *out_display_id);
static int32_t DestroyVirtualDisplay(hwc2_device_t *device, hwc2_display_t display);
static int32_t PresentDisplay(hwc2_device_t *device, hwc2_display_t display,
int32_t *out_retire_fence);
static int32_t RegisterCallback(hwc2_device_t *device, int32_t descriptor,
hwc2_callback_data_t callback_data,
hwc2_function_pointer_t pointer);
static int32_t SetOutputBuffer(hwc2_device_t *device, hwc2_display_t display,
buffer_handle_t buffer, int32_t releaseFence);
static int32_t ValidateDisplay(hwc2_device_t *device, hwc2_display_t display,
uint32_t *out_num_types, uint32_t *out_num_requests);
private:
static const int kExternalConnectionTimeoutMs = 500;
static const int kPartialUpdateControlTimeoutMs = 100;
// hwc methods
static int Open(const hw_module_t *module, const char *name, hw_device_t **device);
static int Close(hw_device_t *device);
static void GetCapabilities(struct hwc2_device *device, uint32_t *outCount,
int32_t *outCapabilities);
static hwc2_function_pointer_t GetFunction(struct hwc2_device *device, int32_t descriptor);
// Uevent thread
static void *HWCUeventThread(void *context);
void *HWCUeventThreadHandler();
int GetEventValue(const char *uevent_data, int length, const char *event_info);
int HotPlugHandler(bool connected);
void ResetPanel();
int32_t ConnectDisplay(int disp);
int DisconnectDisplay(int disp);
int GetVsyncPeriod(int disp);
// QClient methods
virtual android::status_t notifyCallback(uint32_t command, const android::Parcel *input_parcel,
android::Parcel *output_parcel);
void DynamicDebug(const android::Parcel *input_parcel);
void SetFrameDumpConfig(const android::Parcel *input_parcel);
android::status_t SetMaxMixerStages(const android::Parcel *input_parcel);
android::status_t SetDisplayMode(const android::Parcel *input_parcel);
android::status_t SetSecondaryDisplayStatus(const android::Parcel *input_parcel,
android::Parcel *output_parcel);
android::status_t ToggleScreenUpdates(const android::Parcel *input_parcel,
android::Parcel *output_parcel);
android::status_t ConfigureRefreshRate(const android::Parcel *input_parcel);
android::status_t QdcmCMDHandler(const android::Parcel *input_parcel,
android::Parcel *output_parcel);
android::status_t ControlPartialUpdate(const android::Parcel *input_parcel, android::Parcel *out);
android::status_t OnMinHdcpEncryptionLevelChange(const android::Parcel *input_parcel,
android::Parcel *output_parcel);
android::status_t SetPanelBrightness(const android::Parcel *input_parcel,
android::Parcel *output_parcel);
android::status_t GetPanelBrightness(const android::Parcel *input_parcel,
android::Parcel *output_parcel);
// These functions return the actual display config info as opposed to FB
android::status_t HandleSetActiveDisplayConfig(const android::Parcel *input_parcel,
android::Parcel *output_parcel);
android::status_t HandleGetActiveDisplayConfig(const android::Parcel *input_parcel,
android::Parcel *output_parcel);
android::status_t HandleGetDisplayConfigCount(const android::Parcel *input_parcel,
android::Parcel *output_parcel);
android::status_t HandleGetDisplayAttributesForConfig(const android::Parcel *input_parcel,
android::Parcel *output_parcel);
android::status_t GetVisibleDisplayRect(const android::Parcel *input_parcel,
android::Parcel *output_parcel);
android::status_t SetDynamicBWForCamera(const android::Parcel *input_parcel,
android::Parcel *output_parcel);
android::status_t GetBWTransactionStatus(const android::Parcel *input_parcel,
android::Parcel *output_parcel);
static Locker locker_;
CoreInterface *core_intf_ = NULL;
HWCDisplay *hwc_display_[HWC_NUM_DISPLAY_TYPES] = {NULL};
HWCCallbacks callbacks_;
pthread_t uevent_thread_;
bool uevent_thread_exit_ = false;
const char *uevent_thread_name_ = "HWC_UeventThread";
HWCBufferAllocator *buffer_allocator_ = NULL;
HWCBufferSyncHandler *buffer_sync_handler_ = NULL;
HWCColorManager *color_mgr_ = NULL;
bool reset_panel_ = false;
bool secure_display_active_ = false;
bool external_pending_connect_ = false;
bool new_bw_mode_ = false;
bool need_invalidate_ = false;
int bw_mode_release_fd_ = -1;
qService::QService *qservice_ = NULL;
};
} // namespace sdm
#endif // __HWC_SESSION_H__