You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
223 lines
7.5 KiB
223 lines
7.5 KiB
/*
|
|
* Copyright (c) 2019, 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.
|
|
*/
|
|
#define ATRACE_TAG (ATRACE_TAG_GRAPHICS | ATRACE_TAG_HAL)
|
|
|
|
#include <cutils/trace.h>
|
|
#include <drm_logger.h>
|
|
|
|
#include "drm_atomic_req.h"
|
|
#include "drm_connector.h"
|
|
#include "drm_crtc.h"
|
|
#include "drm_manager.h"
|
|
#include "drm_plane.h"
|
|
#include "string.h"
|
|
|
|
#define __CLASS__ "DRMAtomicReq"
|
|
|
|
namespace sde_drm {
|
|
|
|
DRMAtomicReq::DRMAtomicReq(int fd, DRMManager *drm_mgr) : drm_mgr_(drm_mgr), fd_(fd) {}
|
|
|
|
DRMAtomicReq::~DRMAtomicReq() {
|
|
if (drm_atomic_req_) {
|
|
drmModeAtomicFree(drm_atomic_req_);
|
|
drm_atomic_req_ = nullptr;
|
|
}
|
|
}
|
|
|
|
int DRMAtomicReq::Init(const DRMDisplayToken &tok) {
|
|
token_ = tok;
|
|
drm_atomic_req_ = drmModeAtomicAlloc();
|
|
if (!drm_atomic_req_) {
|
|
return -ENOMEM;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
int DRMAtomicReq::Perform(DRMOps opcode, uint32_t obj_id, ...) {
|
|
va_list args;
|
|
va_start(args, obj_id);
|
|
switch (opcode) {
|
|
case DRMOps::PLANE_SET_SRC_RECT:
|
|
case DRMOps::PLANE_SET_DST_RECT:
|
|
case DRMOps::PLANE_SET_ZORDER:
|
|
case DRMOps::PLANE_SET_ROTATION:
|
|
case DRMOps::PLANE_SET_ALPHA:
|
|
case DRMOps::PLANE_SET_BLEND_TYPE:
|
|
case DRMOps::PLANE_SET_H_DECIMATION:
|
|
case DRMOps::PLANE_SET_V_DECIMATION:
|
|
case DRMOps::PLANE_SET_FB_ID:
|
|
case DRMOps::PLANE_SET_ROT_FB_ID:
|
|
case DRMOps::PLANE_SET_CRTC:
|
|
case DRMOps::PLANE_SET_SRC_CONFIG:
|
|
case DRMOps::PLANE_SET_INPUT_FENCE:
|
|
case DRMOps::PLANE_SET_SCALER_CONFIG:
|
|
case DRMOps::PLANE_SET_FB_SECURE_MODE:
|
|
case DRMOps::PLANE_SET_CSC_CONFIG:
|
|
case DRMOps::PLANE_SET_MULTIRECT_MODE:
|
|
case DRMOps::PLANE_SET_EXCL_RECT:
|
|
case DRMOps::PLANE_SET_INVERSE_PMA:
|
|
case DRMOps::PLANE_SET_DGM_CSC_CONFIG:
|
|
case DRMOps::PLANE_SET_POST_PROC:
|
|
case DRMOps::PLANE_SET_SSPP_LAYOUT: {
|
|
drm_mgr_->GetPlaneMgr()->Perform(opcode, obj_id, drm_atomic_req_, args);
|
|
} break;
|
|
case DRMOps::CRTC_SET_POST_PROC:
|
|
case DRMOps::CRTC_SET_MODE:
|
|
case DRMOps::CRTC_SET_ACTIVE:
|
|
case DRMOps::CRTC_SET_OUTPUT_FENCE_OFFSET:
|
|
case DRMOps::CRTC_SET_CORE_CLK:
|
|
case DRMOps::CRTC_SET_CORE_AB:
|
|
case DRMOps::CRTC_SET_CORE_IB:
|
|
case DRMOps::CRTC_SET_LLCC_AB:
|
|
case DRMOps::CRTC_SET_LLCC_IB:
|
|
case DRMOps::CRTC_SET_DRAM_AB:
|
|
case DRMOps::CRTC_SET_DRAM_IB:
|
|
case DRMOps::CRTC_SET_ROT_PREFILL_BW:
|
|
case DRMOps::CRTC_SET_ROT_CLK:
|
|
case DRMOps::CRTC_GET_RELEASE_FENCE:
|
|
case DRMOps::CRTC_SET_ROI:
|
|
case DRMOps::CRTC_SET_SECURITY_LEVEL:
|
|
case DRMOps::CRTC_SET_SOLIDFILL_STAGES:
|
|
case DRMOps::CRTC_SET_IDLE_TIMEOUT:
|
|
case DRMOps::CRTC_SET_DEST_SCALER_CONFIG:
|
|
case DRMOps::CRTC_SET_CAPTURE_MODE:
|
|
case DRMOps::CRTC_SET_IDLE_PC_STATE: {
|
|
drm_mgr_->GetCrtcMgr()->Perform(opcode, obj_id, drm_atomic_req_, args);
|
|
} break;
|
|
case DRMOps::CONNECTOR_SET_CRTC:
|
|
case DRMOps::CONNECTOR_GET_RETIRE_FENCE:
|
|
case DRMOps::CONNECTOR_SET_OUTPUT_RECT:
|
|
case DRMOps::CONNECTOR_SET_OUTPUT_FB_ID:
|
|
case DRMOps::CONNECTOR_SET_POWER_MODE:
|
|
case DRMOps::CONNECTOR_SET_ROI:
|
|
case DRMOps::CONNECTOR_SET_AUTOREFRESH:
|
|
case DRMOps::CONNECTOR_SET_FB_SECURE_MODE:
|
|
case DRMOps::CONNECTOR_SET_POST_PROC:
|
|
case DRMOps::CONNECTOR_SET_HDR_METADATA:
|
|
case DRMOps::CONNECTOR_SET_QSYNC_MODE:
|
|
case DRMOps::CONNECTOR_SET_TOPOLOGY_CONTROL:
|
|
case DRMOps::CONNECTOR_SET_FRAME_TRIGGER:
|
|
case DRMOps::CONNECTOR_SET_COLORSPACE: {
|
|
drm_mgr_->GetConnectorMgr()->Perform(opcode, obj_id, drm_atomic_req_, args);
|
|
} break;
|
|
case DRMOps::DPPS_CACHE_FEATURE: {
|
|
drm_mgr_->GetDppsMgrIntf()->CacheDppsFeature(obj_id, args);
|
|
} break;
|
|
case DRMOps::DPPS_COMMIT_FEATURE: {
|
|
drm_mgr_->GetDppsMgrIntf()->CommitDppsFeatures(drm_atomic_req_, token_);
|
|
} break;
|
|
default:
|
|
DRM_LOGE("Invalid opcode %d", opcode);
|
|
}
|
|
va_end(args);
|
|
return 0;
|
|
}
|
|
|
|
int DRMAtomicReq::CallAtomic(DRMCrtc *crtc, uint32_t flags)
|
|
{
|
|
auto plane_mgr = drm_mgr_->GetPlaneMgr();
|
|
size_t cnt;
|
|
|
|
cnt = plane_mgr->ApplyDirtyProperties(drm_atomic_req_);
|
|
ATRACE_INT("dirtyPlaneProps", cnt);
|
|
cnt = crtc->ApplyDirtyProperties(drm_atomic_req_);
|
|
ATRACE_INT("dirtyCrtcProps", cnt);
|
|
|
|
int ret = drmModeAtomicCommit(fd_, drm_atomic_req_, flags, nullptr);
|
|
if (ret) {
|
|
DRM_LOGE("drmModeAtomicCommit failed with error %d (%s).", errno, strerror(errno));
|
|
/* reset all properties so next atomic commit applies all values */
|
|
crtc->ClearProperties();
|
|
plane_mgr->ClearProperties();
|
|
}
|
|
|
|
// reset the drm_atomic_req_ for next call
|
|
drmModeAtomicSetCursor(drm_atomic_req_, 0);
|
|
|
|
return ret;
|
|
}
|
|
|
|
int DRMAtomicReq::Validate() {
|
|
auto crtc = drm_mgr_->GetCrtcMgr()->GetObject(token_.crtc_id);
|
|
if (crtc == nullptr) {
|
|
DRM_LOGE("Invalid crtc %d", token_.crtc_id);
|
|
return -EINVAL;
|
|
}
|
|
|
|
drm_mgr_->GetPlaneMgr()->UnsetUnusedResources(token_.crtc_id, false /*is_commit*/,
|
|
drm_atomic_req_);
|
|
int ret = CallAtomic(crtc, DRM_MODE_ATOMIC_ALLOW_MODESET | DRM_MODE_ATOMIC_TEST_ONLY);
|
|
if (!ret)
|
|
crtc->PostValidate();
|
|
|
|
// reset any dirty properties, all properties should be set again before Commit
|
|
crtc->DiscardDirtyProperties();
|
|
drm_mgr_->GetPlaneMgr()->PostValidate(token_.crtc_id);
|
|
|
|
return ret;
|
|
}
|
|
|
|
int DRMAtomicReq::Commit(bool synchronous, bool retain_planes) {
|
|
DTRACE_SCOPED();
|
|
auto crtc = drm_mgr_->GetCrtcMgr()->GetObject(token_.crtc_id);
|
|
if (crtc == nullptr) {
|
|
DRM_LOGE("Invalid crtc %d", token_.crtc_id);
|
|
return -EINVAL;
|
|
}
|
|
|
|
if (retain_planes) {
|
|
// It is not enough to simply avoid calling UnsetUnusedPlanes, since state transitons have to
|
|
// be correct when CommitPlaneState is called
|
|
drm_mgr_->GetPlaneMgr()->RetainPlanes(token_.crtc_id);
|
|
}
|
|
|
|
drm_mgr_->GetPlaneMgr()->UnsetUnusedResources(token_.crtc_id, true /*is_commit*/,
|
|
drm_atomic_req_);
|
|
|
|
uint32_t flags = DRM_MODE_ATOMIC_ALLOW_MODESET;
|
|
|
|
if (!synchronous) {
|
|
flags |= DRM_MODE_ATOMIC_NONBLOCK;
|
|
}
|
|
|
|
int ret = CallAtomic(crtc, flags);
|
|
|
|
drm_mgr_->GetPlaneMgr()->PostCommit(token_.crtc_id, !ret);
|
|
crtc->PostCommit(!ret);
|
|
|
|
ATRACE_INT("dirtyPlaneProps", 0);
|
|
ATRACE_INT("dirtyCrtcProps", 0);
|
|
|
|
return ret;
|
|
}
|
|
|
|
} // namespace sde_drm
|