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