/* * Copyright (C) 2016 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 DRM_HWC_TWO_H #define DRM_HWC_TWO_H #include "drmdisplaycompositor.h" #include "drmlayer.h" #include "resources/resourcemanager.h" #include "vsyncworker.h" #include "platform.h" #include "rockchip/drmgralloc.h" #include "rockchip/invalidateworker.h" #include "utils/drmfence.h" #include "rockchip/producer/drmvideoproducer.h" #include "resources/resourcescache.h" #include #include "drmbufferqueue.h" #ifdef USE_LIBPQ #include "Pq.h" #endif #include #include #include #include #include namespace android { class DrmGralloc; class DrmHwcTwo; class GemHandle; class ResourceManager; class DrmDisplayCompositor; static DrmHwcTwo *g_ctx = NULL; #define MAX_NUM_BUFFER_SLOTS 32 #define MAX_NUM_FRAME_TIMESTAMP_CNT 20 class DrmHwcTwo : public hwc2_device_t { public: static int HookDevOpen(const struct hw_module_t *module, const char *name, struct hw_device_t **dev); DrmHwcTwo(); HWC2::Error Init(); hwc2_drm_display_t* GetDisplayCtxPtr(hwc2_display_t display_id); private: class HwcLayer { public: HwcLayer(uint32_t layer_id, DrmDevice *drm){ id_ = layer_id; drmGralloc_ = DrmGralloc::getInstance(); drm_ = drm; bufferInfoMap_.clear(); bSideband2_=false; sidebandStreamHandle_ = NULL; memset(&mSidebandInfo_, 0x00, sizeof(vt_sideband_data_t)); }; void clear(){ buffer_ = NULL; if(!bSideband2_ && sidebandStreamHandle_ != NULL){ int ret = drmGralloc_->freeBuffer(sidebandStreamHandle_); if(ret){ HWC2_ALOGE("freeBuffer sidebandStreamHandle = %p fail, ret=%d",sidebandStreamHandle_,ret); } sidebandStreamHandle_ = NULL; } } HWC2::Composition sf_type() const { return mCurrentState.sf_type_; } HWC2::Composition validated_type() const { return mCurrentState.validated_type_; } void accept_type_change() { mCurrentState.sf_type_ = mCurrentState.validated_type_; } void set_validated_type(HWC2::Composition type) { mCurrentState.validated_type_ = type; } bool type_changed() const { return mCurrentState.sf_type_ != mCurrentState.validated_type_; } uint32_t z_order() const { return mCurrentState.z_order_; } typedef struct Hwc2LayerState{ Hwc2LayerState& operator=(Hwc2LayerState& rhs){ buffer_ = rhs.buffer_; sf_type_ = rhs.sf_type_; validated_type_ = rhs.validated_type_; alpha_ = rhs.alpha_; blending_ = rhs.blending_; transform_ = rhs.transform_; dataspace_ = rhs.dataspace_; source_crop_ = rhs.source_crop_; display_frame_ = rhs.display_frame_; cursor_x_ = rhs.cursor_x_; cursor_y_ = rhs.cursor_y_; color_ = rhs.color_; z_order_ = rhs.z_order_; sidebandStreamHandle_ = rhs.sidebandStreamHandle_; return *this; } bool operator==(Hwc2LayerState& rhs){ if( buffer_ == rhs.buffer_ && sf_type_ == rhs.sf_type_ && validated_type_ == rhs.validated_type_ && alpha_ == rhs.alpha_ && blending_ == rhs.blending_ && transform_ == rhs.transform_ && dataspace_ == rhs.dataspace_ && cursor_x_ == rhs.cursor_x_ && cursor_y_ == rhs.cursor_y_ && color_.r == rhs.color_.r && color_.g == rhs.color_.g && color_.b == rhs.color_.b && color_.a == rhs.color_.a && z_order_ == rhs.z_order_ && sidebandStreamHandle_ == rhs.sidebandStreamHandle_ && source_crop_.left == rhs.source_crop_.left && source_crop_.top == rhs.source_crop_.top && source_crop_.right == rhs.source_crop_.right && source_crop_.bottom == rhs.source_crop_.bottom && display_frame_.left == rhs.display_frame_.left && display_frame_.top == rhs.display_frame_.top && display_frame_.right == rhs.display_frame_.right && display_frame_.bottom == rhs.display_frame_.bottom) { return true; } return false; } // BufferHandle buffer_handle_t buffer_ = NULL; // Sidebande buffer_handle_t sidebandStreamHandle_ = NULL; // sf_type_ stores the initial type given to us by surfaceflinger, // validated_type_ stores the type after running ValidateDisplay HWC2::Composition sf_type_ = HWC2::Composition::Invalid; HWC2::Composition validated_type_ = HWC2::Composition::Invalid; float alpha_ = 1.0f; HWC2::BlendMode blending_ = HWC2::BlendMode::None; HWC2::Transform transform_ = HWC2::Transform::None; android_dataspace_t dataspace_ = HAL_DATASPACE_UNKNOWN; hwc_rect_t display_frame_; hwc_frect_t source_crop_; int32_t cursor_x_; int32_t cursor_y_; hwc_color_t color_; uint32_t z_order_ = 0; } Hwc2LayerState_t; buffer_handle_t buffer() { return buffer_; } void CacheBufferInfo(buffer_handle_t buffer) { buffer_ = buffer; mCurrentState.buffer_ = buffer; // Bufferinfo Cache uint64_t buffer_id; drmGralloc_->hwc_get_handle_buffer_id(buffer_, &buffer_id); // Get Buffer info const auto mapBuffer = bufferInfoMap_.find(buffer_id); if(mapBuffer == bufferInfoMap_.end()){ // If bHasCache_ is true, the new buffer_id need to reset mapBuffer if(bHasCache_){ HWC2_ALOGD_IF_VERBOSE("bHasCache=%d to reset bufferInfoMap_ BufferId=%" PRIx64 " Name=%s", bHasCache_,buffer_id,pBufferInfo_->sLayerName_.c_str()); bufferInfoMap_.clear(); bHasCache_ = false; } // If size is too big, the new buffer_id need to reset mapBuffer if(bufferInfoMap_.size() > MAX_NUM_BUFFER_SLOTS){ HWC2_ALOGD_IF_VERBOSE("MapSize=%zu too large to reset bufferInfoMap_ BufferId=%" PRIx64 " Name=%s", bufferInfoMap_.size(),buffer_id,pBufferInfo_->sLayerName_.c_str()); bufferInfoMap_.clear(); } auto ret = bufferInfoMap_.emplace(std::make_pair(buffer_id, std::make_shared())); if(ret.second == false){ HWC2_ALOGD_IF_VERBOSE("bufferInfoMap_ emplace fail! BufferHandle=%p",buffer_); }else{ pBufferInfo_ = ret.first->second; pBufferInfo_->uBufferId_ = buffer_id; int ret = drmGralloc_->importBuffer(buffer_, &pBufferInfo_->native_buffer_); if(ret){ HWC2_ALOGD_IF_WARN("buffer-id=0x%" PRIx64 " importBuffer fail.", buffer_id); } // Bug:#426310 // 多路视频同时输出,SurfaceFlinger可能会频繁触发 buffer_handle_t import/release行为 // 可能会导致HWC本地cache的fd失效,故需要本地dup dma-buffer-fd副本,确保fd有效 pBufferInfo_->iFd_ = base::unique_fd(dup(drmGralloc_->hwc_get_handle_primefd(buffer_))); pBufferInfo_->iWidth_ = drmGralloc_->hwc_get_handle_attibute(buffer_,ATT_WIDTH); pBufferInfo_->iHeight_ = drmGralloc_->hwc_get_handle_attibute(buffer_,ATT_HEIGHT); pBufferInfo_->iStride_ = drmGralloc_->hwc_get_handle_attibute(buffer_,ATT_STRIDE); pBufferInfo_->iSize_ = drmGralloc_->hwc_get_handle_attibute(buffer_,ATT_SIZE); pBufferInfo_->iHeightStride_ = drmGralloc_->hwc_get_handle_attibute(buffer_,ATT_HEIGHT_STRIDE); pBufferInfo_->iByteStride_ = drmGralloc_->hwc_get_handle_attibute(buffer_,ATT_BYTE_STRIDE_WORKROUND); pBufferInfo_->iFormat_ = drmGralloc_->hwc_get_handle_attibute(buffer_,ATT_FORMAT); pBufferInfo_->iUsage_ = drmGralloc_->hwc_get_handle_usage(buffer_); pBufferInfo_->uFourccFormat_ = drmGralloc_->hwc_get_handle_fourcc_format(buffer_); pBufferInfo_->uModifier_ = drmGralloc_->hwc_get_handle_format_modifier(buffer_); drmGralloc_->hwc_get_handle_plane_bytes_stride(buffer_, pBufferInfo_->uByteStridePlanes_); drmGralloc_->hwc_get_handle_name(buffer_,pBufferInfo_->sLayerName_); layer_name_ = pBufferInfo_->sLayerName_; HWC2_ALOGD_IF_VERBOSE("bufferInfoMap_ size = %zu insert success! BufferId=%" PRIx64 "w=%d h=%d format=%d fourcc=%c%c%c%c Name=%s", bufferInfoMap_.size(),buffer_id, pBufferInfo_->iWidth_, pBufferInfo_->iHeight_, pBufferInfo_->iFormat_, pBufferInfo_->uFourccFormat_, pBufferInfo_->uFourccFormat_ >> 8, pBufferInfo_->uFourccFormat_ >> 16, pBufferInfo_->uFourccFormat_ >> 24, pBufferInfo_->sLayerName_.c_str()); } }else{ bHasCache_ = true; pBufferInfo_ = mapBuffer->second; HWC2_ALOGD_IF_VERBOSE("bufferInfoMap_ size = %zu has cache! BufferId=%" PRIx64 " Name=%s", bufferInfoMap_.size(),buffer_id,pBufferInfo_->sLayerName_.c_str()); } if(mDrawingState.buffer_ != mCurrentState.buffer_){ nsecs_t current_time = systemTime(); qFrameTimestamp_.push(current_time); qFrameTimestampBack_.push(current_time); while(qFrameTimestamp_.size() > MAX_NUM_FRAME_TIMESTAMP_CNT){ qFrameTimestamp_.pop(); qFrameTimestampBack_.pop(); } } // ALOGI("rk-debug Name=%s mFps=%f", pBufferInfo_->sLayerName_.c_str(), GetFps());; } void NoCacheBufferInfo(buffer_handle_t buffer) { // clear cache bufferInfoMap_.clear(); bHasCache_ = false; buffer_ = buffer; mCurrentState.buffer_ = buffer; // Bufferinfo Cache uint64_t buffer_id; drmGralloc_->hwc_get_handle_buffer_id(buffer_, &buffer_id); pBufferInfo_ = std::make_shared(); pBufferInfo_->uBufferId_ = buffer_id; int ret = drmGralloc_->importBuffer(buffer_, &pBufferInfo_->native_buffer_); if(ret){ HWC2_ALOGD_IF_WARN("buffer-id=0x%" PRIx64 " importBuffer fail.", buffer_id); } pBufferInfo_->iFd_ = base::unique_fd(dup(drmGralloc_->hwc_get_handle_primefd(buffer_))); pBufferInfo_->iWidth_ = drmGralloc_->hwc_get_handle_attibute(buffer_,ATT_WIDTH); pBufferInfo_->iHeight_ = drmGralloc_->hwc_get_handle_attibute(buffer_,ATT_HEIGHT); pBufferInfo_->iStride_ = drmGralloc_->hwc_get_handle_attibute(buffer_,ATT_STRIDE); pBufferInfo_->iSize_ = drmGralloc_->hwc_get_handle_attibute(buffer_,ATT_SIZE); pBufferInfo_->iHeightStride_ = drmGralloc_->hwc_get_handle_attibute(buffer_,ATT_HEIGHT_STRIDE); pBufferInfo_->iByteStride_ = drmGralloc_->hwc_get_handle_attibute(buffer_,ATT_BYTE_STRIDE_WORKROUND); pBufferInfo_->iFormat_ = drmGralloc_->hwc_get_handle_attibute(buffer_,ATT_FORMAT); pBufferInfo_->iUsage_ = drmGralloc_->hwc_get_handle_usage(buffer_); pBufferInfo_->uFourccFormat_ = drmGralloc_->hwc_get_handle_fourcc_format(buffer_); pBufferInfo_->uModifier_ = drmGralloc_->hwc_get_handle_format_modifier(buffer_); drmGralloc_->hwc_get_handle_name(buffer_,pBufferInfo_->sLayerName_); layer_name_ = pBufferInfo_->sLayerName_; HWC2_ALOGD_IF_VERBOSE("bufferInfoMap_ size = %zu insert success! BufferId=%" PRIx64 " fd=%d w=%d h=%d format=%d fourcc=%c%c%c%c usage=%" PRIx64 " modifier=%" PRIx64 " Name=%s", bufferInfoMap_.size(),buffer_id, pBufferInfo_->iFd_.get(), pBufferInfo_->iWidth_, pBufferInfo_->iHeight_, pBufferInfo_->iFormat_, pBufferInfo_->uFourccFormat_, pBufferInfo_->uFourccFormat_ >> 8, pBufferInfo_->uFourccFormat_ >> 16, pBufferInfo_->uFourccFormat_ >> 24, pBufferInfo_->iUsage_, pBufferInfo_->uModifier_, pBufferInfo_->sLayerName_.c_str()); if(mDrawingState.buffer_ != mCurrentState.buffer_){ nsecs_t current_time = systemTime(); qFrameTimestamp_.push(current_time); qFrameTimestampBack_.push(current_time); while(qFrameTimestamp_.size() > MAX_NUM_FRAME_TIMESTAMP_CNT){ qFrameTimestamp_.pop(); qFrameTimestampBack_.pop(); } } } void set_output_buffer(buffer_handle_t buffer) { buffer_ = buffer; mCurrentState.buffer_ = buffer; // Bufferinfo Cache uint64_t buffer_id; drmGralloc_->hwc_get_handle_buffer_id(buffer_, &buffer_id); pBufferInfo_ = std::make_shared(); int ret = drmGralloc_->importBuffer(buffer_, &pBufferInfo_->native_buffer_); if(ret){ HWC2_ALOGD_IF_WARN("buffer-id=0x%" PRIx64 " importBuffer fail.", buffer_id); } pBufferInfo_->uBufferId_ = buffer_id; pBufferInfo_->iFd_ = base::unique_fd(dup(drmGralloc_->hwc_get_handle_primefd(buffer_))); pBufferInfo_->iWidth_ = drmGralloc_->hwc_get_handle_attibute(buffer_,ATT_WIDTH); pBufferInfo_->iHeight_ = drmGralloc_->hwc_get_handle_attibute(buffer_,ATT_HEIGHT); pBufferInfo_->iStride_ = drmGralloc_->hwc_get_handle_attibute(buffer_,ATT_STRIDE); pBufferInfo_->iSize_ = drmGralloc_->hwc_get_handle_attibute(buffer_,ATT_SIZE); pBufferInfo_->iHeightStride_ = drmGralloc_->hwc_get_handle_attibute(buffer_,ATT_HEIGHT_STRIDE); pBufferInfo_->iByteStride_ = drmGralloc_->hwc_get_handle_attibute(buffer_,ATT_BYTE_STRIDE_WORKROUND); pBufferInfo_->iFormat_ = drmGralloc_->hwc_get_handle_attibute(buffer_,ATT_FORMAT); pBufferInfo_->iUsage_ = drmGralloc_->hwc_get_handle_usage(buffer_); pBufferInfo_->uFourccFormat_ = drmGralloc_->hwc_get_handle_fourcc_format(buffer_); pBufferInfo_->uModifier_ = drmGralloc_->hwc_get_handle_format_modifier(buffer_); drmGralloc_->hwc_get_handle_name(buffer_,pBufferInfo_->sLayerName_); layer_name_ = pBufferInfo_->sLayerName_; HWC2_ALOGD_IF_VERBOSE("bufferInfoMap_ size = %zu insert success! BufferId=%" PRIx64 " fd=%d w=%d h=%d format=%d fourcc=%c%c%c%c usage=%" PRIx64 " modifier=%" PRIx64 " Name=%s", bufferInfoMap_.size(),buffer_id, pBufferInfo_->iFd_.get(), pBufferInfo_->iWidth_, pBufferInfo_->iHeight_, pBufferInfo_->iFormat_, pBufferInfo_->uFourccFormat_, pBufferInfo_->uFourccFormat_ >> 8, pBufferInfo_->uFourccFormat_ >> 16, pBufferInfo_->uFourccFormat_ >> 24, pBufferInfo_->iUsage_, pBufferInfo_->uModifier_, pBufferInfo_->sLayerName_.c_str()); } int initOrGetGemhanleFromCache(DrmHwcLayer* drmHwcLayer) { if(pBufferInfo_ == NULL){ HWC2_ALOGD_IF_VERBOSE("Id=%d pBufferInfo_ is NULL can't find BufferInfoCache!",id_); return -1; } // Bufferinfo Cache uint64_t buffer_id = pBufferInfo_->uBufferId_; if(!pBufferInfo_->gemHandle_.isValid()){ pBufferInfo_->gemHandle_.InitGemHandle(pBufferInfo_->sLayerName_.c_str(), pBufferInfo_->iFd_.get(), buffer_id); pBufferInfo_->uGemHandle_ = pBufferInfo_->gemHandle_.GetGemHandle(); drmHwcLayer->uGemHandle_ = pBufferInfo_->gemHandle_.GetGemHandle(); HWC2_ALOGD_IF_VERBOSE("bufferInfoMap_ init GemHandle success! BufferId=%" PRIx64 " Name=%s GemHandle=%d ptr=%p", buffer_id,pBufferInfo_->sLayerName_.c_str(), drmHwcLayer->uGemHandle_, drmHwcLayer); return 0; } drmHwcLayer->uGemHandle_ = pBufferInfo_->gemHandle_.GetGemHandle(); HWC2_ALOGD_IF_VERBOSE("bufferInfoMap_ GemHandle cache! BufferId=%" PRIx64 " Name=%s GemHandle=%d ptr=%p", buffer_id,pBufferInfo_->sLayerName_.c_str(), drmHwcLayer->uGemHandle_, drmHwcLayer); return 0; } void setSidebandStream(buffer_handle_t stream) { if(stream != sidebandStreamHandle_){ if(sidebandStreamHandle_ != NULL){ int ret = drmGralloc_->freeBuffer(sidebandStreamHandle_); if(ret){ ALOGE("freeBuffer sidebandStreamHandle = %p fail, ret=%d",sidebandStreamHandle_,ret); } sidebandStreamHandle_ = NULL; } if(stream != NULL){ buffer_handle_t tempHandle; int ret = drmGralloc_->importBuffer(stream,&tempHandle); if(ret){ ALOGE("importBuffer stream=%p, tempHandle=%p fail, ret=%d",stream,tempHandle,ret); } sidebandStreamHandle_ = tempHandle; mCurrentState.sidebandStreamHandle_ = tempHandle; } } // Bufferinfo Cache uint64_t buffer_id; drmGralloc_->hwc_get_handle_buffer_id(sidebandStreamHandle_, &buffer_id); bufferInfoMap_.clear(); auto ret = bufferInfoMap_.emplace(std::make_pair(buffer_id, std::make_shared())); if(ret.second == false){ HWC2_ALOGD_IF_VERBOSE("bufferInfoMap_ emplace fail! BufferHandle=%p",sidebandStreamHandle_); }else{ pBufferInfo_ = ret.first->second; pBufferInfo_->uBufferId_ = buffer_id; pBufferInfo_->iFd_ = base::unique_fd(dup(drmGralloc_->hwc_get_handle_primefd(sidebandStreamHandle_))); pBufferInfo_->iWidth_ = drmGralloc_->hwc_get_handle_attibute(sidebandStreamHandle_,ATT_WIDTH); pBufferInfo_->iHeight_ = drmGralloc_->hwc_get_handle_attibute(sidebandStreamHandle_,ATT_HEIGHT); pBufferInfo_->iStride_ = drmGralloc_->hwc_get_handle_attibute(sidebandStreamHandle_,ATT_STRIDE); pBufferInfo_->iHeightStride_ = drmGralloc_->hwc_get_handle_attibute(sidebandStreamHandle_,ATT_HEIGHT_STRIDE); pBufferInfo_->iByteStride_ = drmGralloc_->hwc_get_handle_attibute(sidebandStreamHandle_,ATT_BYTE_STRIDE_WORKROUND); pBufferInfo_->iFormat_ = drmGralloc_->hwc_get_handle_attibute(sidebandStreamHandle_,ATT_FORMAT); pBufferInfo_->iUsage_ = drmGralloc_->hwc_get_handle_usage(sidebandStreamHandle_); pBufferInfo_->uFourccFormat_ = drmGralloc_->hwc_get_handle_fourcc_format(sidebandStreamHandle_); pBufferInfo_->uModifier_ = drmGralloc_->hwc_get_handle_format_modifier(sidebandStreamHandle_); drmGralloc_->hwc_get_handle_name(sidebandStreamHandle_,pBufferInfo_->sLayerName_); layer_name_ = pBufferInfo_->sLayerName_; pBufferInfo_->gemHandle_.InitGemHandle(pBufferInfo_->sLayerName_.c_str(), pBufferInfo_->iFd_, buffer_id); pBufferInfo_->uGemHandle_ = pBufferInfo_->gemHandle_.GetGemHandle(); HWC2_ALOGD_IF_VERBOSE("bufferInfoMap_ size = %zu insert success! BufferId=%" PRIx64 " Name=%s", bufferInfoMap_.size(),buffer_id,pBufferInfo_->sLayerName_.c_str()); } } void set_acquire_fence(sp af) { acquire_fence_ = af; } const sp acquire_fence(){ return acquire_fence_; } void set_release_fence(sp rf) { release_fence_.add(rf); } const sp release_fence(){ return release_fence_.get(); } const sp back_release_fence(){ return release_fence_.get_back(); } uint32_t id(){ return id_; } // SidebandStream layer void PopulateSidebandLayer(DrmHwcLayer *layer, hwc2_drm_display_t* ctx); // Normal layer void PopulateNormalLayer(DrmHwcLayer *layer, hwc2_drm_display_t* ctx); void PopulateDrmLayer(hwc2_layer_t layer_id, DrmHwcLayer *layer, hwc2_drm_display_t* ctx, uint32_t frame_no); void PopulateFB(hwc2_layer_t layer_id, DrmHwcLayer *drmHwcLayer, hwc2_drm_display_t* ctx, uint32_t frame_no, bool validate); const std::shared_ptr GetBufferInfo() { return pBufferInfo_;}; void DumpLayerInfo(String8 &output); int DumpData(); void EnableAfbc() { is_afbc_ = true;}; void DisableAfbc() { is_afbc_ = false;}; bool isAfbc() { return is_afbc_;}; bool StateChange() { if(mCurrentState == mDrawingState){ return false; }else{ mDrawingState = mCurrentState; return true; } }; bool isSidebandLayer() { return bSideband2_; } int getTunnelId() { return mSidebandInfo_.tunnel_id; } float GetFps(){ nsecs_t current_time = systemTime(); nsecs_t start_time = qFrameTimestamp_.front(); while( !qFrameTimestamp_.empty() && (current_time - start_time > float(s2ns(1)) )){ qFrameTimestamp_.pop(); start_time = qFrameTimestamp_.front(); } if(!qFrameTimestamp_.empty()){ mFps_ = qFrameTimestamp_.size() * float(s2ns(1)) / (current_time - start_time); }else{ mFps_ = 0; } return mFps_; } float GetRealFps(){ nsecs_t end_time = qFrameTimestampBack_.back(); nsecs_t start_time = qFrameTimestampBack_.front(); if(qFrameTimestampBack_.size() > 10){ mRealFps_ = qFrameTimestampBack_.size() * float(s2ns(1)) / (end_time - start_time); if(mRealMaxFps_ < mRealFps_){ mRealMaxFps_ = (int)mRealFps_; } }else{ mRealFps_ = 60; } return mRealFps_; } int GetRealMaxFps(){ if(mRealMaxFps_ != -1){ return mRealMaxFps_; } return 60; } int DoSvep(bool validate, DrmHwcLayer *drmHwcLayer); int DoPq(bool validate, DrmHwcLayer *drmHwcLayer, hwc2_drm_display_t* ctx); // Layer hooks HWC2::Error SetCursorPosition(int32_t x, int32_t y); HWC2::Error SetLayerBlendMode(int32_t mode); HWC2::Error SetLayerBuffer(buffer_handle_t buffer, int32_t acquire_fence); HWC2::Error SetLayerColor(hwc_color_t color); HWC2::Error SetLayerCompositionType(int32_t type); HWC2::Error SetLayerDataspace(int32_t dataspace); HWC2::Error SetLayerDisplayFrame(hwc_rect_t frame); HWC2::Error SetLayerPlaneAlpha(float alpha); HWC2::Error SetLayerSidebandStream(const native_handle_t *stream); HWC2::Error SetLayerSourceCrop(hwc_frect_t crop); HWC2::Error SetLayerSurfaceDamage(hwc_region_t damage); HWC2::Error SetLayerTransform(int32_t transform); HWC2::Error SetLayerVisibleRegion(hwc_region_t visible); HWC2::Error SetLayerZOrder(uint32_t z); private: // Hwc2Layer id uint32_t id_; // Buffer Handle buffer_handle_t buffer_ = NULL; // SidebandStream Handle bool bSideband2_=false; bool bSideband2Valid_=false; buffer_handle_t sidebandStreamHandle_ = NULL; // current state vt_sideband_data_t mSidebandInfo_; // current frame state Hwc2LayerState_t mCurrentState; // last frame state Hwc2LayerState_t mDrawingState; // Fence sp acquire_fence_ = AcquireFence::NO_FENCE; DeferredReleaseFence release_fence_; // Buffer info map bool bHasCache_ = false; std::map> bufferInfoMap_; std::string layer_name_; bool is_afbc_; // Buffer info point std::shared_ptr pBufferInfo_ = NULL; // Hwc2Layer fps, for debug. std::queue qFrameTimestamp_; std::queue qFrameTimestampBack_; // 考虑世界时间的fps, 1s内不刷新则刷新率为0 float mFps_ = 0; // 图层更新的fps,不考虑世界时间,提供已刷新的图层刷新率 float mRealFps_ = 0; // 记录图层真实最高刷新率 int mRealMaxFps_ = -1; // DRM Resource DrmGralloc *drmGralloc_; DrmDevice *drm_; #ifdef USE_LIBPQ std::shared_ptr bufferQueue_; Pq* pq_; bool bPqReady_; PqContext pqCtx_; #endif }; struct HwcCallback { HwcCallback(hwc2_callback_data_t d, hwc2_function_pointer_t f) : data(d), func(f) { } hwc2_callback_data_t data; hwc2_function_pointer_t func; }; class HwcDisplay { public: HwcDisplay(ResourceManager *resource_manager, DrmDevice *drm, std::shared_ptr importer, hwc2_display_t handle, HWC2::DisplayType type); HwcDisplay(const HwcDisplay &) = delete; HWC2::Error Init(); HWC2::Error InitVirtual(); HWC2::Error CheckStateAndReinit(bool clear_layer = false); HWC2::Error RegisterVsyncCallback(hwc2_callback_data_t data, hwc2_function_pointer_t func); HWC2::Error UnregisterVsyncCallback(); HWC2::Error RegisterInvalidateCallback(hwc2_callback_data_t data, hwc2_function_pointer_t func); HWC2::Error UnregisterInvalidateCallback(); int ClearDisplay(); HWC2::Error CheckDisplayState(); // HWC Hooks HWC2::Error AcceptDisplayChanges(); HWC2::Error CreateLayer(hwc2_layer_t *layer); HWC2::Error DestroyLayer(hwc2_layer_t layer); HWC2::Error GetActiveConfig(hwc2_config_t *config); HWC2::Error GetChangedCompositionTypes(uint32_t *num_elements, hwc2_layer_t *layers, int32_t *types); HWC2::Error GetClientTargetSupport(uint32_t width, uint32_t height, int32_t format, int32_t dataspace); HWC2::Error GetColorModes(uint32_t *num_modes, int32_t *modes); HWC2::Error GetDisplayAttribute(hwc2_config_t config, int32_t attribute, int32_t *value); HWC2::Error GetDisplayConfigs(uint32_t *num_configs, hwc2_config_t *configs); HWC2::Error GetDisplayName(uint32_t *size, char *name); HWC2::Error GetDisplayRequests(int32_t *display_requests, uint32_t *num_elements, hwc2_layer_t *layers, int32_t *layer_requests); HWC2::Error GetDisplayType(int32_t *type); HWC2::Error GetDozeSupport(int32_t *support); HWC2::Error GetHdrCapabilities(uint32_t *num_types, int32_t *types, float *max_luminance, float *max_average_luminance, float *min_luminance); HWC2::Error GetReleaseFences(uint32_t *num_elements, hwc2_layer_t *layers, int32_t *fences); HWC2::Error PresentVirtualDisplay(int32_t *retire_fence); HWC2::Error PresentDisplay(int32_t *retire_fence); HWC2::Error SetActiveConfig(hwc2_config_t config); // RK:VRR HWC2::Error UpdateRefreshRate(hwc2_config_t config); HWC2::Error ChosePreferredConfig(); HWC2::Error SetClientTarget(buffer_handle_t target, int32_t acquire_fence, int32_t dataspace, hwc_region_t damage); HWC2::Error SetColorMode(int32_t mode); HWC2::Error SetColorTransform(const float *matrix, int32_t hint); HWC2::Error SetOutputBuffer(buffer_handle_t buffer, int32_t release_fence); HWC2::Error SetPowerMode(int32_t mode); HWC2::Error SyncPowerMode(); HWC2::Error SetVsyncEnabled(int32_t enabled); HWC2::Error ValidateDisplay(uint32_t *num_types, uint32_t *num_requests); HWC2::Error ValidateVirtualDisplay(uint32_t *num_types, uint32_t *num_requests); #ifdef ANDROID_S //composer 2.4 HWC2::Error GetDisplayConnectionType(uint32_t *outType); HWC2::Error GetDisplayVsyncPeriod(hwc2_vsync_period_t *outVsyncPeriod); #endif std::map &get_layers(){ return layers_; } bool has_layer(hwc2_layer_t layer) { return layers_.count(layer) > 0; } HwcLayer &get_layer(hwc2_layer_t layer) { return layers_.at(layer); } int DumpDisplayInfo(String8 &output); int DumpDisplayLayersInfo(String8 &output); int DumpDisplayLayersInfo(); int DumpAllLayerData(); bool PresentFinish(void) { return present_finish_; }; int HoplugEventTmeline(); int UpdateDisplayMode(); int UpdateDisplayInfo(); int UpdateHdmiOutputFormat(); int UpdateBCSH(); int UpdateOverscan(); int UpdateSidebandMode(); int SwitchHdrMode(); bool DisableHdrModeRK3588(); bool DisableHdrMode(); int EnableMetadataHdrMode(DrmHwcLayer& hdrLayer); int EnableHdrMode(DrmHwcLayer& hdrLayer); void UpdateSvepState(); int ActiveModeChange(bool change); bool IsActiveModeChange(); hwc2_drm_display_t* GetDisplayCtxPtr(); // Static Screen opt function int UpdateTimerEnable(); int UpdateTimerState(bool gles_comp); // SelfRefresh function int SelfRefreshEnable(); int EntreStaticScreen(uint64_t refresh, int refresh_cnt); int InvalidateControl(uint64_t refresh, int refresh_cnt); int isVirtual() { return type_ == HWC2::DisplayType::Virtual;} private: HWC2::Error ValidatePlanes(); HWC2::Error InitDrmHwcLayer(); HWC2::Error CreateComposition(); HWC2::Error ModifyHwcLayerDisplayFrame(bool only_fb_scale); int ImportBuffers(); void AddFenceToRetireFence(int fd); int DoMirrorDisplay(int32_t *retire_fence); ResourceManager *resource_manager_; DrmDevice *drm_; std::shared_ptr compositor_; std::shared_ptr importer_; std::unique_ptr planner_; std::vector drm_hwc_layers_; std::vector composition_planes_; std::vector plane_group; VSyncWorker vsync_worker_; InvalidateWorker invalidate_worker_; DrmConnector *connector_ = NULL; DrmCrtc *crtc_ = NULL; std::vector sf_modes_; hwc2_display_t handle_; HWC2::DisplayType type_; uint32_t layer_idx_ = 1; std::map layers_; HwcLayer client_layer_; // WriteBack 需要使用 HwcLayer output_layer_; std::set mHasResetBufferId_; int32_t color_mode_; bool init_success_; bool validate_success_; bool present_finish_; hwc2_drm_display_t ctx_; bool static_screen_timer_enable_; bool static_screen_opt_; bool force_gles_; bool bNeedSyncPMState_; HWC2::PowerMode mPowerMode_; int fb_blanked; int iLastLayerSize_; uint32_t frame_no_ = 0; uint64_t wb_frame_no_ = 0; SyncTimeline sync_timeline_; DeferredRetireFence d_retire_fence_; bool bDropFrame_; bool bLastSvepState_; bool bVrrDisplay_; bool bActiveModeChange_; bool bUseWriteBack_; int iLastTunnelId_=0; }; enum PLUG_EVENT_TYPE{ DRM_HOTPLUG_NONE = 0, DRM_HOTPLUG_PLUG_EVENT = 1, DRM_HOTPLUG_UNPLUG_EVENT = 2, }; class DrmHotplugHandler : public DrmEventHandler { public: DrmHotplugHandler(DrmHwcTwo *hwc2, DrmDevice *drm) : hwc2_(hwc2), drm_(drm) { } void HdmiTvOnlyOne(PLUG_EVENT_TYPE hdmi_hotplug_state); void HandleEvent(uint64_t timestamp_us); void HandleResolutionSwitchEvent(int display_id); private: DrmHwcTwo *hwc2_; DrmDevice *drm_; }; static DrmHwcTwo *toDrmHwcTwo(hwc2_device_t *dev) { return static_cast(dev); } template static hwc2_function_pointer_t ToHook(T function) { static_assert(std::is_same::value, "Incompatible fn pointer"); return reinterpret_cast(function); } template static T DeviceHook(hwc2_device_t *dev, Args... args) { DrmHwcTwo *hwc = toDrmHwcTwo(dev); return static_cast(((*hwc).*func)(std::forward(args)...)); } template static int32_t DisplayHook(hwc2_device_t *dev, hwc2_display_t display_handle, Args... args) { DrmHwcTwo *hwc = toDrmHwcTwo(dev); if(hwc->displays_.count(display_handle)){ HwcDisplay &display = hwc->displays_.at(display_handle); return static_cast((display.*func)(std::forward(args)...)); }else{ return static_cast(HWC2::Error::BadDisplay); } } template static int32_t LayerHook(hwc2_device_t *dev, hwc2_display_t display_handle, hwc2_layer_t layer_handle, Args... args) { DrmHwcTwo *hwc = toDrmHwcTwo(dev); if(hwc->displays_.count(display_handle)){ HwcDisplay &display = hwc->displays_.at(display_handle); if(display.has_layer(layer_handle)){ HwcLayer &layer = display.get_layer(layer_handle); return static_cast((layer.*func)(std::forward(args)...)); }else{ return static_cast(HWC2::Error::BadLayer); } }else{ return static_cast(HWC2::Error::BadDisplay); } } // hwc2_device_t hooks static int HookDevClose(hw_device_t *dev); static void HookDevGetCapabilities(hwc2_device_t *dev, uint32_t *out_count, int32_t *out_capabilities); static hwc2_function_pointer_t HookDevGetFunction(struct hwc2_device *device, int32_t descriptor); // Device functions HWC2::Error CreateVirtualDisplay(uint32_t width, uint32_t height, int32_t *format, hwc2_display_t *display); HWC2::Error DestroyVirtualDisplay(hwc2_display_t display); void Dump(uint32_t *size, char *buffer); uint32_t GetMaxVirtualDisplayCount(); HWC2::Error RegisterCallback(int32_t descriptor, hwc2_callback_data_t data, hwc2_function_pointer_t function); HWC2::Error CreateDisplay(hwc2_display_t displ, HWC2::DisplayType type); void HandleDisplayHotplug(hwc2_display_t displayid, int state); void HandleInitialHotplugState(DrmDevice *drmDevice); bool IsHasRegisterDisplayId(hwc2_display_t displayid); static void StaticScreenOptHandler(int sig){ if (sig == SIGALRM) if(g_ctx!=NULL){ HwcDisplay &display = g_ctx->displays_.at(0); display.EntreStaticScreen(60,1); } return; }; ResourceManager *resource_manager_; std::map displays_; std::map callbacks_; std::string mDumpString; std::atomic mVirtualDisplayCount_; // 通过 mHasRegisterDisplay_ 存储已向SurfaceFlinger注册的display std::set mHasRegisterDisplay_; }; } // namespace android #endif // DRM_HWC_TWO_H