| Ana Krulec | 241cf83 | 2018-08-10 15:03:23 -0700 | [diff] [blame] | 1 | /* | 
 | 2 |  * Copyright 2018 The Android Open Source Project | 
 | 3 |  * | 
 | 4 |  * Licensed under the Apache License, Version 2.0 (the "License"); | 
 | 5 |  * you may not use this file except in compliance with the License. | 
 | 6 |  * You may obtain a copy of the License at | 
 | 7 |  * | 
 | 8 |  *      http://www.apache.org/licenses/LICENSE-2.0 | 
 | 9 |  * | 
 | 10 |  * Unless required by applicable law or agreed to in writing, software | 
 | 11 |  * distributed under the License is distributed on an "AS IS" BASIS, | 
 | 12 |  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | 
 | 13 |  * See the License for the specific language governing permissions and | 
 | 14 |  * limitations under the License. | 
 | 15 |  */ | 
 | 16 |  | 
| Midas Chien | bc5f22f | 2018-08-16 15:51:19 +0800 | [diff] [blame] | 17 | #define ATRACE_TAG ATRACE_TAG_GRAPHICS | 
 | 18 |  | 
| Ana Krulec | 241cf83 | 2018-08-10 15:03:23 -0700 | [diff] [blame] | 19 | #include "DispSyncSource.h" | 
 | 20 |  | 
