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 
30 namespace android {
31 
32 // ---------------------------------------------------------------------------
33 
updateTexImage(BufferRejecter * rejecter,const DispSync & dispSync,bool * autoRefresh,bool * queuedBuffer,uint64_t maxFrameNumber)34 status_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 
bindTextureImage()112 status_t SurfaceFlingerConsumer::bindTextureImage()
113 {
114     Mutex::Autolock lock(mMutex);
115 
116     return bindTextureImageLocked();
117 }
118 
acquireBufferLocked(BufferItem * item,nsecs_t presentWhen,uint64_t maxFrameNumber)119 status_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 
getTransformToDisplayInverse() const130 bool SurfaceFlingerConsumer::getTransformToDisplayInverse() const {
131     return mTransformToDisplayInverse;
132 }
133 
getSurfaceDamage() const134 const Region& SurfaceFlingerConsumer::getSurfaceDamage() const {
135     return mSurfaceDamage;
136 }
137 
getSidebandStream() const138 sp<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.
computeExpectedPresent(const DispSync & dispSync)166 nsecs_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
setReleaseFence(const sp<Fence> & fence)191 void 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 
releasePendingBuffer()208 void 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
setReleaseFence(const sp<Fence> & fence)224 void SurfaceFlingerConsumer::setReleaseFence(const sp<Fence>& fence) {
225     mPrevReleaseFence = fence;
226     GLConsumer::setReleaseFence(fence);
227 }
228 #endif
229 
getPrevReleaseFence() const230 sp<Fence> SurfaceFlingerConsumer::getPrevReleaseFence() const {
231     return mPrevReleaseFence;
232 }
233 
setContentsChangedListener(const wp<ContentsChangedListener> & listener)234 void SurfaceFlingerConsumer::setContentsChangedListener(
235         const wp<ContentsChangedListener>& listener) {
236     setFrameAvailableListener(listener);
237     Mutex::Autolock lock(mMutex);
238     mContentsChangedListener = listener;
239 }
240 
onSidebandStreamChanged()241 void 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