190 lines
7.5 KiB
C++
190 lines
7.5 KiB
C++
/* Copyright Statement:
|
|
*
|
|
* This software/firmware and related documentation ("MediaTek Software") are
|
|
* protected under relevant copyright laws. The information contained herein is
|
|
* confidential and proprietary to MediaTek Inc. and/or its licensors. Without
|
|
* the prior written permission of MediaTek inc. and/or its licensors, any
|
|
* reproduction, modification, use or disclosure of MediaTek Software, and
|
|
* information contained herein, in whole or in part, shall be strictly
|
|
* prohibited.
|
|
*
|
|
* MediaTek Inc. (C) 2022. All rights reserved.
|
|
*
|
|
* BY OPENING THIS FILE, RECEIVER HEREBY UNEQUIVOCALLY ACKNOWLEDGES AND AGREES
|
|
* THAT THE SOFTWARE/FIRMWARE AND ITS DOCUMENTATIONS ("MEDIATEK SOFTWARE")
|
|
* RECEIVED FROM MEDIATEK AND/OR ITS REPRESENTATIVES ARE PROVIDED TO RECEIVER
|
|
* ON AN "AS-IS" BASIS ONLY. MEDIATEK EXPRESSLY DISCLAIMS ANY AND ALL
|
|
* WARRANTIES, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED
|
|
* WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR
|
|
* NONINFRINGEMENT. NEITHER DOES MEDIATEK PROVIDE ANY WARRANTY WHATSOEVER WITH
|
|
* RESPECT TO THE SOFTWARE OF ANY THIRD PARTY WHICH MAY BE USED BY,
|
|
* INCORPORATED IN, OR SUPPLIED WITH THE MEDIATEK SOFTWARE, AND RECEIVER AGREES
|
|
* TO LOOK ONLY TO SUCH THIRD PARTY FOR ANY WARRANTY CLAIM RELATING THERETO.
|
|
* RECEIVER EXPRESSLY ACKNOWLEDGES THAT IT IS RECEIVER'S SOLE RESPONSIBILITY TO
|
|
* OBTAIN FROM ANY THIRD PARTY ALL PROPER LICENSES CONTAINED IN MEDIATEK
|
|
* SOFTWARE. MEDIATEK SHALL ALSO NOT BE RESPONSIBLE FOR ANY MEDIATEK SOFTWARE
|
|
* RELEASES MADE TO RECEIVER'S SPECIFICATION OR TO CONFORM TO A PARTICULAR
|
|
* STANDARD OR OPEN FORUM. RECEIVER'S SOLE AND EXCLUSIVE REMEDY AND MEDIATEK'S
|
|
* ENTIRE AND CUMULATIVE LIABILITY WITH RESPECT TO THE MEDIATEK SOFTWARE
|
|
* RELEASED HEREUNDER WILL BE, AT MEDIATEK'S OPTION, TO REVISE OR REPLACE THE
|
|
* MEDIATEK SOFTWARE AT ISSUE, OR REFUND ANY SOFTWARE LICENSE FEES OR SERVICE
|
|
* CHARGE PAID BY RECEIVER TO MEDIATEK FOR SUCH MEDIATEK SOFTWARE AT ISSUE.
|
|
*
|
|
* The following software/firmware and/or related documentation ("MediaTek
|
|
* Software") have been modified by MediaTek Inc. All revisions are subject to
|
|
* any receiver's applicable license agreements with MediaTek Inc.
|
|
*/
|
|
|
|
#pragma once
|
|
|
|
#define ATRACE_TAG ATRACE_TAG_GRAPHICS
|
|
|
|
#include <log/log.h>
|
|
#include <thread>
|
|
#include <utils/Trace.h>
|
|
#include <utils/Mutex.h>
|
|
#include <android-base/properties.h>
|
|
|
|
#define MAX_DELAY_COUNT 5
|
|
|
|
namespace android {
|
|
// ---------------------------------------------------------------------------
|
|
class ScheduleHelper
|
|
{
|
|
public:
|
|
bool mDebug;
|
|
int64_t mDelayTransactionThreshold;
|
|
size_t mPendingTransactionsCount;
|
|
size_t mLocklessTransactionsCount;
|
|
int64_t mSfWorkDuration;
|
|
int64_t mVsyncPeriod;
|
|
int64_t mLastScheduledPresentTime;
|
|
|
|
std::vector<int64_t> mDelayedTimesForPending;
|
|
std::vector<int64_t> mDelayedTimesForLockless;
|
|
|
|
Mutex mPendings;
|
|
Mutex mLockless;
|
|
Mutex mGeneral;
|
|
static ScheduleHelper& getInstance() {
|
|
static ScheduleHelper gInstance;
|
|
return gInstance;
|
|
}
|
|
|
|
~ScheduleHelper() {};
|
|
|
|
int64_t getDelayTimeForTransaction(bool isauto, int64_t desiredTime) {
|
|
int64_t delayed_time = 0;
|
|
if (!isauto) {
|
|
Mutex::Autolock lock(mGeneral);
|
|
const auto now = systemTime();
|
|
// we add 2ms to cover slight shift of presentTime
|
|
const auto nextPredictedPresentTime = mLastScheduledPresentTime + mVsyncPeriod + ms2ns(2);
|
|
const auto delayedWakeUpTime = desiredTime - mSfWorkDuration;
|
|
delayed_time = delayedWakeUpTime - now;
|
|
if (desiredTime <= nextPredictedPresentTime || // don't delay if it is in next vsync.
|
|
delayed_time > mDelayTransactionThreshold) { // don't delay too much
|
|
delayed_time = 0;
|
|
}
|
|
}
|
|
ATRACE_INT64("delayedTransaction", delayed_time);
|
|
return delayed_time;
|
|
}
|
|
|
|
int64_t checkDelayTimeForPendingTransaction(bool isauto, int64_t desiredTime) {
|
|
int64_t delayTime = getDelayTimeForTransaction(isauto, desiredTime);
|
|
Mutex::Autolock lock(mPendings);
|
|
if (delayTime > 0 && mDelayedTimesForPending.size() < MAX_DELAY_COUNT) {
|
|
if (mDelayedTimesForPending.size() < MAX_DELAY_COUNT) {
|
|
mDelayedTimesForPending.push_back(delayTime);
|
|
} else {
|
|
ALOGW("can't delay more pending transaction");
|
|
}
|
|
}
|
|
return delayTime;
|
|
}
|
|
|
|
int64_t checkDelayForLocklessTransaction(bool isauto, int64_t desiredTime) {
|
|
return getDelayTimeForTransaction(isauto, desiredTime);
|
|
}
|
|
|
|
void queueDelayTimeForLocklessTransaction(int64_t delayTime) {
|
|
Mutex::Autolock lock(mLockless);
|
|
mLocklessTransactionsCount+=1;
|
|
if (delayTime > 0 && mDelayedTimesForLockless.size() < MAX_DELAY_COUNT) {
|
|
if (mDelayedTimesForLockless.size() < MAX_DELAY_COUNT) {
|
|
mDelayedTimesForLockless.push_back(delayTime);
|
|
} else {
|
|
ALOGW("can't delay more lockless transaction");
|
|
}
|
|
}
|
|
}
|
|
|
|
int64_t getNextDelayedTimeOfPendingTransactions() {
|
|
Mutex::Autolock lock(mPendings);
|
|
if (mDelayedTimesForPending.empty()) return 0;
|
|
int64_t delayTime = mDelayedTimesForPending.back();
|
|
mDelayedTimesForPending.pop_back();
|
|
return delayTime;
|
|
}
|
|
|
|
void updateDurationVsync(int64_t sfduration, int64_t vsync) {
|
|
Mutex::Autolock lock(mGeneral);
|
|
mSfWorkDuration = sfduration;
|
|
mVsyncPeriod = vsync;
|
|
}
|
|
|
|
void updateLastSchedulePresentTime(int64_t time) {
|
|
Mutex::Autolock lock(mGeneral);
|
|
mLastScheduledPresentTime = time;
|
|
}
|
|
|
|
void resetLocklessCount() {
|
|
Mutex::Autolock lock(mLockless);
|
|
mDelayedTimesForLockless.clear();
|
|
mLocklessTransactionsCount = 0;
|
|
}
|
|
|
|
void increasePendingTransactionsCount() {
|
|
Mutex::Autolock lock(mPendings);
|
|
mPendingTransactionsCount += 1;
|
|
}
|
|
|
|
void resetPendingTransactionsCount() {
|
|
Mutex::Autolock lock(mPendings);
|
|
mPendingTransactionsCount = 0;
|
|
}
|
|
|
|
bool hasPendingTransactions() {
|
|
Mutex::Autolock lock1(mPendings);
|
|
Mutex::Autolock lock2(mLockless);
|
|
// If all pending transactions are delayed and all lockless transactions
|
|
// are delayed, there is no pending transactions.
|
|
if (mDebug) {
|
|
ATRACE_INT("PendingTransactionsCount", static_cast<int>(mPendingTransactionsCount));
|
|
ATRACE_INT("DelayedTimesForPending", static_cast<int>(mDelayedTimesForPending.size()));
|
|
ATRACE_INT("LocklessTransactionsCount", static_cast<int>(mLocklessTransactionsCount));
|
|
ATRACE_INT("DelayedTimesForLockless", static_cast<int>(mDelayedTimesForLockless.size()));
|
|
}
|
|
if ((mPendingTransactionsCount - mDelayedTimesForPending.size() == 0) &&
|
|
(mLocklessTransactionsCount - mDelayedTimesForLockless.size() ==0)) {
|
|
return false;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
private:
|
|
ScheduleHelper() {
|
|
mDebug = base::GetBoolProperty("debug.sf.schedule_helper", false);
|
|
mDelayTransactionThreshold = base::GetIntProperty("debug.sf.mDelayTransactionThreshold", 500000000);
|
|
mDelayedTimesForPending.reserve(MAX_DELAY_COUNT);
|
|
mDelayedTimesForLockless.reserve(MAX_DELAY_COUNT);
|
|
mPendingTransactionsCount = 0;
|
|
mLocklessTransactionsCount = 0;
|
|
mSfWorkDuration = 0;
|
|
mVsyncPeriod = 0;
|
|
mLastScheduledPresentTime = 0;
|
|
}
|
|
};
|
|
// ---------------------------------------------------------------------------
|
|
}; // namespace android
|