1 /* 2 * Copyright (C) 2012 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 17 #define ATRACE_TAG ATRACE_TAG_GRAPHICS 18 //#define LOG_NDEBUG 0 19 20 #include "SurfaceFlingerConsumer.h" 21 #include "Layer.h" 22 23 #include <private/gui/SyncFeatures.h> 24 25 #include <gui/BufferItem.h> 26 27 #include <utils/Errors.h> 28 #include <utils/NativeHandle.h> 29 #include <utils/Trace.h> 30 31 namespace android { 32 33 // --------------------------------------------------------------------------- 34 35 status_t SurfaceFlingerConsumer::updateTexImage(BufferRejecter* rejecter, 36 const DispSync& dispSync, bool* autoRefresh, bool* queuedBuffer, 37 uint64_t maxFrameNumber) 38 { 39 ATRACE_CALL(); 40 ALOGV("updateTexImage"); 41 Mutex::Autolock lock(mMutex); 42 43 if (mAbandoned) { 44 ALOGE("updateTexImage: GLConsumer is abandoned!"); 45 return NO_INIT; 46 } 47 48 // Make sure the EGL state is the same as in previous calls. 49 status_t err = checkAndUpdateEglStateLocked(); 50 if (err != NO_ERROR) { 51 return err; 52 } 53 54 BufferItem item; 55 56 // Acquire the next buffer. 57 // In asynchronous mode the list is guaranteed to be one buffer 58 // deep, while in synchronous mode we use the oldest buffer. 59 err = acquireBufferLocked(&item, computeExpectedPresent(dispSync), 60 maxFrameNumber); 61 if (err != NO_ERROR) { 62 if (err == BufferQueue::NO_BUFFER_AVAILABLE) { 63 err = NO_ERROR; 64 } else if (err == BufferQueue::PRESENT_LATER) { 65 // return the error, without logging 66 } else { 67 ALOGE("updateTexImage: acquire failed: %s (%d)", 68 strerror(-err), err); 69 } 70 return err; 71 } 72 73 // We call the rejecter here, in case the caller has a reason to 74 // not accept this buffer. This is used by SurfaceFlinger to 75 // reject buffers which have the wrong size 76 int slot = item.mSlot; 77 if (rejecter && rejecter->reject(mSlots[slot].mGraphicBuffer, item)) { 78 releaseBufferLocked(slot, mSlots[slot].mGraphicBuffer, EGL_NO_SYNC_KHR); 79 return BUFFER_REJECTED; 80 } 81 82 if (autoRefresh) { 83 *autoRefresh = item.mAutoRefresh; 84 } 85 86 if (queuedBuffer) { 87 *queuedBuffer = item.mQueuedBuffer; 88 } 89 90 // Release the previous buffer. 91 #ifdef USE_HWC2 92 err = updateAndReleaseLocked(item, &mPendingRelease); 93 #else 94 err = updateAndReleaseLocked(item); 95 #endif 96 if (err != NO_ERROR) { 97 return err; 98 } 99 100 if (!SyncFeatures::getInstance().useNativeFenceSync()) { 101 // Bind the new buffer to the GL texture. 102 // 103 // Older devices require the "implicit" synchronization provided 104 // by glEGLImageTargetTexture2DOES, which this method calls. Newer 105 // devices will either call this in Layer::onDraw, or (if it's not 106 // a GL-composited layer) not at all. 107 err = bindTextureImageLocked(); 108 } 109 110 return err; 111 } 112 113 status_t SurfaceFlingerConsumer::bindTextureImage() 114 { 115 Mutex::Autolock lock(mMutex); 116 117 return bindTextureImageLocked(); 118 } 119 120 status_t SurfaceFlingerConsumer::acquireBufferLocked(BufferItem* item, 121 nsecs_t presentWhen, uint64_t maxFrameNumber) { 122 status_t result = GLConsumer::acquireBufferLocked(item, presentWhen, 123 maxFrameNumber); 124 if (result == NO_ERROR) { 125 mTransformToDisplayInverse = item->mTransformToDisplayInverse; 126 mSurfaceDamage = item->mSurfaceDamage; 127 } 128 return result; 129 } 130 131 bool SurfaceFlingerConsumer::getTransformToDisplayInverse() const { 132 Mutex::Autolock lock(mMutex); 133 return mTransformToDisplayInverse; 134 } 135 136 const Region& SurfaceFlingerConsumer::getSurfaceDamage() const { 137 return mSurfaceDamage; 138 } 139 140 sp<NativeHandle> SurfaceFlingerConsumer::getSidebandStream() const { 141 return mConsumer->getSidebandStream(); 142 } 143 144 // We need to determine the time when a buffer acquired now will be 145 // displayed. This can be calculated: 146 // time when previous buffer's actual-present fence was signaled 147 // + current display refresh rate * HWC latency 148 // + a little extra padding 149 // 150 // Buffer producers are expected to set their desired presentation time 151 // based on choreographer time stamps, which (coming from vsync events) 152 // will be slightly later then the actual-present timing. If we get a 153 // desired-present time that is unintentionally a hair after the next 154 // vsync, we'll hold the frame when we really want to display it. We 155 // need to take the offset between actual-present and reported-vsync 156 // into account. 157 // 158 // If the system is configured without a DispSync phase offset for the app, 159 // we also want to throw in a bit of padding to avoid edge cases where we 160 // just barely miss. We want to do it here, not in every app. A major 161 // source of trouble is the app's use of the display's ideal refresh time 162 // (via Display.getRefreshRate()), which could be off of the actual refresh 163 // by a few percent, with the error multiplied by the number of frames 164 // between now and when the buffer should be displayed. 165 // 166 // If the refresh reported to the app has a phase offset, we shouldn't need 167 // to tweak anything here. 168 nsecs_t SurfaceFlingerConsumer::computeExpectedPresent(const DispSync& dispSync) 169 { 170 // The HWC doesn't currently have a way to report additional latency. 171 // Assume that whatever we submit now will appear right after the flip. 172 // For a smart panel this might be 1. This is expressed in frames, 173 // rather than time, because we expect to have a constant frame delay 174 // regardless of the refresh rate. 175 const uint32_t hwcLatency = 0; 176 177 // Ask DispSync when the next refresh will be (CLOCK_MONOTONIC). 178 const nsecs_t nextRefresh = dispSync.computeNextRefresh(hwcLatency); 179 180 // The DispSync time is already adjusted for the difference between 181 // vsync and reported-vsync (PRESENT_TIME_OFFSET_FROM_VSYNC_NS), so 182 // we don't need to factor that in here. Pad a little to avoid 183 // weird effects if apps might be requesting times right on the edge. 184 nsecs_t extraPadding = 0; 185 if (VSYNC_EVENT_PHASE_OFFSET_NS == 0) { 186 extraPadding = 1000000; // 1ms (6% of 60Hz) 187 } 188 189 return nextRefresh + extraPadding; 190 } 191 192 #ifdef USE_HWC2 193 void SurfaceFlingerConsumer::setReleaseFence(const sp<Fence>& fence) 194 { 195 mPrevReleaseFence = fence; 196 if (!mPendingRelease.isPending) { 197 GLConsumer::setReleaseFence(fence); 198 return; 199 } 200 auto currentTexture = mPendingRelease.currentTexture; 201 if (fence->isValid() && 202 currentTexture != BufferQueue::INVALID_BUFFER_SLOT) { 203 status_t result = addReleaseFence(currentTexture, 204 mPendingRelease.graphicBuffer, fence); 205 ALOGE_IF(result != NO_ERROR, "setReleaseFence: failed to add the" 206 " fence: %s (%d)", strerror(-result), result); 207 } 208 } 209 210 void SurfaceFlingerConsumer::releasePendingBuffer() 211 { 212 if (!mPendingRelease.isPending) { 213 ALOGV("Pending buffer already released"); 214 return; 215 } 216 ALOGV("Releasing pending buffer"); 217 Mutex::Autolock lock(mMutex); 218 status_t result = releaseBufferLocked(mPendingRelease.currentTexture, 219 mPendingRelease.graphicBuffer, mPendingRelease.display, 220 mPendingRelease.fence); 221 ALOGE_IF(result != NO_ERROR, "releasePendingBuffer failed: %s (%d)", 222 strerror(-result), result); 223 mPendingRelease = PendingRelease(); 224 } 225 #else 226 void SurfaceFlingerConsumer::setReleaseFence(const sp<Fence>& fence) { 227 mPrevReleaseFence = fence; 228 GLConsumer::setReleaseFence(fence); 229 } 230 #endif 231 232 sp<Fence> SurfaceFlingerConsumer::getPrevReleaseFence() const { 233 return mPrevReleaseFence; 234 } 235 236 void SurfaceFlingerConsumer::setContentsChangedListener( 237 const wp<ContentsChangedListener>& listener) { 238 setFrameAvailableListener(listener); 239 Mutex::Autolock lock(mMutex); 240 mContentsChangedListener = listener; 241 } 242 243 void SurfaceFlingerConsumer::onSidebandStreamChanged() { 244 sp<ContentsChangedListener> listener; 245 { // scope for the lock 246 Mutex::Autolock lock(mMutex); 247 ALOG_ASSERT(mFrameAvailableListener.unsafe_get() == mContentsChangedListener.unsafe_get()); 248 listener = mContentsChangedListener.promote(); 249 } 250 251 if (listener != NULL) { 252 listener->onSidebandStreamChanged(); 253 } 254 } 255 256 bool SurfaceFlingerConsumer::getFrameTimestamps(uint64_t frameNumber, 257 FrameTimestamps* outTimestamps) const { 258 sp<const Layer> l = mLayer.promote(); 259 return l.get() ? l->getFrameTimestamps(frameNumber, outTimestamps) : false; 260 } 261 262 // --------------------------------------------------------------------------- 263 }; // namespace android 264 265