| Ana Krulec | 072233f | 2018-08-10 15:03:23 -0700 | [diff] [blame] | 21 | #include <android-base/stringprintf.h> | 
| Ana Krulec | 241cf83 | 2018-08-10 15:03:23 -0700 | [diff] [blame] | 22 | #include <utils/Trace.h> | 
| Ana Krulec | 072233f | 2018-08-10 15:03:23 -0700 | [diff] [blame] | 23 | #include <mutex> | 
| Ana Krulec | 241cf83 | 2018-08-10 15:03:23 -0700 | [diff] [blame] | 24 |  | 
 | 25 | #include "DispSync.h" | 
 | 26 | #include "EventThread.h" | 
 | 27 |  | 
 | 28 | namespace android { | 
 | 29 |  | 
| Ady Abraham | 45e4e36 | 2019-06-07 18:20:51 -0700 | [diff] [blame] | 30 | DispSyncSource::DispSyncSource(DispSync* dispSync, nsecs_t phaseOffset, | 
 | 31 |                                nsecs_t offsetThresholdForNextVsync, bool traceVsync, | 
| Ana Krulec | 241cf83 | 2018-08-10 15:03:23 -0700 | [diff] [blame] | 32 |                                const char* name) | 
 | 33 |       : mName(name), | 
| Ana Krulec | 241cf83 | 2018-08-10 15:03:23 -0700 | [diff] [blame] | 34 |         mTraceVsync(traceVsync), | 
| Ana Krulec | 072233f | 2018-08-10 15:03:23 -0700 | [diff] [blame] | 35 |         mVsyncOnLabel(base::StringPrintf("VsyncOn-%s", name)), | 
 | 36 |         mVsyncEventLabel(base::StringPrintf("VSYNC-%s", name)), | 
| Alec Mouri | d7599d8 | 2019-05-22 19:58:00 -0700 | [diff] [blame] | 37 |         mVsyncOffsetLabel(base::StringPrintf("VsyncOffset-%s", name)), | 
 | 38 |         mVsyncNegativeOffsetLabel(base::StringPrintf("VsyncNegativeOffset-%s", name)), | 
| Ana Krulec | 241cf83 | 2018-08-10 15:03:23 -0700 | [diff] [blame] | 39 |         mDispSync(dispSync), | 
| Ady Abraham | 45e4e36 | 2019-06-07 18:20:51 -0700 | [diff] [blame] | 40 |         mPhaseOffset(phaseOffset), | 
 | 41 |         mOffsetThresholdForNextVsync(offsetThresholdForNextVsync) {} | 
| Ana Krulec | 241cf83 | 2018-08-10 15:03:23 -0700 | [diff] [blame] | 42 |  | 
 | 43 | void DispSyncSource::setVSyncEnabled(bool enable) { | 
| Ana Krulec | 072233f | 2018-08-10 15:03:23 -0700 | [diff] [blame] | 44 |     std::lock_guard lock(mVsyncMutex); | 
| Ana Krulec | 241cf83 | 2018-08-10 15:03:23 -0700 | [diff] [blame] | 45 |     if (enable) { | 
| Alec Mouri | d7599d8 | 2019-05-22 19:58:00 -0700 | [diff] [blame] | 46 |         tracePhaseOffset(); | 
| Ana Krulec | 241cf83 | 2018-08-10 15:03:23 -0700 | [diff] [blame] | 47 |         status_t err = mDispSync->addEventListener(mName, mPhaseOffset, | 
| Alec Mouri | 7355eb2 | 2019-03-05 14:19:10 -0800 | [diff] [blame] | 48 |                                                    static_cast<DispSync::Callback*>(this), | 
 | 49 |                                                    mLastCallbackTime); | 
| Ana Krulec | 241cf83 | 2018-08-10 15:03:23 -0700 | [diff] [blame] | 50 |         if (err != NO_ERROR) { | 
 | 51 |             ALOGE("error registering vsync callback: %s (%d)", strerror(-err), err); | 
 | 52 |         } | 
| Ana Krulec | 072233f | 2018-08-10 15:03:23 -0700 | [diff] [blame] | 53 |         // ATRACE_INT(mVsyncOnLabel.c_str(), 1); | 
| Ana Krulec | 241cf83 | 2018-08-10 15:03:23 -0700 | [diff] [blame] | 54 |     } else { | 
| Alec Mouri | 7355eb2 | 2019-03-05 14:19:10 -0800 | [diff] [blame] | 55 |         status_t err = mDispSync->removeEventListener(static_cast<DispSync::Callback*>(this), | 
 | 56 |                                                       &mLastCallbackTime); | 
| Ana Krulec | 241cf83 | 2018-08-10 15:03:23 -0700 | [diff] [blame] | 57 |         if (err != NO_ERROR) { | 
 | 58 |             ALOGE("error unregistering vsync callback: %s (%d)", strerror(-err), err); | 
 | 59 |         } | 
| Ana Krulec | 072233f | 2018-08-10 15:03:23 -0700 | [diff] [blame] | 60 |         // ATRACE_INT(mVsyncOnLabel.c_str(), 0); | 
| Ana Krulec | 241cf83 | 2018-08-10 15:03:23 -0700 | [diff] [blame] | 61 |     } | 
 | 62 |     mEnabled = enable; | 
 | 63 | } | 
 | 64 |  | 
 | 65 | void DispSyncSource::setCallback(VSyncSource::Callback* callback) { | 
| Ana Krulec | 072233f | 2018-08-10 15:03:23 -0700 | [diff] [blame] | 66 |     std::lock_guard lock(mCallbackMutex); | 
| Ana Krulec | 241cf83 | 2018-08-10 15:03:23 -0700 | [diff] [blame] | 67 |     mCallback = callback; | 
 | 68 | } | 
 | 69 |  | 
 | 70 | void DispSyncSource::setPhaseOffset(nsecs_t phaseOffset) { | 
| Ana Krulec | 072233f | 2018-08-10 15:03:23 -0700 | [diff] [blame] | 71 |     std::lock_guard lock(mVsyncMutex); | 
| Ady Abraham | 45e4e36 | 2019-06-07 18:20:51 -0700 | [diff] [blame] | 72 |     const nsecs_t period = mDispSync->getPeriod(); | 
 | 73 |     // Check if offset should be handled as negative | 
 | 74 |     if (phaseOffset >= mOffsetThresholdForNextVsync) { | 
 | 75 |         phaseOffset -= period; | 
| Ana Krulec | 241cf83 | 2018-08-10 15:03:23 -0700 | [diff] [blame] | 76 |     } | 
| Ady Abraham | 45e4e36 | 2019-06-07 18:20:51 -0700 | [diff] [blame] | 77 |  | 
 | 78 |     // Normalize phaseOffset to [-period, period) | 
 | 79 |     const int numPeriods = phaseOffset / period; | 
 | 80 |     phaseOffset -= numPeriods * period; | 
| Ady Abraham | 11b6a70 | 2019-06-27 11:24:19 -0700 | [diff] [blame] | 81 |     if (mPhaseOffset == phaseOffset) { | 
 | 82 |         return; | 
 | 83 |     } | 
 | 84 |  | 
| Ana Krulec | 241cf83 | 2018-08-10 15:03:23 -0700 | [diff] [blame] | 85 |     mPhaseOffset = phaseOffset; | 
| Alec Mouri | d7599d8 | 2019-05-22 19:58:00 -0700 | [diff] [blame] | 86 |     tracePhaseOffset(); | 
| Ana Krulec | 241cf83 | 2018-08-10 15:03:23 -0700 | [diff] [blame] | 87 |  | 
 | 88 |     // If we're not enabled, we don't need to mess with the listeners | 
 | 89 |     if (!mEnabled) { | 
 | 90 |         return; | 
 | 91 |     } | 
 | 92 |  | 
 | 93 |     status_t err = | 
 | 94 |             mDispSync->changePhaseOffset(static_cast<DispSync::Callback*>(this), mPhaseOffset); | 
 | 95 |     if (err != NO_ERROR) { | 
 | 96 |         ALOGE("error changing vsync offset: %s (%d)", strerror(-err), err); | 
 | 97 |     } | 
 | 98 | } | 
 | 99 |  | 
 | 100 | void DispSyncSource::onDispSyncEvent(nsecs_t when) { | 
 | 101 |     VSyncSource::Callback* callback; | 
 | 102 |     { | 
| Ana Krulec | 072233f | 2018-08-10 15:03:23 -0700 | [diff] [blame] | 103 |         std::lock_guard lock(mCallbackMutex); | 
| Ana Krulec | 241cf83 | 2018-08-10 15:03:23 -0700 | [diff] [blame] | 104 |         callback = mCallback; | 
| Alec Mouri | d7599d8 | 2019-05-22 19:58:00 -0700 | [diff] [blame] | 105 |     } | 
| Ana Krulec | 241cf83 | 2018-08-10 15:03:23 -0700 | [diff] [blame] | 106 |  | 
| Alec Mouri | d7599d8 | 2019-05-22 19:58:00 -0700 | [diff] [blame] | 107 |     if (mTraceVsync) { | 
 | 108 |         mValue = (mValue + 1) % 2; | 
 | 109 |         ATRACE_INT(mVsyncEventLabel.c_str(), mValue); | 
| Ana Krulec | 241cf83 | 2018-08-10 15:03:23 -0700 | [diff] [blame] | 110 |     } | 
 | 111 |  | 
 | 112 |     if (callback != nullptr) { | 
 | 113 |         callback->onVSyncEvent(when); | 
 | 114 |     } | 
 | 115 | } | 
 | 116 |  | 
| Alec Mouri | d7599d8 | 2019-05-22 19:58:00 -0700 | [diff] [blame] | 117 | void DispSyncSource::tracePhaseOffset() { | 
 | 118 |     if (mPhaseOffset > 0) { | 
 | 119 |         ATRACE_INT(mVsyncOffsetLabel.c_str(), mPhaseOffset); | 
 | 120 |         ATRACE_INT(mVsyncNegativeOffsetLabel.c_str(), 0); | 
 | 121 |     } else { | 
 | 122 |         ATRACE_INT(mVsyncOffsetLabel.c_str(), 0); | 
 | 123 |         ATRACE_INT(mVsyncNegativeOffsetLabel.c_str(), -mPhaseOffset); | 
 | 124 |     } | 
 | 125 | } | 
 | 126 |  | 
 | 127 | } // namespace android |