surfaceflinger: refactor FrambufferSurface
This change refactors the FramebufferSurface class to inherit from the new
ConsumerBase class.
Bug: 6620200
Change-Id: I46ec942ddb019658e3c5e79465548b171b2261f2
diff --git a/libs/gui/ConsumerBase.cpp b/libs/gui/ConsumerBase.cpp
new file mode 100644
index 0000000..af19ac0
--- /dev/null
+++ b/libs/gui/ConsumerBase.cpp
@@ -0,0 +1,205 @@
+/*
+ * Copyright (C) 2010 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "ConsumerBase"
+#define ATRACE_TAG ATRACE_TAG_GRAPHICS
+//#define LOG_NDEBUG 0
+
+#define GL_GLEXT_PROTOTYPES
+#define EGL_EGLEXT_PROTOTYPES
+
+#include <EGL/egl.h>
+#include <EGL/eglext.h>
+
+#include <hardware/hardware.h>
+
+#include <gui/IGraphicBufferAlloc.h>
+#include <gui/ISurfaceComposer.h>
+#include <gui/SurfaceComposerClient.h>
+#include <gui/ConsumerBase.h>
+
+#include <private/gui/ComposerService.h>
+
+#include <utils/Log.h>
+#include <utils/String8.h>
+#include <utils/Trace.h>
+
+// Macros for including the ConsumerBase name in log messages
+#define CB_LOGV(x, ...) ALOGV("[%s] "x, mName.string(), ##__VA_ARGS__)
+#define CB_LOGD(x, ...) ALOGD("[%s] "x, mName.string(), ##__VA_ARGS__)
+#define CB_LOGI(x, ...) ALOGI("[%s] "x, mName.string(), ##__VA_ARGS__)
+#define CB_LOGW(x, ...) ALOGW("[%s] "x, mName.string(), ##__VA_ARGS__)
+#define CB_LOGE(x, ...) ALOGE("[%s] "x, mName.string(), ##__VA_ARGS__)
+
+namespace android {
+
+// Get an ID that's unique within this process.
+static int32_t createProcessUniqueId() {
+ static volatile int32_t globalCounter = 0;
+ return android_atomic_inc(&globalCounter);
+}
+
+ConsumerBase::ConsumerBase(const sp<BufferQueue>& bufferQueue) :
+ mBufferQueue(bufferQueue) {
+ // Choose a name using the PID and a process-unique ID.
+ mName = String8::format("unnamed-%d-%d", getpid(), createProcessUniqueId());
+
+ // Note that we can't create an sp<...>(this) in a ctor that will not keep a
+ // reference once the ctor ends, as that would cause the refcount of 'this'
+ // dropping to 0 at the end of the ctor. Since all we need is a wp<...>
+ // that's what we create.
+ wp<BufferQueue::ConsumerListener> listener;
+ sp<BufferQueue::ConsumerListener> proxy;
+ listener = static_cast<BufferQueue::ConsumerListener*>(this);
+ proxy = new BufferQueue::ProxyConsumerListener(listener);
+
+ status_t err = mBufferQueue->consumerConnect(proxy);
+ if (err != NO_ERROR) {
+ CB_LOGE("SurfaceTexture: error connecting to BufferQueue: %s (%d)",
+ strerror(-err), err);
+ } else {
+ mBufferQueue->setConsumerName(mName);
+ }
+}
+
+ConsumerBase::~ConsumerBase() {
+ CB_LOGV("~ConsumerBase");
+ abandon();
+}
+
+void ConsumerBase::freeBufferLocked(int slotIndex) {
+ CB_LOGV("freeBufferLocked: slotIndex=%d", slotIndex);
+ mSlots[slotIndex].mGraphicBuffer = 0;
+ mSlots[slotIndex].mFence = 0;
+}
+
+// Used for refactoring, should not be in final interface
+sp<BufferQueue> ConsumerBase::getBufferQueue() const {
+ Mutex::Autolock lock(mMutex);
+ return mBufferQueue;
+}
+
+void ConsumerBase::onFrameAvailable() {
+ CB_LOGV("onFrameAvailable");
+
+ sp<FrameAvailableListener> listener;
+ { // scope for the lock
+ Mutex::Autolock lock(mMutex);
+ listener = mFrameAvailableListener;
+ }
+
+ if (listener != NULL) {
+ CB_LOGV("actually calling onFrameAvailable");
+ listener->onFrameAvailable();
+ }
+}
+
+void ConsumerBase::onBuffersReleased() {
+ Mutex::Autolock lock(mMutex);
+
+ CB_LOGV("onBuffersReleased");
+
+ if (mAbandoned) {
+ // Nothing to do if we're already abandoned.
+ return;
+ }
+
+ uint32_t mask = 0;
+ mBufferQueue->getReleasedBuffers(&mask);
+ for (int i = 0; i < BufferQueue::NUM_BUFFER_SLOTS; i++) {
+ if (mask & (1 << i)) {
+ freeBufferLocked(i);
+ }
+ }
+}
+
+void ConsumerBase::abandon() {
+ CB_LOGV("abandon");
+ Mutex::Autolock lock(mMutex);
+
+ if (!mAbandoned) {
+ abandonLocked();
+ mAbandoned = true;
+ }
+}
+
+void ConsumerBase::abandonLocked() {
+ CB_LOGV("abandonLocked");
+ for (int i =0; i < BufferQueue::NUM_BUFFER_SLOTS; i++) {
+ freeBufferLocked(i);
+ }
+ // disconnect from the BufferQueue
+ mBufferQueue->consumerDisconnect();
+ mBufferQueue.clear();
+}
+
+void ConsumerBase::setFrameAvailableListener(
+ const sp<FrameAvailableListener>& listener) {
+ CB_LOGV("setFrameAvailableListener");
+ Mutex::Autolock lock(mMutex);
+ mFrameAvailableListener = listener;
+}
+
+void ConsumerBase::dump(String8& result) const {
+ char buffer[1024];
+ dump(result, "", buffer, 1024);
+}
+
+void ConsumerBase::dump(String8& result, const char* prefix,
+ char* buffer, size_t size) const {
+ Mutex::Autolock _l(mMutex);
+ dumpLocked(result, prefix, buffer, size);
+}
+
+void ConsumerBase::dumpLocked(String8& result, const char* prefix,
+ char* buffer, size_t SIZE) const {
+ snprintf(buffer, SIZE, "%smAbandoned=%d\n", prefix, int(mAbandoned));
+ result.append(buffer);
+
+ if (!mAbandoned) {
+ mBufferQueue->dump(result, prefix, buffer, SIZE);
+ }
+}
+
+status_t ConsumerBase::acquireBufferLocked(BufferQueue::BufferItem *item) {
+ status_t err = mBufferQueue->acquireBuffer(item);
+ if (err != NO_ERROR) {
+ return err;
+ }
+
+ if (item->mGraphicBuffer != NULL) {
+ mSlots[item->mBuf].mGraphicBuffer = item->mGraphicBuffer;
+ }
+
+ CB_LOGV("acquireBufferLocked: -> slot=%d", item->mBuf);
+
+ return OK;
+}
+
+status_t ConsumerBase::releaseBufferLocked(int slot, EGLDisplay display,
+ EGLSyncKHR eglFence, const sp<Fence>& fence) {
+ CB_LOGV("releaseBufferLocked: slot=%d", slot);
+ status_t err = mBufferQueue->releaseBuffer(slot, display, eglFence, fence);
+ if (err == BufferQueue::STALE_BUFFER_SLOT) {
+ freeBufferLocked(slot);
+ }
+
+ mSlots[slot].mFence.clear();
+
+ return err;
+}
+
+} // namespace android
\ No newline at end of file