• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1  /*
2   * Copyright (C) 2010 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 LOG_TAG "ConsumerBase"
18  #define ATRACE_TAG ATRACE_TAG_GRAPHICS
19  //#define LOG_NDEBUG 0
20  
21  #define EGL_EGLEXT_PROTOTYPES
22  
23  #include <EGL/egl.h>
24  #include <EGL/eglext.h>
25  
26  #include <hardware/hardware.h>
27  
28  #include <gui/IGraphicBufferAlloc.h>
29  #include <gui/ISurfaceComposer.h>
30  #include <gui/SurfaceComposerClient.h>
31  #include <gui/ConsumerBase.h>
32  
33  #include <private/gui/ComposerService.h>
34  
35  #include <utils/Log.h>
36  #include <utils/String8.h>
37  #include <utils/Trace.h>
38  
39  // Macros for including the ConsumerBase name in log messages
40  #define CB_LOGV(x, ...) ALOGV("[%s] "x, mName.string(), ##__VA_ARGS__)
41  #define CB_LOGD(x, ...) ALOGD("[%s] "x, mName.string(), ##__VA_ARGS__)
42  #define CB_LOGI(x, ...) ALOGI("[%s] "x, mName.string(), ##__VA_ARGS__)
43  #define CB_LOGW(x, ...) ALOGW("[%s] "x, mName.string(), ##__VA_ARGS__)
44  #define CB_LOGE(x, ...) ALOGE("[%s] "x, mName.string(), ##__VA_ARGS__)
45  
46  namespace android {
47  
48  // Get an ID that's unique within this process.
createProcessUniqueId()49  static int32_t createProcessUniqueId() {
50      static volatile int32_t globalCounter = 0;
51      return android_atomic_inc(&globalCounter);
52  }
53  
ConsumerBase(const sp<IGraphicBufferConsumer> & bufferQueue,bool controlledByApp)54  ConsumerBase::ConsumerBase(const sp<IGraphicBufferConsumer>& bufferQueue, bool controlledByApp) :
55          mAbandoned(false),
56          mConsumer(bufferQueue) {
57      // Choose a name using the PID and a process-unique ID.
58      mName = String8::format("unnamed-%d-%d", getpid(), createProcessUniqueId());
59  
60      // Note that we can't create an sp<...>(this) in a ctor that will not keep a
61      // reference once the ctor ends, as that would cause the refcount of 'this'
62      // dropping to 0 at the end of the ctor.  Since all we need is a wp<...>
63      // that's what we create.
64      wp<ConsumerListener> listener = static_cast<ConsumerListener*>(this);
65      sp<IConsumerListener> proxy = new BufferQueue::ProxyConsumerListener(listener);
66  
67      status_t err = mConsumer->consumerConnect(proxy, controlledByApp);
68      if (err != NO_ERROR) {
69          CB_LOGE("ConsumerBase: error connecting to BufferQueue: %s (%d)",
70                  strerror(-err), err);
71      } else {
72          mConsumer->setConsumerName(mName);
73      }
74  }
75  
~ConsumerBase()76  ConsumerBase::~ConsumerBase() {
77      CB_LOGV("~ConsumerBase");
78      Mutex::Autolock lock(mMutex);
79  
80      // Verify that abandon() has been called before we get here.  This should
81      // be done by ConsumerBase::onLastStrongRef(), but it's possible for a
82      // derived class to override that method and not call
83      // ConsumerBase::onLastStrongRef().
84      LOG_ALWAYS_FATAL_IF(!mAbandoned, "[%s] ~ConsumerBase was called, but the "
85          "consumer is not abandoned!", mName.string());
86  }
87  
onLastStrongRef(const void * id)88  void ConsumerBase::onLastStrongRef(const void* id) {
89      abandon();
90  }
91  
freeBufferLocked(int slotIndex)92  void ConsumerBase::freeBufferLocked(int slotIndex) {
93      CB_LOGV("freeBufferLocked: slotIndex=%d", slotIndex);
94      mSlots[slotIndex].mGraphicBuffer = 0;
95      mSlots[slotIndex].mFence = Fence::NO_FENCE;
96      mSlots[slotIndex].mFrameNumber = 0;
97  }
98  
onFrameAvailable()99  void ConsumerBase::onFrameAvailable() {
100      CB_LOGV("onFrameAvailable");
101  
102      sp<FrameAvailableListener> listener;
103      { // scope for the lock
104          Mutex::Autolock lock(mMutex);
105          listener = mFrameAvailableListener.promote();
106      }
107  
108      if (listener != NULL) {
109          CB_LOGV("actually calling onFrameAvailable");
110          listener->onFrameAvailable();
111      }
112  }
113  
onBuffersReleased()114  void ConsumerBase::onBuffersReleased() {
115      Mutex::Autolock lock(mMutex);
116  
117      CB_LOGV("onBuffersReleased");
118  
119      if (mAbandoned) {
120          // Nothing to do if we're already abandoned.
121          return;
122      }
123  
124      uint32_t mask = 0;
125      mConsumer->getReleasedBuffers(&mask);
126      for (int i = 0; i < BufferQueue::NUM_BUFFER_SLOTS; i++) {
127          if (mask & (1 << i)) {
128              freeBufferLocked(i);
129          }
130      }
131  }
132  
abandon()133  void ConsumerBase::abandon() {
134      CB_LOGV("abandon");
135      Mutex::Autolock lock(mMutex);
136  
137      if (!mAbandoned) {
138          abandonLocked();
139          mAbandoned = true;
140      }
141  }
142  
abandonLocked()143  void ConsumerBase::abandonLocked() {
144  	CB_LOGV("abandonLocked");
145      for (int i =0; i < BufferQueue::NUM_BUFFER_SLOTS; i++) {
146          freeBufferLocked(i);
147      }
148      // disconnect from the BufferQueue
149      mConsumer->consumerDisconnect();
150      mConsumer.clear();
151  }
152  
setFrameAvailableListener(const wp<FrameAvailableListener> & listener)153  void ConsumerBase::setFrameAvailableListener(
154          const wp<FrameAvailableListener>& listener) {
155      CB_LOGV("setFrameAvailableListener");
156      Mutex::Autolock lock(mMutex);
157      mFrameAvailableListener = listener;
158  }
159  
dump(String8 & result) const160  void ConsumerBase::dump(String8& result) const {
161      dump(result, "");
162  }
163  
dump(String8 & result,const char * prefix) const164  void ConsumerBase::dump(String8& result, const char* prefix) const {
165      Mutex::Autolock _l(mMutex);
166      dumpLocked(result, prefix);
167  }
168  
dumpLocked(String8 & result,const char * prefix) const169  void ConsumerBase::dumpLocked(String8& result, const char* prefix) const {
170      result.appendFormat("%smAbandoned=%d\n", prefix, int(mAbandoned));
171  
172      if (!mAbandoned) {
173          mConsumer->dump(result, prefix);
174      }
175  }
176  
acquireBufferLocked(BufferQueue::BufferItem * item,nsecs_t presentWhen)177  status_t ConsumerBase::acquireBufferLocked(BufferQueue::BufferItem *item,
178          nsecs_t presentWhen) {
179      status_t err = mConsumer->acquireBuffer(item, presentWhen);
180      if (err != NO_ERROR) {
181          return err;
182      }
183  
184      if (item->mGraphicBuffer != NULL) {
185          mSlots[item->mBuf].mGraphicBuffer = item->mGraphicBuffer;
186      }
187  
188      mSlots[item->mBuf].mFrameNumber = item->mFrameNumber;
189      mSlots[item->mBuf].mFence = item->mFence;
190  
191      CB_LOGV("acquireBufferLocked: -> slot=%d/%llu",
192              item->mBuf, item->mFrameNumber);
193  
194      return OK;
195  }
196  
addReleaseFence(int slot,const sp<GraphicBuffer> graphicBuffer,const sp<Fence> & fence)197  status_t ConsumerBase::addReleaseFence(int slot,
198          const sp<GraphicBuffer> graphicBuffer, const sp<Fence>& fence) {
199      Mutex::Autolock lock(mMutex);
200      return addReleaseFenceLocked(slot, graphicBuffer, fence);
201  }
202  
addReleaseFenceLocked(int slot,const sp<GraphicBuffer> graphicBuffer,const sp<Fence> & fence)203  status_t ConsumerBase::addReleaseFenceLocked(int slot,
204          const sp<GraphicBuffer> graphicBuffer, const sp<Fence>& fence) {
205      CB_LOGV("addReleaseFenceLocked: slot=%d", slot);
206  
207      // If consumer no longer tracks this graphicBuffer, we can safely
208      // drop this fence, as it will never be received by the producer.
209      if (!stillTracking(slot, graphicBuffer)) {
210          return OK;
211      }
212  
213      if (!mSlots[slot].mFence.get()) {
214          mSlots[slot].mFence = fence;
215      } else {
216          sp<Fence> mergedFence = Fence::merge(
217                  String8::format("%.28s:%d", mName.string(), slot),
218                  mSlots[slot].mFence, fence);
219          if (!mergedFence.get()) {
220              CB_LOGE("failed to merge release fences");
221              // synchronization is broken, the best we can do is hope fences
222              // signal in order so the new fence will act like a union
223              mSlots[slot].mFence = fence;
224              return BAD_VALUE;
225          }
226          mSlots[slot].mFence = mergedFence;
227      }
228  
229      return OK;
230  }
231  
releaseBufferLocked(int slot,const sp<GraphicBuffer> graphicBuffer,EGLDisplay display,EGLSyncKHR eglFence)232  status_t ConsumerBase::releaseBufferLocked(
233          int slot, const sp<GraphicBuffer> graphicBuffer,
234          EGLDisplay display, EGLSyncKHR eglFence) {
235      // If consumer no longer tracks this graphicBuffer (we received a new
236      // buffer on the same slot), the buffer producer is definitely no longer
237      // tracking it.
238      if (!stillTracking(slot, graphicBuffer)) {
239          return OK;
240      }
241  
242      CB_LOGV("releaseBufferLocked: slot=%d/%llu",
243              slot, mSlots[slot].mFrameNumber);
244      status_t err = mConsumer->releaseBuffer(slot, mSlots[slot].mFrameNumber,
245              display, eglFence, mSlots[slot].mFence);
246      if (err == BufferQueue::STALE_BUFFER_SLOT) {
247          freeBufferLocked(slot);
248      }
249  
250      mSlots[slot].mFence = Fence::NO_FENCE;
251  
252      return err;
253  }
254  
stillTracking(int slot,const sp<GraphicBuffer> graphicBuffer)255  bool ConsumerBase::stillTracking(int slot,
256          const sp<GraphicBuffer> graphicBuffer) {
257      if (slot < 0 || slot >= BufferQueue::NUM_BUFFER_SLOTS) {
258          return false;
259      }
260      return (mSlots[slot].mGraphicBuffer != NULL &&
261              mSlots[slot].mGraphicBuffer->handle == graphicBuffer->handle);
262  }
263  
264  } // namespace android
265