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