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