summaryrefslogtreecommitdiff
path: root/libhwc2.1/libvrr/VariableRefreshRateController.h
diff options
context:
space:
mode:
Diffstat (limited to 'libhwc2.1/libvrr/VariableRefreshRateController.h')
-rw-r--r--libhwc2.1/libvrr/VariableRefreshRateController.h207
1 files changed, 207 insertions, 0 deletions
diff --git a/libhwc2.1/libvrr/VariableRefreshRateController.h b/libhwc2.1/libvrr/VariableRefreshRateController.h
new file mode 100644
index 0000000..1a20109
--- /dev/null
+++ b/libhwc2.1/libvrr/VariableRefreshRateController.h
@@ -0,0 +1,207 @@
+/*
+ * Copyright (C) 2023 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.
+ */
+
+#pragma once
+
+#include <utils/Mutex.h>
+#include <condition_variable>
+#include <list>
+#include <map>
+#include <optional>
+#include <queue>
+#include <thread>
+
+#include "../libdevice/ExynosDisplay.h"
+#include "RingBuffer.h"
+#include "VariableRefreshRateInterface.h"
+
+namespace android::hardware::graphics::composer {
+
+constexpr uint64_t kMillisecondToNanoSecond = 1000000;
+
+class VariableRefreshRateController : public VsyncListener, public PresentListener {
+public:
+ ~VariableRefreshRateController();
+
+ auto static CreateInstance(ExynosDisplay* display)
+ -> std::shared_ptr<VariableRefreshRateController>;
+
+ int notifyExpectedPresent(int64_t timestamp, int32_t frameIntervalNs);
+
+ // Clear historical record data.
+ void reset();
+
+ // After setting the active Vrr configuration, we will automatically transition into the
+ // rendering state and post the timeout event.
+ void setActiveVrrConfiguration(hwc2_config_t config);
+
+ void setEnable(bool isEnabled);
+
+ void setPowerMode(int32_t mode);
+
+ void setVrrConfigurations(std::unordered_map<hwc2_config_t, VrrConfig_t> configs);
+
+private:
+ static constexpr int kDefaultRingBufferCapacity = 128;
+ static constexpr int64_t kDefaultWakeUpTimeInPowerSaving =
+ 500 * (std::nano::den / std::milli::den); // 500 ms
+ static constexpr int64_t SIGNAL_TIME_PENDING = INT64_MAX;
+ static constexpr int64_t SIGNAL_TIME_INVALID = -1;
+
+ static const std::string kFrameInsertionNodeName;
+ static constexpr int kDefaultNumFramesToInsert = 2;
+ static constexpr int64_t kDefaultFrameInsertionTimer =
+ 33 * (std::nano::den / std::milli::den); // 33 ms
+
+ enum class VrrControllerState {
+ kDisable = 0,
+ kRendering,
+ kHibernate,
+ };
+
+ typedef struct PresentEvent {
+ hwc2_config_t config;
+ int64_t mTime;
+ int mDuration;
+ } PresentEvent;
+
+ typedef struct VsyncEvent {
+ enum class Type {
+ kVblank,
+ kReleaseFence,
+ };
+ Type mType;
+ int64_t mTime;
+ } VsyncEvent;
+
+ typedef struct VrrRecord {
+ static constexpr int kDefaultRingBufferCapacity = 128;
+
+ void clear() {
+ mNextExpectedPresentTime = std::nullopt;
+ mPendingCurrentPresentTime = std::nullopt;
+ mPresentHistory.clear();
+ mVsyncHistory.clear();
+ }
+
+ std::optional<PresentEvent> mNextExpectedPresentTime = std::nullopt;
+ std::optional<PresentEvent> mPendingCurrentPresentTime = std::nullopt;
+
+ typedef RingBuffer<PresentEvent, kDefaultRingBufferCapacity> PresentTimeRecord;
+ typedef RingBuffer<VsyncEvent, kDefaultRingBufferCapacity> VsyncRecord;
+ PresentTimeRecord mPresentHistory;
+ VsyncRecord mVsyncHistory;
+ } VrrRecord;
+
+ enum VrrControllerEventType {
+ kRenderingTimeout = 0,
+ kHibernateTimeout,
+ kNotifyExpectedPresentConfig,
+ kNextFrameInsertion,
+ // Sensors, outer events...
+ };
+
+ struct VrrControllerEvent {
+ bool operator<(const VrrControllerEvent& b) const { return mWhenNs > b.mWhenNs; }
+ std::string getName() const {
+ switch (mEventType) {
+ case kRenderingTimeout:
+ return "RenderingTimeout";
+ case kHibernateTimeout:
+ return "kHibernateTimeout";
+ case kNotifyExpectedPresentConfig:
+ return "NotifyExpectedPresentConfig";
+ case kNextFrameInsertion:
+ return "kNextFrameInsertion";
+ default:
+ return "Unknown";
+ }
+ }
+
+ std::string toString() const {
+ std::ostringstream os;
+ os << "Vrr event: [";
+ os << "type = " << getName() << ", ";
+ os << "when = " << mWhenNs << "ns]";
+ return os.str();
+ }
+ int64_t mDisplay;
+ VrrControllerEventType mEventType;
+ int64_t mWhenNs;
+ };
+
+ VariableRefreshRateController(ExynosDisplay* display);
+
+ // Implement interface PresentListener.
+ virtual void onPresent(int32_t fence) override;
+ virtual void setExpectedPresentTime(int64_t timestampNanos, int frameIntervalNs) override;
+
+ // Implement interface VsyncListener.
+ virtual void onVsync(int64_t timestamp, int32_t vsyncPeriodNanos) override;
+
+ void cancelFrameInsertionLocked();
+
+ int doFrameInsertionLocked();
+ int doFrameInsertionLocked(int frames);
+
+ void dropEventLocked();
+ void dropEventLocked(VrrControllerEventType event_type);
+
+ std::string dumpEventQueueLocked();
+
+ int64_t getLastFenceSignalTimeUnlocked(int fd);
+
+ int64_t getNextEventTimeLocked() const;
+
+ std::string getStateName(VrrControllerState state) const;
+
+ // Functions responsible for state machine transitions.
+ void handleCadenceChange();
+ void handleResume();
+ void handleHibernate();
+ void handleStayHibernate();
+
+ void postEvent(VrrControllerEventType type, int64_t when);
+
+ void stopThread(bool exit);
+
+ // The core function of the VRR controller thread.
+ void threadBody();
+
+ void updateVsyncHistory();
+
+ ExynosDisplay* mDisplay;
+
+ // The subsequent variables must be guarded by mMutex when accessed.
+ int mPendingFramesToInsert = 0;
+ std::priority_queue<VrrControllerEvent> mEventQueue;
+ VrrRecord mRecord;
+ int32_t mPowerMode = -1;
+ VrrControllerState mState;
+ hwc2_config_t mVrrActiveConfig;
+ std::unordered_map<hwc2_config_t, VrrConfig_t> mVrrConfigs;
+ std::optional<int> mLastPresentFence;
+
+ std::unique_ptr<FileNodeWriter> mFileNodeWritter;
+
+ bool mEnabled = false;
+ bool mThreadExit = false;
+
+ std::mutex mMutex;
+ std::condition_variable mCondition;
+};
+
+} // namespace android::hardware::graphics::composer