surfaceflinger: refactor FrambufferSurface
This change refactors the FramebufferSurface class to inherit from the new
ConsumerBase class.
Bug: 6620200
Change-Id: I46ec942ddb019658e3c5e79465548b171b2261f2
diff --git a/services/surfaceflinger/DisplayHardware/FramebufferSurface.cpp b/services/surfaceflinger/DisplayHardware/FramebufferSurface.cpp
index 7695e7f..f329136 100644
--- a/services/surfaceflinger/DisplayHardware/FramebufferSurface.cpp
+++ b/services/surfaceflinger/DisplayHardware/FramebufferSurface.cpp
@@ -1,6 +1,6 @@
/*
**
- ** Copyright 2007 The Android Open Source Project
+ ** Copyright 2012 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.
@@ -48,17 +48,33 @@
// ----------------------------------------------------------------------------
+class GraphicBufferAlloc : public BnGraphicBufferAlloc {
+public:
+ GraphicBufferAlloc() { };
+ virtual ~GraphicBufferAlloc() { };
+ virtual sp<GraphicBuffer> createGraphicBuffer(uint32_t w, uint32_t h,
+ PixelFormat format, uint32_t usage, status_t* error) {
+ sp<GraphicBuffer> graphicBuffer(new GraphicBuffer(w, h, format, usage));
+ return graphicBuffer;
+ }
+};
+
+
/*
* This implements the (main) framebuffer management. This class is used
* mostly by SurfaceFlinger, but also by command line GL application.
*
*/
-FramebufferSurface::FramebufferSurface()
- : SurfaceTextureClient(),
- fbDev(0), mCurrentBufferIndex(-1), mUpdateOnDemand(false)
+FramebufferSurface::FramebufferSurface():
+ ConsumerBase(new BufferQueue(true, NUM_FRAME_BUFFERS,
+ new GraphicBufferAlloc())),
+ fbDev(0),
+ mCurrentBufferSlot(-1),
+ mCurrentBuffer(0)
{
hw_module_t const* module;
+
if (hw_get_module(GRALLOC_HARDWARE_MODULE_ID, &module) == 0) {
int stride;
int err;
@@ -70,85 +86,64 @@
if (!fbDev)
return;
- mUpdateOnDemand = (fbDev->setUpdateRect != 0);
-
- const_cast<uint32_t&>(ANativeWindow::flags) = fbDev->flags;
- const_cast<int&>(ANativeWindow::minSwapInterval) = fbDev->minSwapInterval;
- const_cast<int&>(ANativeWindow::maxSwapInterval) = fbDev->maxSwapInterval;
-
- if (fbDev->xdpi == 0 || fbDev->ydpi == 0) {
- ALOGE("invalid screen resolution from fb HAL (xdpi=%f, ydpi=%f), "
- "defaulting to 160 dpi", fbDev->xdpi, fbDev->ydpi);
- const_cast<float&>(ANativeWindow::xdpi) = 160;
- const_cast<float&>(ANativeWindow::ydpi) = 160;
- } else {
- const_cast<float&>(ANativeWindow::xdpi) = fbDev->xdpi;
- const_cast<float&>(ANativeWindow::ydpi) = fbDev->ydpi;
- }
-
+ mName = "FramebufferSurface";
+ mBufferQueue->setConsumerName(mName);
+ mBufferQueue->setConsumerUsageBits(GRALLOC_USAGE_HW_FB |
+ GRALLOC_USAGE_HW_RENDER | GRALLOC_USAGE_HW_COMPOSER);
+ mBufferQueue->setDefaultBufferFormat(fbDev->format);
+ mBufferQueue->setDefaultBufferSize(fbDev->width, fbDev->height);
+ mBufferQueue->setSynchronousMode(true);
+ mBufferQueue->setBufferCountServer(NUM_FRAME_BUFFERS);
} else {
ALOGE("Couldn't get gralloc module");
}
-
- class GraphicBufferAlloc : public BnGraphicBufferAlloc {
- public:
- GraphicBufferAlloc() { };
- virtual ~GraphicBufferAlloc() { };
- virtual sp<GraphicBuffer> createGraphicBuffer(uint32_t w, uint32_t h,
- PixelFormat format, uint32_t usage, status_t* error) {
- sp<GraphicBuffer> graphicBuffer(new GraphicBuffer(w, h, format, usage));
- return graphicBuffer;
- }
- };
-
- mBufferQueue = new BufferQueue(true, NUM_FRAME_BUFFERS, new GraphicBufferAlloc());
- mBufferQueue->setConsumerUsageBits(GRALLOC_USAGE_HW_FB|GRALLOC_USAGE_HW_RENDER|GRALLOC_USAGE_HW_COMPOSER);
- mBufferQueue->setDefaultBufferFormat(fbDev->format);
- mBufferQueue->setDefaultBufferSize(fbDev->width, fbDev->height);
- mBufferQueue->setSynchronousMode(true);
- mBufferQueue->setBufferCountServer(NUM_FRAME_BUFFERS);
- setISurfaceTexture(mBufferQueue);
}
-void FramebufferSurface::onFirstRef() {
- class Listener : public BufferQueue::ConsumerListener {
- const wp<FramebufferSurface> that;
- virtual ~Listener() { }
- virtual void onBuffersReleased() { }
- void onFrameAvailable() {
- sp<FramebufferSurface> self = that.promote();
- if (self != NULL) {
- BufferQueue::BufferItem item;
- status_t err = self->mBufferQueue->acquireBuffer(&item);
- if (err == 0) {
- if (item.mGraphicBuffer != 0) {
- self->mBuffers[item.mBuf] = item.mGraphicBuffer;
- }
- if (item.mFence.get()) {
- err = item.mFence->wait(Fence::TIMEOUT_NEVER);
- if (err) {
- ALOGE("failed waiting for buffer's fence: %d", err);
- self->mBufferQueue->releaseBuffer(item.mBuf,
- EGL_NO_DISPLAY, EGL_NO_SYNC_KHR,
- item.mFence);
- return;
- }
- }
- self->fbDev->post(self->fbDev, self->mBuffers[item.mBuf]->handle);
- if (self->mCurrentBufferIndex >= 0) {
- self->mBufferQueue->releaseBuffer(self->mCurrentBufferIndex,
- EGL_NO_DISPLAY, EGL_NO_SYNC_KHR, Fence::NO_FENCE);
- }
- self->mCurrentBufferIndex = item.mBuf;
- }
- }
- }
- public:
- Listener(const sp<FramebufferSurface>& that) : that(that) { }
- };
+status_t FramebufferSurface::nextBuffer(sp<GraphicBuffer>* buffer) {
+ Mutex::Autolock lock(mMutex);
- mBufferQueue->setConsumerName(String8("FramebufferSurface"));
- mBufferQueue->consumerConnect(new Listener(this));
+ BufferQueue::BufferItem item;
+ status_t err = acquireBufferLocked(&item);
+ if (err == BufferQueue::NO_BUFFER_AVAILABLE) {
+ if (buffer != NULL) {
+ *buffer = mCurrentBuffer;
+ }
+ return NO_ERROR;
+ } else if (err != NO_ERROR) {
+ ALOGE("error acquiring buffer: %s (%d)", strerror(-err), err);
+ return err;
+ }
+
+ // If the BufferQueue has freed and reallocated a buffer in mCurrentSlot
+ // then we may have acquired the slot we already own. If we had released
+ // our current buffer before we call acquireBuffer then that release call
+ // would have returned STALE_BUFFER_SLOT, and we would have called
+ // freeBufferLocked on that slot. Because the buffer slot has already
+ // been overwritten with the new buffer all we have to do is skip the
+ // releaseBuffer call and we should be in the same state we'd be in if we
+ // had released the old buffer first.
+ if (mCurrentBufferSlot != BufferQueue::INVALID_BUFFER_SLOT &&
+ item.mBuf != mCurrentBufferSlot) {
+ // Release the previous buffer.
+ err = releaseBufferLocked(mCurrentBufferSlot, EGL_NO_DISPLAY,
+ EGL_NO_SYNC_KHR, Fence::NO_FENCE);
+ if (err != NO_ERROR && err != BufferQueue::STALE_BUFFER_SLOT) {
+ ALOGE("error releasing buffer: %s (%d)", strerror(-err), err);
+ return err;
+ }
+ }
+
+ mCurrentBufferSlot = item.mBuf;
+ mCurrentBuffer = mSlots[mCurrentBufferSlot].mGraphicBuffer;
+ if (item.mFence != NULL) {
+ item.mFence->wait(Fence::TIMEOUT_NEVER);
+ }
+
+ if (buffer != NULL) {
+ *buffer = mCurrentBuffer;
+ }
+
+ return NO_ERROR;
}
FramebufferSurface::~FramebufferSurface() {
@@ -157,6 +152,29 @@
}
}
+void FramebufferSurface::onFrameAvailable() {
+ // XXX: The following code is here temporarily as part of the transition
+ // away from the framebuffer HAL.
+ sp<GraphicBuffer> buf;
+ status_t err = nextBuffer(&buf);
+ if (err != NO_ERROR) {
+ ALOGE("error latching next FramebufferSurface buffer: %s (%d)",
+ strerror(-err), err);
+ return;
+ }
+ err = fbDev->post(fbDev, buf->handle);
+ if (err != NO_ERROR) {
+ ALOGE("error posting framebuffer: %d", err);
+ }
+}
+
+void FramebufferSurface::freeBufferLocked(int slotIndex) {
+ ConsumerBase::freeBufferLocked(slotIndex);
+ if (slotIndex == mCurrentBufferSlot) {
+ mCurrentBufferSlot = BufferQueue::INVALID_BUFFER_SLOT;
+ }
+}
+
float FramebufferSurface::getRefreshRate() const {
/* FIXME: REFRESH_RATE is a temporary HACK until we are able to report the
* refresh rate properly from the HAL. The WindowManagerService now relies
@@ -172,10 +190,7 @@
status_t FramebufferSurface::setUpdateRectangle(const Rect& r)
{
- if (!mUpdateOnDemand) {
- return INVALID_OPERATION;
- }
- return fbDev->setUpdateRect(fbDev, r.left, r.top, r.width(), r.height());
+ return INVALID_OPERATION;
}
status_t FramebufferSurface::compositionComplete()
@@ -190,38 +205,10 @@
if (fbDev->common.version >= 1 && fbDev->dump) {
const size_t SIZE = 4096;
char buffer[SIZE];
-
fbDev->dump(fbDev, buffer, SIZE);
result.append(buffer);
}
-}
-
-int FramebufferSurface::query(int what, int* value) const {
- Mutex::Autolock _l(mLock);
- framebuffer_device_t* fb = fbDev;
- switch (what) {
- case NATIVE_WINDOW_DEFAULT_WIDTH:
- case NATIVE_WINDOW_WIDTH:
- *value = fb->width;
- return NO_ERROR;
- case NATIVE_WINDOW_DEFAULT_HEIGHT:
- case NATIVE_WINDOW_HEIGHT:
- *value = fb->height;
- return NO_ERROR;
- case NATIVE_WINDOW_FORMAT:
- *value = fb->format;
- return NO_ERROR;
- case NATIVE_WINDOW_CONCRETE_TYPE:
- *value = NATIVE_WINDOW_FRAMEBUFFER;
- return NO_ERROR;
- case NATIVE_WINDOW_QUEUES_TO_WINDOW_COMPOSER:
- *value = 0;
- return NO_ERROR;
- case NATIVE_WINDOW_TRANSFORM_HINT:
- *value = 0;
- return NO_ERROR;
- }
- return SurfaceTextureClient::query(what, value);
+ ConsumerBase::dump(result);
}
// ----------------------------------------------------------------------------
diff --git a/services/surfaceflinger/DisplayHardware/FramebufferSurface.h b/services/surfaceflinger/DisplayHardware/FramebufferSurface.h
index 672bfbb..95feaa0 100644
--- a/services/surfaceflinger/DisplayHardware/FramebufferSurface.h
+++ b/services/surfaceflinger/DisplayHardware/FramebufferSurface.h
@@ -20,9 +20,7 @@
#include <stdint.h>
#include <sys/types.h>
-#include <EGL/egl.h>
-
-#include <gui/SurfaceTextureClient.h>
+#include <gui/ConsumerBase.h>
#define NUM_FRAME_BUFFERS 2
@@ -35,7 +33,7 @@
// ---------------------------------------------------------------------------
-class FramebufferSurface : public SurfaceTextureClient {
+class FramebufferSurface : public ConsumerBase {
public:
static sp<FramebufferSurface> create();
@@ -43,28 +41,34 @@
// TODO: this should be coming from HWC
float getRefreshRate() const;
- bool isUpdateOnDemand() const { return mUpdateOnDemand; }
+ bool isUpdateOnDemand() const { return false; }
status_t setUpdateRectangle(const Rect& updateRect);
status_t compositionComplete();
- void dump(String8& result);
+ virtual void dump(String8& result);
-protected:
- virtual void onFirstRef();
+ // nextBuffer waits for and then latches the next buffer from the
+ // BufferQueue and releases the previously latched buffer to the
+ // BufferQueue. The new buffer is returned in the 'buffer' argument.
+ status_t nextBuffer(sp<GraphicBuffer>* buffer);
private:
FramebufferSurface();
virtual ~FramebufferSurface(); // this class cannot be overloaded
- virtual int query(int what, int* value) const;
+
+ virtual void onFrameAvailable();
+ virtual void freeBufferLocked(int slotIndex);
framebuffer_device_t* fbDev;
- sp<BufferQueue> mBufferQueue;
- int mCurrentBufferIndex;
- sp<GraphicBuffer> mBuffers[NUM_FRAME_BUFFERS];
+ // mCurrentBufferIndex is the slot index of the current buffer or
+ // INVALID_BUFFER_SLOT to indicate that either there is no current buffer
+ // or the buffer is not associated with a slot.
+ int mCurrentBufferSlot;
- mutable Mutex mLock;
- bool mUpdateOnDemand;
+ // mCurrentBuffer is the current buffer or NULL to indicate that there is
+ // no current buffer.
+ sp<GraphicBuffer> mCurrentBuffer;
};
// ---------------------------------------------------------------------------
diff --git a/services/surfaceflinger/DisplayHardware/HWComposer.h b/services/surfaceflinger/DisplayHardware/HWComposer.h
index b9c9337..607cbae 100644
--- a/services/surfaceflinger/DisplayHardware/HWComposer.h
+++ b/services/surfaceflinger/DisplayHardware/HWComposer.h
@@ -42,6 +42,7 @@
class GraphicBuffer;
class LayerBase;
+class Region;
class String8;
class SurfaceFlinger;