732 lines
24 KiB
C++
Executable File
732 lines
24 KiB
C++
Executable File
/*
|
||
* Copyright (C) 2018 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.
|
||
*/
|
||
|
||
#define LOG_TAG "hwc-resource-manager"
|
||
|
||
#include "resources/resourcemanager.h"
|
||
#include "drmlayer.h"
|
||
|
||
#include <cutils/properties.h>
|
||
#include <log/log.h>
|
||
#include <sstream>
|
||
#include <string>
|
||
|
||
#include <drm_fourcc.h>
|
||
#include <xf86drm.h>
|
||
#include <xf86drmMode.h>
|
||
|
||
#include <utils/Trace.h>
|
||
|
||
#include <rga.h>
|
||
|
||
//XML prase
|
||
#include <tinyxml2.h>
|
||
|
||
namespace android {
|
||
|
||
#define hwcMIN(x, y) (((x) <= (y)) ? (x) : (y))
|
||
#define hwcMAX(x, y) (((x) >= (y)) ? (x) : (y))
|
||
|
||
#ifndef IS_ALIGN
|
||
#define IS_ALIGN(val, align) (((val) & (align - 1)) == 0)
|
||
#endif
|
||
|
||
#ifndef ALIGN
|
||
#define ALIGN(value, base) (((value) + ((base)-1)) & ~((base)-1))
|
||
#endif
|
||
|
||
#ifndef ALIGN_DOWN
|
||
#define ALIGN_DOWN(value, base) (value & (~(base - 1)))
|
||
#endif
|
||
|
||
// define from hardware/rockchip/libgralloc/bifrost/src/mali_gralloc_usages.h
|
||
#ifndef RK_GRALLOC_USAGE_WITHIN_4G
|
||
#define RK_GRALLOC_USAGE_WITHIN_4G (1ULL << 56)
|
||
#endif
|
||
|
||
#ifndef RK_GRALLOC_USAGE_STRIDE_ALIGN_16
|
||
#define RK_GRALLOC_USAGE_STRIDE_ALIGN_16 (1ULL << 57)
|
||
#endif
|
||
|
||
/* Gralloc 4.0 中, 表征 "调用 alloc() 的 client 要求分配的 buffer 不是 AFBC 格式".
|
||
*/
|
||
#ifndef MALI_GRALLOC_USAGE_NO_AFBC
|
||
#define MALI_GRALLOC_USAGE_NO_AFBC (1ULL << 29)
|
||
#endif
|
||
|
||
#define WB_BUFFERQUEUE_MAX_SIZE 4
|
||
|
||
ResourceManager::ResourceManager() :
|
||
num_displays_(0) {
|
||
drmGralloc_ = DrmGralloc::getInstance();
|
||
}
|
||
|
||
int ResourceManager::Init(DrmHwcTwo *hwc2) {
|
||
hwc2_ = hwc2;
|
||
int ret = AddDrmDevice();
|
||
if(ret){
|
||
ALOGE("Failed to AddDrmDevice ");
|
||
}
|
||
|
||
if (!num_displays_) {
|
||
ALOGE("Failed to initialize any displays");
|
||
return ret ? -EINVAL : ret;
|
||
}
|
||
|
||
|
||
fb0_fd = open("/dev/graphics/fb0", O_RDWR, 0);
|
||
if(fb0_fd < 0){
|
||
ALOGE("Open fb0 fail in %s",__FUNCTION__);
|
||
}
|
||
|
||
DrmDevice *drm = drms_.front().get();
|
||
for(auto &crtc : drm->crtcs()){
|
||
mapDrmDisplayCompositor_.insert(
|
||
std::pair<int, std::shared_ptr<DrmDisplayCompositor>>(crtc->id(),std::make_shared<DrmDisplayCompositor>()));
|
||
HWC2_ALOGI("Create DrmDisplayCompositor crtc=%d",crtc->id());
|
||
}
|
||
|
||
displays_ = drm->GetDisplays();
|
||
if(displays_.size() == 0){
|
||
ALOGE("Failed to initialize any displays");
|
||
return ret ? -EINVAL : ret;
|
||
}
|
||
|
||
// 更新全局平台版本信息
|
||
gSetSocId(drm->getSocId());
|
||
// 更新全局 kernel drm 版本信息
|
||
gSetDrmVersion(drm->getDrmVersion());
|
||
|
||
// 更新配置
|
||
InitProperty();
|
||
return 0;
|
||
}
|
||
|
||
int ResourceManager::AddDrmDevice() {
|
||
std::unique_ptr<DrmDevice> drm = std::make_unique<DrmDevice>();
|
||
int displays_added, ret;
|
||
std::tie(ret, displays_added) = drm->Init(num_displays_);
|
||
if (ret < 0)
|
||
return ret;
|
||
|
||
//Get soc id
|
||
soc_id_ = drm->getSocId();
|
||
//DrmVersion
|
||
drmVersion_ = drm->getDrmVersion();
|
||
drmGralloc_->set_drm_version(dup(drm->fd()),drmVersion_);
|
||
|
||
std::shared_ptr<Importer> importer;
|
||
importer.reset(Importer::CreateInstance(drm.get()));
|
||
if (!importer) {
|
||
ALOGE("Failed to create importer instance");
|
||
return -ENODEV;
|
||
}
|
||
importers_.push_back(std::move(importer));
|
||
drms_.push_back(std::move(drm));
|
||
num_displays_ += displays_added;
|
||
return ret;
|
||
}
|
||
|
||
DrmConnector *ResourceManager::AvailableWritebackConnector(int display) {
|
||
DrmDevice *drm_device = GetDrmDevice(display);
|
||
DrmConnector *writeback_conn = NULL;
|
||
if (drm_device) {
|
||
writeback_conn = drm_device->AvailableWritebackConnector(display);
|
||
if (writeback_conn)
|
||
return writeback_conn;
|
||
}
|
||
for (auto &drm : drms_) {
|
||
if (drm.get() == drm_device)
|
||
continue;
|
||
writeback_conn = drm->AvailableWritebackConnector(display);
|
||
if (writeback_conn)
|
||
return writeback_conn;
|
||
}
|
||
return writeback_conn;
|
||
}
|
||
|
||
int ResourceManager::InitProperty() {
|
||
char property_value[PROPERTY_VALUE_MAX];
|
||
property_get("vendor.hwc.enable_composition_drop_mode", property_value, "0");
|
||
mCompositionDropMode_ = atoi(property_value) != 0;
|
||
|
||
property_get("vendor.hwc.enable_dynamic_display_mode", property_value, "0");
|
||
mDynamicDisplayMode_ = atoi(property_value) > 0;
|
||
|
||
property_get("vendor.hwc.enable_sideband_stream_2_mode", property_value, "0");
|
||
mSidebandStream2Mode_ = atoi(property_value) > 0;
|
||
|
||
property_get("vendor.hwc.video_buf_cache_max_size", property_value, "0");
|
||
mCacheBufferLimitSize_ = atoi(property_value);
|
||
|
||
return 0;
|
||
}
|
||
|
||
bool ResourceManager::IsCompositionDropMode() const {
|
||
return mCompositionDropMode_;
|
||
}
|
||
|
||
bool ResourceManager::IsDynamicDisplayMode() const {
|
||
return mDynamicDisplayMode_;
|
||
}
|
||
|
||
bool ResourceManager::IsSidebandStream2Mode() const {
|
||
// RK3528 默认开启 Sideband2.0支持
|
||
if(gIsRK3528()){
|
||
return true;
|
||
}
|
||
return mSidebandStream2Mode_;
|
||
}
|
||
|
||
int ResourceManager::GetCacheBufferLimitSize() const{
|
||
return mCacheBufferLimitSize_;
|
||
}
|
||
|
||
DrmDevice *ResourceManager::GetDrmDevice(int display) {
|
||
for (auto &drm : drms_) {
|
||
if (drm->HandlesDisplay(display & ~DRM_CONNECTOR_SPILT_MODE_MASK))
|
||
return drm.get();
|
||
}
|
||
return NULL;
|
||
}
|
||
|
||
std::shared_ptr<Importer> ResourceManager::GetImporter(int display) {
|
||
for (unsigned int i = 0; i < drms_.size(); i++) {
|
||
if (drms_[i]->HandlesDisplay(display & ~DRM_CONNECTOR_SPILT_MODE_MASK))
|
||
return importers_[i];
|
||
}
|
||
return NULL;
|
||
}
|
||
|
||
std::shared_ptr<DrmDisplayCompositor> ResourceManager::GetDrmDisplayCompositor(DrmCrtc* crtc){
|
||
if(!crtc){
|
||
HWC2_ALOGE("crtc is null");
|
||
return NULL;
|
||
}
|
||
|
||
if(mapDrmDisplayCompositor_.size() == 0){
|
||
HWC2_ALOGE("mapDrmDisplayCompositor_.size()=0");
|
||
return NULL;
|
||
}
|
||
|
||
auto pairDrmDisplayCompositor = mapDrmDisplayCompositor_.find(crtc->id());
|
||
return pairDrmDisplayCompositor->second;
|
||
}
|
||
|
||
int ResourceManager::GetWBDisplay() const {
|
||
std::unique_lock<std::recursive_mutex> lock(mRecursiveMutex);
|
||
return iWriteBackDisplayId_;
|
||
}
|
||
|
||
bool ResourceManager::isWBMode() const {
|
||
std::unique_lock<std::recursive_mutex> lock(mRecursiveMutex);
|
||
return bEnableWriteBackRef_ > 0;
|
||
}
|
||
|
||
const DrmMode& ResourceManager::GetWBMode() const {
|
||
std::unique_lock<std::recursive_mutex> lock(mRecursiveMutex);
|
||
return mWBMode_;
|
||
}
|
||
|
||
bool ResourceManager::IsDisableHwVirtualDisplay(){
|
||
std::unique_lock<std::recursive_mutex> lock(mRecursiveMutex);
|
||
return mVDMode_ == HWC2_DISABLE_HW_VIRTUAL_DISPLAY;
|
||
}
|
||
|
||
bool ResourceManager::IsWriteBackByVop(){
|
||
std::unique_lock<std::recursive_mutex> lock(mRecursiveMutex);
|
||
return mVDMode_ == HWC2_HW_VIRTUAL_DISPLAY_USE_VOP;
|
||
}
|
||
|
||
bool ResourceManager::IsWriteBackByRga(){
|
||
std::unique_lock<std::recursive_mutex> lock(mRecursiveMutex);
|
||
return mVDMode_ == HWC2_HW_VIRTUAL_DISPLAY_USE_RGA;
|
||
}
|
||
|
||
HwVirtualDisplayMode_t ResourceManager::ChooseWriteBackMode(int display){
|
||
std::unique_lock<std::recursive_mutex> lock(mRecursiveMutex);
|
||
// 2. 获取待 WriteBack display状态,状态异常则直接关闭 WriteBack 模式
|
||
DrmDevice *drmDevice = GetDrmDevice(display);
|
||
DrmConnector *writeBackConn = drmDevice->GetConnectorForDisplay(display);
|
||
if(!writeBackConn){
|
||
HWC2_ALOGE("display=%d WriteBackConn is NULL", display);
|
||
return HWC2_DISABLE_HW_VIRTUAL_DISPLAY;
|
||
}
|
||
|
||
if(writeBackConn->state() != DRM_MODE_CONNECTED){
|
||
HWC2_ALOGE("display=%d WriteBackConn state isn't connected(%d)",
|
||
display, writeBackConn->state());
|
||
return HWC2_DISABLE_HW_VIRTUAL_DISPLAY;
|
||
}
|
||
|
||
// 3. 获取待 WriteBack 当前分辨率,用于申请 WriteBackBuffer
|
||
// 4. WriteBack 硬件要求 16对齐,否则超出部分会直接丢弃
|
||
mWBMode_ = writeBackConn->current_mode();
|
||
if(mWBMode_.width() > 4096 || mWBMode_.height() > 2160){
|
||
HWC2_ALOGI("Primary resolution=%dx%d, use WriteBack by RGA", mWBMode_.width(), mWBMode_.height());
|
||
return HWC2_HW_VIRTUAL_DISPLAY_USE_RGA;
|
||
}
|
||
|
||
HWC2_ALOGI("Primary resolution=%dx%d, use WriteBack by Vop WriteBack", mWBMode_.width(), mWBMode_.height());
|
||
return HWC2_HW_VIRTUAL_DISPLAY_USE_VOP;
|
||
}
|
||
|
||
// 使用 Vop 作为 WriteBack 内容输出单元
|
||
int ResourceManager::WriteBackUseVop(int display){
|
||
std::unique_lock<std::recursive_mutex> lock(mRecursiveMutex);
|
||
iWBWidth_ = ALIGN_DOWN(mWBMode_.width(),16);
|
||
iWBHeight_ = mWBMode_.height();
|
||
iWBFormat_ = HAL_PIXEL_FORMAT_YCrCb_NV12;
|
||
|
||
// 5. 创建 WriteBackBuffer BufferQueue,并且申请 WB Buffer.
|
||
if(mWriteBackBQ_ == NULL){
|
||
mWriteBackBQ_ = std::make_shared<DrmBufferQueue>(WB_BUFFERQUEUE_MAX_SIZE);
|
||
mNextWriteBackBuffer_
|
||
= mWriteBackBQ_->DequeueDrmBuffer(iWBWidth_,
|
||
iWBHeight_,
|
||
iWBFormat_,
|
||
RK_GRALLOC_USAGE_STRIDE_ALIGN_16 |
|
||
MALI_GRALLOC_USAGE_NO_AFBC,
|
||
"WriteBackBuffer");
|
||
if(!mNextWriteBackBuffer_->initCheck()){
|
||
HWC2_ALOGE("display=%d WBBuffer Dequeue fail, w=%d h=%d format=%d",
|
||
display,
|
||
iWBWidth_,
|
||
iWBHeight_,
|
||
iWBFormat_);
|
||
return -1;
|
||
}
|
||
}
|
||
|
||
bEnableWriteBackRef_++;
|
||
iWriteBackDisplayId_ = display;
|
||
return 0;
|
||
}
|
||
|
||
// 使用 Rga 作为 WriteBack 内容输出单元
|
||
int ResourceManager::WriteBackUseRga(int display){
|
||
// 利用 RGA 进行 WriteBack, RGA alpha blend 要求点对点,不允许缩放
|
||
// 故要求申请内存与系统UI分辨率一致
|
||
if(hwc2_->GetDisplayCtxPtr(display) != NULL){
|
||
hwc2_drm_display_t* dpy_ctx = hwc2_->GetDisplayCtxPtr(display);
|
||
iWBWidth_ = dpy_ctx->framebuffer_width;
|
||
iWBHeight_ = dpy_ctx->framebuffer_height;
|
||
iWBFormat_ = HAL_PIXEL_FORMAT_RGBA_8888;
|
||
}else{
|
||
iWBWidth_ = mWBMode_.h_display();
|
||
iWBHeight_ = mWBMode_.v_display();
|
||
iWBFormat_ = HAL_PIXEL_FORMAT_RGBA_8888;
|
||
}
|
||
|
||
// 5. 创建 WriteBackBuffer BufferQueue,并且申请 WB Buffer.
|
||
if(mWriteBackBQ_ == NULL){
|
||
mWriteBackBQ_ = std::make_shared<DrmBufferQueue>();
|
||
|
||
mNextWriteBackBuffer_
|
||
= mWriteBackBQ_->DequeueDrmBuffer(iWBWidth_,
|
||
iWBHeight_,
|
||
iWBFormat_,
|
||
RK_GRALLOC_USAGE_STRIDE_ALIGN_16 |
|
||
MALI_GRALLOC_USAGE_NO_AFBC,
|
||
"WriteBackBuffer");
|
||
if(!mNextWriteBackBuffer_->initCheck()){
|
||
HWC2_ALOGE("display=%d WBBuffer Dequeue fail, w=%d h=%d format=%d",
|
||
display,
|
||
iWBWidth_,
|
||
iWBHeight_,
|
||
iWBFormat_);
|
||
return -1;
|
||
}
|
||
}
|
||
|
||
bEnableWriteBackRef_++;
|
||
iWriteBackDisplayId_ = display;
|
||
return 0;
|
||
}
|
||
|
||
int ResourceManager::EnableWriteBackMode(int display){
|
||
std::unique_lock<std::recursive_mutex> lock(mRecursiveMutex);
|
||
|
||
// 1. 检查 WB 模块是否已经被绑定
|
||
if(bEnableWriteBackRef_ > 0){
|
||
if(iWriteBackDisplayId_ != display){
|
||
HWC2_ALOGE("WriteBack has bind display %d, so display=%d WB request can't handle.",
|
||
iWriteBackDisplayId_, display);
|
||
return -1;
|
||
}else{
|
||
bEnableWriteBackRef_++;
|
||
return 0;
|
||
}
|
||
}
|
||
|
||
// 2. 根据 primary 分辨率模式选择 WriteBack 模式
|
||
mVDMode_ = ChooseWriteBackMode(display);
|
||
switch(mVDMode_){
|
||
case HWC2_HW_VIRTUAL_DISPLAY_USE_VOP:
|
||
return WriteBackUseVop(display);
|
||
case HWC2_HW_VIRTUAL_DISPLAY_USE_RGA:
|
||
return WriteBackUseRga(display);
|
||
case HWC2_DISABLE_HW_VIRTUAL_DISPLAY:
|
||
default:
|
||
HWC2_ALOGE("display=%d can't find any suitable WriteBack mode, roll back to GLES display, VDMode=%d",
|
||
display, mVDMode_);
|
||
return -1;
|
||
}
|
||
|
||
return -1;
|
||
}
|
||
|
||
|
||
int ResourceManager::UpdateWriteBackResolutionUseVop(int display){
|
||
std::unique_lock<std::recursive_mutex> lock(mRecursiveMutex);
|
||
|
||
// 2. 获取待 WriteBack display状态,状态异常则直接关闭 WriteBack 模式
|
||
DrmDevice *drmDevice = GetDrmDevice(display);
|
||
DrmConnector *writeBackConn = drmDevice->GetConnectorForDisplay(display);
|
||
if(!writeBackConn){
|
||
HWC2_ALOGE("display=%d WriteBackConn is NULL", display);
|
||
return -1;
|
||
}
|
||
|
||
if(writeBackConn->state() != DRM_MODE_CONNECTED){
|
||
HWC2_ALOGE("display=%d WriteBackConn state isn't connected(%d)",
|
||
display, writeBackConn->state());
|
||
return -1;
|
||
}
|
||
|
||
// 3. 获取待 WriteBack 当前分辨率,用于申请 WriteBackBuffer
|
||
DrmMode currentMode = writeBackConn->current_mode();
|
||
mWBMode_ = currentMode;
|
||
int tempWBWidth = ALIGN_DOWN(mWBMode_.width(),16);
|
||
int tempWBHeight = mWBMode_.height();
|
||
if(tempWBWidth == iWBWidth_ &&
|
||
tempWBHeight == iWBHeight_){
|
||
return 0;
|
||
}else{
|
||
HWC2_ALOGI("display=%d update WriteBack resolution(%dx%d)=>(%dx%d)",
|
||
display, iWBWidth_, iWBHeight_,
|
||
currentMode.width(), currentMode.height());
|
||
}
|
||
|
||
iWBWidth_ = tempWBWidth;
|
||
iWBHeight_ = tempWBHeight;
|
||
iWBFormat_ = HAL_PIXEL_FORMAT_YCrCb_NV12;
|
||
|
||
// 4. 创建 WriteBackBuffer BufferQueue,并且申请 WB Buffer.
|
||
if(mWriteBackBQ_ == NULL){
|
||
mWriteBackBQ_ = std::make_shared<DrmBufferQueue>(WB_BUFFERQUEUE_MAX_SIZE);
|
||
}
|
||
|
||
mNextWriteBackBuffer_
|
||
= mWriteBackBQ_->DequeueDrmBuffer(iWBWidth_,
|
||
iWBHeight_,
|
||
iWBFormat_,
|
||
RK_GRALLOC_USAGE_STRIDE_ALIGN_16 |
|
||
MALI_GRALLOC_USAGE_NO_AFBC,
|
||
"WriteBackBuffer");
|
||
if(!mNextWriteBackBuffer_->initCheck()){
|
||
HWC2_ALOGE("display=%d WBBuffer Dequeue fail, w=%d h=%d format=%d",
|
||
display, iWBWidth_, iWBHeight_, iWBFormat_);
|
||
return -1;
|
||
}
|
||
return 0;
|
||
}
|
||
|
||
int ResourceManager::UpdateWriteBackResolution(int display){
|
||
std::unique_lock<std::recursive_mutex> lock(mRecursiveMutex);
|
||
|
||
// 1. 检查 WB 模块是否已经被绑定
|
||
if(bEnableWriteBackRef_ > 0){
|
||
if(iWriteBackDisplayId_ != display){
|
||
HWC2_ALOGE("WriteBack has bind display %d, so display=%d WB request can't handle.",
|
||
iWriteBackDisplayId_, display);
|
||
return -1;
|
||
}
|
||
}
|
||
|
||
// 根据 WriteBack mode 处理 update WriteBack resolution 请求
|
||
switch(mVDMode_){
|
||
case HWC2_HW_VIRTUAL_DISPLAY_USE_VOP:
|
||
return UpdateWriteBackResolutionUseVop(display);
|
||
case HWC2_HW_VIRTUAL_DISPLAY_USE_RGA:
|
||
// RGA 模式不需要考虑分辨率切换的场景
|
||
return 0;
|
||
case HWC2_DISABLE_HW_VIRTUAL_DISPLAY:
|
||
default:
|
||
HWC2_ALOGE("display=%d can't find any suitable WriteBack mode, VDMode=%d ", display, mVDMode_);
|
||
return -1;
|
||
}
|
||
return 0;
|
||
}
|
||
|
||
int ResourceManager::DisableWriteBackMode(int display){
|
||
std::unique_lock<std::recursive_mutex> lock(mRecursiveMutex);
|
||
if(display != iWriteBackDisplayId_)
|
||
return 0;
|
||
|
||
bEnableWriteBackRef_--;
|
||
if(bEnableWriteBackRef_ <= 0){
|
||
iWriteBackDisplayId_ = -1;
|
||
mFinishBufferQueue_.clear();
|
||
mVDMode_ = HWC2_DISABLE_HW_VIRTUAL_DISPLAY;
|
||
}
|
||
return 0;
|
||
}
|
||
|
||
std::shared_ptr<DrmBuffer> ResourceManager::GetResetWBBuffer(){
|
||
std::unique_lock<std::recursive_mutex> lock(mRecursiveMutex);
|
||
if(mResetBackBuffer_ == NULL){
|
||
mResetBackBuffer_ = std::make_shared<DrmBuffer>(640,
|
||
360,
|
||
HAL_PIXEL_FORMAT_YCrCb_NV12,
|
||
RK_GRALLOC_USAGE_STRIDE_ALIGN_16 |
|
||
RK_GRALLOC_USAGE_WITHIN_4G,
|
||
"WBResetBuffer");
|
||
if(mResetBackBuffer_->Init()){
|
||
HWC2_ALOGE("DrmBuffer Init fail, w=%d h=%d format=%d name=%s",
|
||
640, 360, HAL_PIXEL_FORMAT_YCrCb_NV12, "WBResetBuffer");
|
||
mResetBackBuffer_ = NULL;
|
||
return NULL;
|
||
}
|
||
|
||
rga_buffer_t src;
|
||
im_rect src_rect;
|
||
|
||
memset(&src, 0x0, sizeof(rga_buffer_t));
|
||
memset(&src_rect, 0x0, sizeof(im_rect));
|
||
|
||
// Set src buffer info
|
||
src.fd = mResetBackBuffer_->GetFd();
|
||
src.width = mResetBackBuffer_->GetWidth();
|
||
src.height = mResetBackBuffer_->GetHeight();
|
||
src.wstride = mResetBackBuffer_->GetStride();
|
||
src.hstride = mResetBackBuffer_->GetHeightStride();
|
||
src.format = mResetBackBuffer_->GetFormat();
|
||
|
||
// Set src rect info
|
||
src_rect.x = 0;
|
||
src_rect.y = 0;
|
||
src_rect.width = src.width ;
|
||
src_rect.height = src.height;
|
||
|
||
src.color_space_mode = IM_RGB_TO_YUV_BT601_LIMIT;
|
||
|
||
// Set Dataspace
|
||
// if((buffer.mBufferInfo_.uDataSpace_ & HAL_DATASPACE_STANDARD_BT709) == HAL_DATASPACE_STANDARD_BT709){
|
||
// dst.color_space_mode = IM_YUV_TO_RGB_BT709_LIMIT;
|
||
// SVEP_ALOGD_IF("color_space_mode = BT709 dataspace=0x%" PRIx64,buffer.mBufferInfo_.uDataSpace_);
|
||
// }else{
|
||
// SVEP_ALOGD_IF("color_space_mode = BT601 dataspace=0x%" PRIx64,buffer.mBufferInfo_.uDataSpace_);
|
||
// }
|
||
|
||
IM_STATUS im_state;
|
||
|
||
// Call Im2d 格式转换
|
||
im_state = imfill(src, src_rect, 0x0);
|
||
|
||
if(im_state != IM_STATUS_SUCCESS){
|
||
HWC2_ALOGE("call im2d reset Fail!");
|
||
}
|
||
}
|
||
return mResetBackBuffer_;
|
||
}
|
||
std::shared_ptr<DrmBuffer> ResourceManager::GetNextWBBuffer(){
|
||
std::unique_lock<std::recursive_mutex> lock(mRecursiveMutex);
|
||
return mNextWriteBackBuffer_;
|
||
}
|
||
|
||
std::shared_ptr<DrmBuffer> ResourceManager::GetDrawingWBBuffer(){
|
||
std::unique_lock<std::recursive_mutex> lock(mRecursiveMutex);
|
||
return mDrawingWriteBackBuffer_;;
|
||
}
|
||
|
||
int ResourceManager::GetFinishWBBufferSize(){
|
||
std::unique_lock<std::recursive_mutex> lock(mRecursiveMutex);
|
||
return mFinishBufferQueue_.size();
|
||
}
|
||
|
||
int ResourceManager::OutputWBBuffer(int display_id,
|
||
rga_buffer_t &dst,
|
||
im_rect &dst_rect,
|
||
int32_t *retire_fence,
|
||
uint64_t *last_frame_no){
|
||
|
||
ATRACE_CALL();
|
||
std::unique_lock<std::recursive_mutex> lock(mRecursiveMutex);
|
||
if(mFinishBufferQueue_.size() == 0){
|
||
HWC2_ALOGE("mFinishBufferQueue_ size is 0");
|
||
return -1;
|
||
}
|
||
|
||
std::shared_ptr<DrmBuffer> output_buffer = NULL;
|
||
uint64_t output_frame_no = 0;
|
||
std::queue<PAIR_ID_BUFFER> tmp_bufferqueue;
|
||
for(auto &FinishBufferPair : mFinishBufferQueue_){
|
||
if(FinishBufferPair.first > *last_frame_no){
|
||
output_buffer = FinishBufferPair.second;
|
||
output_frame_no = FinishBufferPair.first;
|
||
break;
|
||
}
|
||
}
|
||
|
||
if(output_buffer == NULL && mFinishBufferQueue_.size() >0){
|
||
output_buffer = mFinishBufferQueue_.back().second;
|
||
output_frame_no = mFinishBufferQueue_.back().first;
|
||
HWC2_ALOGW("VDS may output a same image frame_no=%" PRIu64 " Last_frame_no=%" PRIu64 , output_frame_no, *last_frame_no);
|
||
}
|
||
|
||
if(output_buffer == NULL){
|
||
HWC2_ALOGE("output_buffer is NULL");
|
||
return -1;
|
||
}
|
||
|
||
HWC2_ALOGD_IF_DEBUG("WB: display=%d frame_no=%" PRIu64 " id=%" PRIu64 " queue.size=%zu" ,
|
||
display_id, output_frame_no, output_buffer->GetId(),mFinishBufferQueue_.size());
|
||
|
||
output_buffer->WaitFinishFence();
|
||
// 添加调试接口,抓打印WriteBack Buffer
|
||
char value[PROPERTY_VALUE_MAX];
|
||
property_get("debug.wb.dump", value, "0");
|
||
if(atoi(value) > 0){
|
||
output_buffer->DumpData();
|
||
}
|
||
|
||
rga_buffer_t src;
|
||
rga_buffer_t pat;
|
||
im_rect src_rect;
|
||
im_rect pat_rect;
|
||
|
||
memset(&src, 0x0, sizeof(rga_buffer_t));
|
||
memset(&pat, 0x0, sizeof(rga_buffer_t));
|
||
memset(&src_rect, 0x0, sizeof(im_rect));
|
||
memset(&src_rect, 0x0, sizeof(im_rect));
|
||
|
||
// Set src buffer info
|
||
src.fd = output_buffer->GetFd();
|
||
src.width = output_buffer->GetWidth();
|
||
src.height = output_buffer->GetHeight();
|
||
src.wstride = output_buffer->GetStride();
|
||
src.hstride = output_buffer->GetHeightStride();
|
||
src.format = output_buffer->GetFormat();
|
||
|
||
// 由于WriteBack仅支持BGR888(B:G:R little endian),故需要使用RGA做格式转换
|
||
if(src.format == HAL_PIXEL_FORMAT_RGB_888)
|
||
src.format = RK_FORMAT_BGR_888;
|
||
// 由于WriteBack仅支持BGR565(B:G:R little endian),故需要使用RGA做格式转换
|
||
if(src.format == HAL_PIXEL_FORMAT_RGB_565)
|
||
src.format = RK_FORMAT_BGR_565;
|
||
|
||
|
||
// Set src rect info
|
||
src_rect.x = 0;
|
||
src_rect.y = 0;
|
||
src_rect.width = output_buffer->GetWidth();
|
||
src_rect.height = output_buffer->GetHeight();
|
||
|
||
// Set Dataspace
|
||
// if((srcBuffer.mBufferInfo_.uDataSpace_ & HAL_DATASPACE_STANDARD_BT709) == HAL_DATASPACE_STANDARD_BT709){
|
||
// dst.color_space_mode = IM_YUV_TO_RGB_BT709_LIMIT;
|
||
// SVEP_ALOGD_IF("color_space_mode = BT709 dataspace=0x%" PRIx64,srcBuffer.mBufferInfo_.uDataSpace_);
|
||
// }else{
|
||
// SVEP_ALOGD_IF("color_space_mode = BT601 dataspace=0x%" PRIx64,srcBuffer.mBufferInfo_.uDataSpace_);
|
||
// }
|
||
|
||
IM_STATUS im_state;
|
||
|
||
im_opt_t imOpt;
|
||
memset(&imOpt, 0x00, sizeof(im_opt_t));
|
||
imOpt.core = IM_SCHEDULER_RGA3_CORE0 | IM_SCHEDULER_RGA3_CORE1;
|
||
|
||
// Call Im2d 格式转换
|
||
im_state = improcess(src, dst, pat, src_rect, dst_rect, pat_rect, 0, NULL, &imOpt, IM_SYNC);
|
||
|
||
if(im_state == IM_STATUS_SUCCESS){
|
||
HWC2_ALOGD_IF_VERBOSE("call im2d convert to rgb888 Success");
|
||
*retire_fence = -1;
|
||
}else{
|
||
HWC2_ALOGD_IF_DEBUG("call im2d fail, ret=%d Error=%s", im_state, imStrError(im_state));
|
||
*retire_fence = -1;
|
||
return -1;
|
||
}
|
||
|
||
*last_frame_no = output_frame_no;
|
||
|
||
return 0;
|
||
}
|
||
|
||
int ResourceManager::SwapWBBuffer(uint64_t frame_no){
|
||
|
||
ATRACE_CALL();
|
||
std::unique_lock<std::recursive_mutex> lock(mRecursiveMutex);
|
||
if(bEnableWriteBackRef_ <= 0){
|
||
HWC2_ALOGE("");
|
||
return -1;
|
||
}
|
||
|
||
// 1. Drawing 切换为 Finish 状态, 并 push 进队列
|
||
if(mDrawingWriteBackBuffer_ != NULL){
|
||
mFinishBufferQueue_.push_back(PAIR_ID_BUFFER{frame_no, mDrawingWriteBackBuffer_});
|
||
HWC2_ALOGD_IF_VERBOSE("WB: frame_no=%" PRIu64 " id=%" PRIu64 " queue.size=%zu" ,frame_no, mDrawingWriteBackBuffer_->GetId(),mFinishBufferQueue_.size());
|
||
// 环形缓冲区,若达到环形缓冲区最大尺寸,则需要丢掉最旧的一帧缓存
|
||
if(mFinishBufferQueue_.size() > (WB_BUFFERQUEUE_MAX_SIZE - 1)){
|
||
auto last_buffer_pair = mFinishBufferQueue_.begin();
|
||
mFinishBufferQueue_.erase(last_buffer_pair);
|
||
HWC2_ALOGD_IF_WARN("WB: lost frame_no=%" PRIu64 " id=%" PRIu64 " queue.size=%zu" ,
|
||
last_buffer_pair->first,
|
||
((last_buffer_pair->second != NULL) ? last_buffer_pair->second->GetId() : -1),
|
||
mFinishBufferQueue_.size());
|
||
|
||
}
|
||
}
|
||
// 2. Next 切换为 Drawing 状态
|
||
mDrawingWriteBackBuffer_ = mNextWriteBackBuffer_;
|
||
if(mWriteBackBQ_->QueueBuffer(mNextWriteBackBuffer_)){
|
||
HWC2_ALOGE("display=%d WBBuffer Queue fail, w=%d h=%d format=%d",
|
||
iWriteBackDisplayId_,
|
||
iWBWidth_,
|
||
iWBHeight_,
|
||
iWBFormat_);
|
||
return -1;
|
||
}
|
||
|
||
// 3. 申请 Next Buffer
|
||
std::shared_ptr<DrmBuffer> next
|
||
= mWriteBackBQ_->DequeueDrmBuffer(iWBWidth_,
|
||
iWBHeight_,
|
||
iWBFormat_,
|
||
RK_GRALLOC_USAGE_STRIDE_ALIGN_16 |
|
||
MALI_GRALLOC_USAGE_NO_AFBC,
|
||
"WriteBackBuffer");
|
||
if(!next->initCheck()){
|
||
HWC2_ALOGE("display=%d WBBuffer Dequeue fail, w=%d h=%d format=%d",
|
||
iWriteBackDisplayId_,
|
||
iWBWidth_,
|
||
iWBHeight_,
|
||
iWBFormat_);
|
||
return -1;
|
||
}
|
||
|
||
HWC2_ALOGD_IF_INFO("display=%d success, w=%d h=%d format=%d",
|
||
iWriteBackDisplayId_,
|
||
iWBWidth_,
|
||
iWBHeight_,
|
||
iWBFormat_);
|
||
|
||
mNextWriteBackBuffer_ = next;
|
||
return 0;
|
||
}
|
||
} // namespace android
|