summaryrefslogtreecommitdiffstats
path: root/libs/surfaceflinger
diff options
context:
space:
mode:
authorMathias Agopian <mathias@google.com>2009-09-07 16:32:45 -0700
committerMathias Agopian <mathias@google.com>2009-09-07 16:32:45 -0700
commitcbb288bfe89f585bf48371bd31b2d4aafa32f32e (patch)
tree73d20f36910dcab8c17c686cdd7014cee285bc39 /libs/surfaceflinger
parentf0780974fc31ae88135d1dcb67cb5fd86bb6deb6 (diff)
downloadframeworks_native-cbb288bfe89f585bf48371bd31b2d4aafa32f32e.zip
frameworks_native-cbb288bfe89f585bf48371bd31b2d4aafa32f32e.tar.gz
frameworks_native-cbb288bfe89f585bf48371bd31b2d4aafa32f32e.tar.bz2
fix [2068105] implement queueBuffer/lockBuffer/dequeueBuffer properly
Rewrote SurfaceFlinger's buffer management from the ground-up. The design now support an arbitrary number of buffers per surface, however the current implementation is limited to four. Currently only 2 buffers are used in practice. The main new feature is to be able to dequeue all buffers at once (very important when there are only two). A client can dequeue all buffers until there are none available, it can lock all buffers except the last one that is used for composition. The client will block then, until a new buffer is enqueued. The current implementation requires that buffers are locked in the same order they are dequeued and enqueued in the same order they are locked. Only one buffer can be locked at a time. eg. Allowed sequence: DQ, DQ, LOCK, Q, LOCK, Q eg. Forbidden sequence: DQ, DQ, LOCK, LOCK, Q, Q
Diffstat (limited to 'libs/surfaceflinger')
-rw-r--r--libs/surfaceflinger/Android.mk2
-rw-r--r--libs/surfaceflinger/Buffer.cpp (renamed from libs/surfaceflinger/LayerBitmap.cpp)109
-rw-r--r--libs/surfaceflinger/Buffer.h (renamed from libs/surfaceflinger/LayerBitmap.h)60
-rw-r--r--libs/surfaceflinger/BufferAllocator.cpp11
-rw-r--r--libs/surfaceflinger/DisplayHardware/DisplayHardware.cpp18
-rw-r--r--libs/surfaceflinger/Layer.cpp493
-rw-r--r--libs/surfaceflinger/Layer.h81
-rw-r--r--libs/surfaceflinger/LayerBase.cpp29
-rw-r--r--libs/surfaceflinger/LayerBase.h19
-rw-r--r--libs/surfaceflinger/LayerBuffer.cpp21
-rw-r--r--libs/surfaceflinger/LayerBuffer.h10
-rw-r--r--libs/surfaceflinger/LayerDim.cpp1
-rw-r--r--libs/surfaceflinger/LayerDim.h5
-rw-r--r--libs/surfaceflinger/SurfaceFlinger.cpp99
-rw-r--r--libs/surfaceflinger/SurfaceFlinger.h9
15 files changed, 278 insertions, 689 deletions
diff --git a/libs/surfaceflinger/Android.mk b/libs/surfaceflinger/Android.mk
index c4a70c8..49da111 100644
--- a/libs/surfaceflinger/Android.mk
+++ b/libs/surfaceflinger/Android.mk
@@ -6,12 +6,12 @@ LOCAL_SRC_FILES:= \
DisplayHardware/DisplayHardware.cpp \
DisplayHardware/DisplayHardwareBase.cpp \
BlurFilter.cpp.arm \
+ Buffer.cpp \
BufferAllocator.cpp \
Layer.cpp \
LayerBase.cpp \
LayerBuffer.cpp \
LayerBlur.cpp \
- LayerBitmap.cpp \
LayerDim.cpp \
MessageQueue.cpp \
SurfaceFlinger.cpp \
diff --git a/libs/surfaceflinger/LayerBitmap.cpp b/libs/surfaceflinger/Buffer.cpp
index dd61e1a..4a7c55e 100644
--- a/libs/surfaceflinger/LayerBitmap.cpp
+++ b/libs/surfaceflinger/Buffer.cpp
@@ -27,8 +27,8 @@
#include <ui/Surface.h>
#include <pixelflinger/pixelflinger.h>
+#include "Buffer.h"
#include "BufferAllocator.h"
-#include "LayerBitmap.h"
#include "SurfaceFlinger.h"
@@ -38,15 +38,16 @@ namespace android {
// Buffer and implementation of android_native_buffer_t
// ===========================================================================
+Buffer::Buffer()
+ : SurfaceBuffer(), mInitCheck(NO_ERROR), mVStride(0)
+{
+}
+
Buffer::Buffer(uint32_t w, uint32_t h, PixelFormat format,
uint32_t reqUsage, uint32_t flags)
- : SurfaceBuffer(), mInitCheck(NO_INIT), mFlags(flags),
- mVStride(0)
+ : SurfaceBuffer(), mInitCheck(NO_INIT), mVStride(0)
{
- this->format = format;
- if (w>0 && h>0) {
- mInitCheck = initSize(w, h, reqUsage);
- }
+ mInitCheck = initSize(w, h, format, reqUsage, flags);
}
Buffer::~Buffer()
@@ -66,7 +67,19 @@ android_native_buffer_t* Buffer::getNativeBuffer() const
return static_cast<android_native_buffer_t*>(const_cast<Buffer*>(this));
}
-status_t Buffer::initSize(uint32_t w, uint32_t h, uint32_t reqUsage)
+status_t Buffer::reallocate(uint32_t w, uint32_t h, PixelFormat f,
+ uint32_t reqUsage, uint32_t flags)
+{
+ if (handle) {
+ BufferAllocator& allocator(BufferAllocator::get());
+ allocator.free(handle);
+ handle = 0;
+ }
+ return initSize(w, h, f, reqUsage, flags);
+}
+
+status_t Buffer::initSize(uint32_t w, uint32_t h, PixelFormat format,
+ uint32_t reqUsage, uint32_t flags)
{
status_t err = NO_ERROR;
@@ -84,7 +97,7 @@ status_t Buffer::initSize(uint32_t w, uint32_t h, uint32_t reqUsage)
*
*/
- if (mFlags & Buffer::SECURE) {
+ if (flags & Buffer::SECURE) {
// secure buffer, don't store it into the GPU
usage = BufferAllocator::USAGE_SW_READ_OFTEN |
BufferAllocator::USAGE_SW_WRITE_OFTEN;
@@ -95,10 +108,10 @@ status_t Buffer::initSize(uint32_t w, uint32_t h, uint32_t reqUsage)
}
err = allocator.alloc(w, h, format, usage, &handle, &stride);
-
if (err == NO_ERROR) {
- width = w;
- height = h;
+ this->width = w;
+ this->height = h;
+ this->format = format;
mVStride = 0;
}
@@ -121,78 +134,6 @@ status_t Buffer::lock(GGLSurface* sur, uint32_t usage)
return res;
}
-// ===========================================================================
-// LayerBitmap
-// ===========================================================================
-
-LayerBitmap::LayerBitmap()
- : mInfo(0), mWidth(0), mHeight(0)
-{
-}
-
-LayerBitmap::~LayerBitmap()
-{
-}
-
-status_t LayerBitmap::init(surface_info_t* info,
- uint32_t w, uint32_t h, PixelFormat format, uint32_t flags)
-{
- if (info == NULL)
- return BAD_VALUE;
-
- mFormat = format;
- mFlags = flags;
- mWidth = w;
- mHeight = h;
-
- mInfo = info;
- memset(info, 0, sizeof(surface_info_t));
- info->flags = surface_info_t::eNeedNewBuffer;
-
- // init the buffer, but don't trigger an allocation
- mBuffer = new Buffer(0, 0, format, flags);
- return NO_ERROR;
-}
-
-status_t LayerBitmap::setSize(uint32_t w, uint32_t h)
-{
- Mutex::Autolock _l(mLock);
- if ((w != mWidth) || (h != mHeight)) {
- mWidth = w;
- mHeight = h;
- // this will signal the client that it needs to asks us for a new buffer
- mInfo->flags = surface_info_t::eNeedNewBuffer;
- }
- return NO_ERROR;
-}
-
-sp<Buffer> LayerBitmap::allocate(uint32_t reqUsage)
-{
- Mutex::Autolock _l(mLock);
- surface_info_t* info = mInfo;
- mBuffer.clear(); // free buffer before allocating a new one
- sp<Buffer> buffer = new Buffer(mWidth, mHeight, mFormat, reqUsage, mFlags);
- status_t err = buffer->initCheck();
- if (LIKELY(err == NO_ERROR)) {
- info->flags = surface_info_t::eBufferDirty;
- info->status = NO_ERROR;
- } else {
- memset(info, 0, sizeof(surface_info_t));
- info->status = NO_MEMORY;
- }
- mBuffer = buffer;
- return buffer;
-}
-
-status_t LayerBitmap::free()
-{
- mBuffer.clear();
- mWidth = 0;
- mHeight = 0;
- return NO_ERROR;
-}
-
-
// ---------------------------------------------------------------------------
}; // namespace android
diff --git a/libs/surfaceflinger/LayerBitmap.h b/libs/surfaceflinger/Buffer.h
index 87e8f42..79f4eeb 100644
--- a/libs/surfaceflinger/LayerBitmap.h
+++ b/libs/surfaceflinger/Buffer.h
@@ -30,7 +30,7 @@
#include <pixelflinger/pixelflinger.h>
-#include <private/ui/SharedState.h>
+#include <private/ui/SharedBufferStack.h>
#include <private/ui/SurfaceBuffer.h>
class copybit_image_t;
@@ -38,10 +38,6 @@ struct android_native_buffer_t;
namespace android {
-// ---------------------------------------------------------------------------
-class IMemory;
-class LayerBitmap;
-
// ===========================================================================
// Buffer
// ===========================================================================
@@ -56,6 +52,8 @@ public:
SECURE = 0x00000004
};
+ Buffer();
+
// creates w * h buffer
Buffer(uint32_t w, uint32_t h, PixelFormat format,
uint32_t reqUsage, uint32_t flags = 0);
@@ -74,6 +72,9 @@ public:
android_native_buffer_t* getNativeBuffer() const;
+ status_t reallocate(uint32_t w, uint32_t h, PixelFormat f,
+ uint32_t reqUsage, uint32_t flags);
+
private:
friend class LightRefBase<Buffer>;
Buffer(const Buffer& rhs);
@@ -81,52 +82,11 @@ private:
Buffer& operator = (const Buffer& rhs);
const Buffer& operator = (const Buffer& rhs) const;
- status_t initSize(uint32_t w, uint32_t h, uint32_t reqUsage);
-
- ssize_t mInitCheck;
- uint32_t mFlags;
- uint32_t mVStride;
-};
-
-// ===========================================================================
-// LayerBitmap
-// ===========================================================================
+ status_t initSize(uint32_t w, uint32_t h, PixelFormat format,
+ uint32_t reqUsage, uint32_t flags);
-class LayerBitmap
-{
-public:
- enum {
- DONT_CLEAR = Buffer::DONT_CLEAR,
- SECURE = Buffer::SECURE
- };
- LayerBitmap();
- ~LayerBitmap();
-
- status_t init(surface_info_t* info,
- uint32_t w, uint32_t h, PixelFormat format, uint32_t flags = 0);
-
- status_t setSize(uint32_t w, uint32_t h);
-
- sp<Buffer> allocate(uint32_t reqUsage);
- status_t free();
-
- sp<const Buffer> getBuffer() const { return mBuffer; }
- sp<Buffer> getBuffer() { return mBuffer; }
-
- uint32_t getWidth() const { return mWidth; }
- uint32_t getHeight() const { return mHeight; }
- PixelFormat getPixelFormat() const { return mBuffer->getPixelFormat(); }
- Rect getBounds() const { return mBuffer->getBounds(); }
-
-private:
- surface_info_t* mInfo;
- sp<Buffer> mBuffer;
- uint32_t mWidth;
- uint32_t mHeight;
- PixelFormat mFormat;
- uint32_t mFlags;
- // protects setSize() and allocate()
- mutable Mutex mLock;
+ ssize_t mInitCheck;
+ uint32_t mVStride;
};
}; // namespace android
diff --git a/libs/surfaceflinger/BufferAllocator.cpp b/libs/surfaceflinger/BufferAllocator.cpp
index cee8b64..19867a5 100644
--- a/libs/surfaceflinger/BufferAllocator.cpp
+++ b/libs/surfaceflinger/BufferAllocator.cpp
@@ -71,14 +71,23 @@ void BufferAllocator::dump(String8& result) const
result.append(buffer);
}
+static inline uint32_t clamp(uint32_t c) {
+ return c>0 ? c : 1;
+}
+
status_t BufferAllocator::alloc(uint32_t w, uint32_t h, PixelFormat format,
int usage, buffer_handle_t* handle, int32_t* stride)
{
Mutex::Autolock _l(mLock);
-
+
+ // make sure to not allocate a 0 x 0 buffer
+ w = clamp(w);
+ h = clamp(h);
+
// we have a h/w allocator and h/w buffer is requested
status_t err = mAllocDev->alloc(mAllocDev,
w, h, format, usage, handle, stride);
+
LOGW_IF(err, "alloc(%u, %u, %d, %08x, ...) failed %d (%s)",
w, h, format, usage, err, strerror(-err));
diff --git a/libs/surfaceflinger/DisplayHardware/DisplayHardware.cpp b/libs/surfaceflinger/DisplayHardware/DisplayHardware.cpp
index 3f607f6..651e7cf 100644
--- a/libs/surfaceflinger/DisplayHardware/DisplayHardware.cpp
+++ b/libs/surfaceflinger/DisplayHardware/DisplayHardware.cpp
@@ -46,22 +46,25 @@ using namespace android;
static __attribute__((noinline))
void checkGLErrors()
{
- GLenum error = glGetError();
- if (error != GL_NO_ERROR)
+ do {
+ // there could be more than one error flag
+ GLenum error = glGetError();
+ if (error == GL_NO_ERROR)
+ break;
LOGE("GL error 0x%04x", int(error));
+ } while(true);
}
static __attribute__((noinline))
void checkEGLErrors(const char* token)
{
EGLint error = eglGetError();
- // GLESonGL seems to be returning 0 when there is no errors?
- if (error && error != EGL_SUCCESS)
- LOGE("%s error 0x%04x (%s)",
+ if (error && error != EGL_SUCCESS) {
+ LOGE("%s: EGL error 0x%04x (%s)",
token, int(error), EGLUtils::strerror(error));
+ }
}
-
/*
* Initialize the display to the specified values.
*
@@ -158,7 +161,6 @@ void DisplayHardware::init(uint32_t dpy)
*/
surface = eglCreateWindowSurface(display, config, mNativeWindow.get(), NULL);
- checkEGLErrors("eglCreateWindowSurface");
if (eglQuerySurface(display, surface, EGL_SWAP_BEHAVIOR, &dummy) == EGL_TRUE) {
if (dummy == EGL_BUFFER_PRESERVED) {
@@ -212,8 +214,6 @@ void DisplayHardware::init(uint32_t dpy)
*/
context = eglCreateContext(display, config, NULL, NULL);
- //checkEGLErrors("eglCreateContext");
-
/*
* Gather OpenGL ES extensions
diff --git a/libs/surfaceflinger/Layer.cpp b/libs/surfaceflinger/Layer.cpp
index 6f92515..ecb6b32 100644
--- a/libs/surfaceflinger/Layer.cpp
+++ b/libs/surfaceflinger/Layer.cpp
@@ -28,9 +28,9 @@
#include <ui/PixelFormat.h>
#include <ui/Surface.h>
+#include "Buffer.h"
#include "clz.h"
#include "Layer.h"
-#include "LayerBitmap.h"
#include "SurfaceFlinger.h"
#include "DisplayHardware/DisplayHardware.h"
@@ -47,26 +47,29 @@ const char* const Layer::typeID = "Layer";
// ---------------------------------------------------------------------------
-Layer::Layer(SurfaceFlinger* flinger, DisplayID display, const sp<Client>& c, int32_t i)
- : LayerBaseClient(flinger, display, c, i),
+Layer::Layer(SurfaceFlinger* flinger, DisplayID display,
+ const sp<Client>& c, int32_t i)
+ : LayerBaseClient(flinger, display, c, i), lcblk(NULL),
mSecure(false),
- mFrontBufferIndex(1),
- mNeedsBlending(true),
- mResizeTransactionDone(false)
+ mNeedsBlending(true)
{
// no OpenGL operation is possible here, since we might not be
// in the OpenGL thread.
+ lcblk = new SharedBufferServer(c->ctrlblk, i, NUM_BUFFERS);
+ mFrontBufferIndex = lcblk->getFrontBuffer();
}
Layer::~Layer()
{
destroy();
// the actual buffers will be destroyed here
+ delete lcblk;
+
}
void Layer::destroy()
{
- for (int i=0 ; i<NUM_BUFFERS ; i++) {
+ for (size_t i=0 ; i<NUM_BUFFERS ; i++) {
if (mTextures[i].name != -1U) {
glDeleteTextures(1, &mTextures[i].name);
mTextures[i].name = -1U;
@@ -76,19 +79,11 @@ void Layer::destroy()
eglDestroyImageKHR(dpy, mTextures[i].image);
mTextures[i].image = EGL_NO_IMAGE_KHR;
}
- mBuffers[i].free();
+ mBuffers[i].clear();
}
mSurface.clear();
}
-void Layer::initStates(uint32_t w, uint32_t h, uint32_t flags)
-{
- LayerBase::initStates(w,h,flags);
-
- if (flags & ISurfaceComposer::eDestroyBackbuffer)
- lcblk->flags |= eNoCopyBack;
-}
-
sp<LayerBaseClient::Surface> Layer::createSurface() const
{
return mSurface;
@@ -112,13 +107,14 @@ status_t Layer::setBuffers( uint32_t w, uint32_t h,
if (flags & ISurfaceComposer::eSecure)
bufferFlags |= Buffer::SECURE;
+ mFormat = format;
+ mWidth = w;
+ mHeight = h;
mSecure = (bufferFlags & Buffer::SECURE) ? true : false;
mNeedsBlending = (info.h_alpha - info.l_alpha) > 0;
- for (int i=0 ; i<2 ; i++) {
- err = mBuffers[i].init(lcblk->surface + i, w, h, format, bufferFlags);
- if (err != NO_ERROR) {
- return err;
- }
+ mBufferFlags = bufferFlags;
+ for (size_t i=0 ; i<NUM_BUFFERS ; i++) {
+ mBuffers[i] = new Buffer();
}
mSurface = new SurfaceLayer(mFlinger, clientIndex(), this);
return NO_ERROR;
@@ -126,7 +122,8 @@ status_t Layer::setBuffers( uint32_t w, uint32_t h,
void Layer::reloadTexture(const Region& dirty)
{
- const sp<Buffer>& buffer(frontBuffer().getBuffer());
+ Mutex::Autolock _l(mLock);
+ sp<Buffer> buffer(getFrontBuffer());
if (LIKELY(mFlags & DisplayHardware::DIRECT_TEXTURE)) {
int index = mFrontBufferIndex;
if (LIKELY(!mTextures[index].dirty)) {
@@ -202,80 +199,64 @@ void Layer::onDraw(const Region& clip) const
const int index = (mFlags & DisplayHardware::DIRECT_TEXTURE) ?
mFrontBufferIndex : 0;
GLuint textureName = mTextures[index].name;
-
if (UNLIKELY(textureName == -1LU)) {
- LOGW("Layer %p doesn't have a texture", this);
+ //LOGW("Layer %p doesn't have a texture", this);
// the texture has not been created yet, this Layer has
// in fact never been drawn into. this happens frequently with
// SurfaceView.
clearWithOpenGL(clip);
return;
}
+
drawWithOpenGL(clip, mTextures[index]);
}
-sp<SurfaceBuffer> Layer::peekBuffer(int usage)
+sp<SurfaceBuffer> Layer::requestBuffer(int index, int usage)
{
/*
- * This is called from the client's Surface::lock(), after it locked
- * the surface successfully. We're therefore guaranteed that the
- * back-buffer is not in use by ourselves.
- * Of course, we need to validate all this, which is not trivial.
- *
- * FIXME: A resize could happen at any time here. What to do about this?
- * - resize() form post()
- * - resize() from doTransaction()
- *
- * We'll probably need an internal lock for this.
- *
+ * This is called from the client's Surface::dequeue(). This can happen
+ * at any time, especially while we're in the middle of using the
+ * buffer 'index' as our front buffer.
*
- * TODO: We need to make sure that post() doesn't swap
- * the buffers under us.
+ * Make sure the buffer we're resizing is not the front buffer and has been
+ * dequeued. Once this condition is asserted, we are guaranteed that this
+ * buffer cannot become the front buffer under our feet, since we're called
+ * from Surface::dequeue()
*/
+ status_t err = lcblk->assertReallocate(index);
+ LOGE_IF(err, "assertReallocate(%d) failed (%s)", index, strerror(-err));
- // it's okay to read swapState for the purpose of figuring out the
- // backbuffer index, which cannot change (since the app has locked it).
- const uint32_t state = lcblk->swapState;
- const int32_t backBufferIndex = layer_cblk_t::backBuffer(state);
+ Mutex::Autolock _l(mLock);
+ uint32_t w = mWidth;
+ uint32_t h = mHeight;
- // get rid of the EGL image, since we shouldn't need it anymore
- // (note that we're in a different thread than where it is being used)
- if (mTextures[backBufferIndex].image != EGL_NO_IMAGE_KHR) {
- EGLDisplay dpy(mFlinger->graphicPlane(0).getEGLDisplay());
- eglDestroyImageKHR(dpy, mTextures[backBufferIndex].image);
- mTextures[backBufferIndex].image = EGL_NO_IMAGE_KHR;
+ sp<Buffer>& buffer(mBuffers[index]);
+ if (buffer->getStrongCount() == 1) {
+ err = buffer->reallocate(w, h, mFormat, usage, mBufferFlags);
+ } else {
+ // here we have to reallocate a new buffer because we could have a
+ // client in our process with a reference to it (eg: status bar),
+ // and we can't release the handle under its feet.
+ buffer.clear();
+ buffer = new Buffer(w, h, mFormat, usage, mBufferFlags);
+ err = buffer->initCheck();
}
-
- LayerBitmap& layerBitmap(mBuffers[backBufferIndex]);
- sp<SurfaceBuffer> buffer = layerBitmap.allocate(usage);
-
- LOGD_IF(DEBUG_RESIZE,
- "Layer::getBuffer(this=%p), index=%d, (%d,%d), (%d,%d)",
- this, backBufferIndex,
- layerBitmap.getWidth(),
- layerBitmap.getHeight(),
- layerBitmap.getBuffer()->getWidth(),
- layerBitmap.getBuffer()->getHeight());
-
- if (UNLIKELY(buffer == 0)) {
- // XXX: what to do, what to do?
+
+ if (err || buffer->handle == 0) {
+ LOGE_IF(err || buffer->handle == 0,
+ "Layer::requestBuffer(this=%p), index=%d, w=%d, h=%d failed (%s)",
+ this, index, w, h, strerror(-err));
} else {
- // texture is now dirty...
- mTextures[backBufferIndex].dirty = true;
- // ... so it the visible region (because we consider the surface's
- // buffer size for visibility calculations)
- forceVisibilityTransaction();
- mFlinger->setTransactionFlags(eTraversalNeeded);
+ LOGD_IF(DEBUG_RESIZE,
+ "Layer::requestBuffer(this=%p), index=%d, w=%d, h=%d",
+ this, index, w, h);
}
- return buffer;
-}
-void Layer::scheduleBroadcast()
-{
- sp<Client> ourClient(client.promote());
- if (ourClient != 0) {
- mFlinger->scheduleBroadcast(ourClient);
+ if (err == NO_ERROR && buffer->handle != 0) {
+ // texture is now dirty...
+ mTextures[index].dirty = true;
}
+ return buffer;
}
uint32_t Layer::doTransaction(uint32_t flags)
@@ -283,114 +264,48 @@ uint32_t Layer::doTransaction(uint32_t flags)
const Layer::State& front(drawingState());
const Layer::State& temp(currentState());
- // the test front.{w|h} != temp.{w|h} is not enough because it is possible
- // that the size changed back to its previous value before the buffer
- // was resized (in the eLocked case below), in which case, we still
- // need to execute the code below so the clients have a chance to be
- // release. resize() deals with the fact that the size can be the same.
-
- /*
- * Various states we could be in...
-
- resize = state & eResizeRequested;
- if (backbufferChanged) {
- if (resize == 0) {
- // ERROR, the resized buffer doesn't have its resize flag set
- } else if (resize == mask) {
- // ERROR one of the buffer has already been resized
- } else if (resize == mask ^ eResizeRequested) {
- // ERROR, the resized buffer doesn't have its resize flag set
- } else if (resize == eResizeRequested) {
- // OK, Normal case, proceed with resize
- }
- } else {
- if (resize == 0) {
- // OK, nothing special, do nothing
- } else if (resize == mask) {
- // restarted transaction, do nothing
- } else if (resize == mask ^ eResizeRequested) {
- // restarted transaction, do nothing
- } else if (resize == eResizeRequested) {
- // OK, size reset to previous value, proceed with resize
- }
- }
- */
-
// Index of the back buffer
const bool backbufferChanged = (front.w != temp.w) || (front.h != temp.h);
- const uint32_t state = lcblk->swapState;
- const int32_t clientBackBufferIndex = layer_cblk_t::backBuffer(state);
- const uint32_t mask = clientBackBufferIndex ? eResizeBuffer1 : eResizeBuffer0;
- uint32_t resizeFlags = state & eResizeRequested;
-
- if (UNLIKELY(backbufferChanged && (resizeFlags != eResizeRequested))) {
- LOGE( "backbuffer size changed, but both resize flags are not set! "
- "(layer=%p), state=%08x, requested (%dx%d), drawing (%d,%d), "
- "index=%d, (%dx%d), (%dx%d)",
- this, state,
- int(temp.w), int(temp.h),
- int(drawingState().w), int(drawingState().h),
- int(clientBackBufferIndex),
- int(mBuffers[0].getWidth()), int(mBuffers[0].getHeight()),
- int(mBuffers[1].getWidth()), int(mBuffers[1].getHeight()));
- // if we get there we're pretty screwed. the only reasonable
- // thing to do is to pretend we should do the resize since
- // backbufferChanged is set (this also will give a chance to
- // client to get unblocked)
- resizeFlags = eResizeRequested;
- }
-
- if (resizeFlags == eResizeRequested) {
- // NOTE: asserting that clientBackBufferIndex!=mFrontBufferIndex
- // here, would be wrong and misleading because by this point
- // mFrontBufferIndex has not been updated yet.
+ if (backbufferChanged) {
+ // the size changed, we need to ask our client to request a new buffer
LOGD_IF(DEBUG_RESIZE,
- "resize (layer=%p), state=%08x, "
- "requested (%dx%d), "
- "drawing (%d,%d), "
- "index=%d, (%dx%d), (%dx%d)",
- this, state,
- int(temp.w), int(temp.h),
+ "resize (layer=%p), requested (%dx%d), "
+ "drawing (%d,%d), (%dx%d), (%dx%d)",
+ this, int(temp.w), int(temp.h),
int(drawingState().w), int(drawingState().h),
- int(clientBackBufferIndex),
- int(mBuffers[0].getWidth()), int(mBuffers[0].getHeight()),
- int(mBuffers[1].getWidth()), int(mBuffers[1].getHeight()));
-
- if (state & eLocked) {
- // if the buffer is locked, we can't resize anything because
- // - the backbuffer is currently in use by the user
- // - the front buffer is being shown
- // We just act as if the transaction didn't happen and we
- // reschedule it later...
- flags |= eRestartTransaction;
- } else {
- // This buffer needs to be resized
- status_t err =
- resize(clientBackBufferIndex, temp.w, temp.h, "transaction");
- if (err == NO_ERROR) {
- const uint32_t mask = clientBackBufferIndex ?
- eResizeBuffer1 : eResizeBuffer0;
- android_atomic_and(~mask, &(lcblk->swapState));
- // since a buffer became available, we can let the client go...
- scheduleBroadcast();
- mResizeTransactionDone = true;
-
- // we're being resized and there is a freeze display request,
- // acquire a freeze lock, so that the screen stays put
- // until we've redrawn at the new size; this is to avoid
- // glitches upon orientation changes.
- if (mFlinger->hasFreezeRequest()) {
- // if the surface is hidden, don't try to acquire the
- // freeze lock, since hidden surfaces may never redraw
- if (!(front.flags & ISurfaceComposer::eLayerHidden)) {
- mFreezeLock = mFlinger->getFreezeLock();
- }
- }
+ int(mBuffers[0]->getWidth()), int(mBuffers[0]->getHeight()),
+ int(mBuffers[1]->getWidth()), int(mBuffers[1]->getHeight()));
+
+ // record the new size, form this point on, when the client request a
+ // buffer, it'll get the new size.
+ setDrawingSize(temp.w, temp.h);
+
+ // all buffers need reallocation
+ lcblk->reallocate();
+
+ // recompute the visible region
+ // FIXME: ideally we would do that only when we have received
+ // a buffer of the right size
+ flags |= Layer::eVisibleRegion;
+ this->contentDirty = true;
+
+#if 0
+ // FIXME: handle freeze lock
+ // we're being resized and there is a freeze display request,
+ // acquire a freeze lock, so that the screen stays put
+ // until we've redrawn at the new size; this is to avoid
+ // glitches upon orientation changes.
+ if (mFlinger->hasFreezeRequest()) {
+ // if the surface is hidden, don't try to acquire the
+ // freeze lock, since hidden surfaces may never redraw
+ if (!(front.flags & ISurfaceComposer::eLayerHidden)) {
+ mFreezeLock = mFlinger->getFreezeLock();
}
}
+#endif
}
-
+
if (temp.sequence != front.sequence) {
if (temp.flags & ISurfaceComposer::eLayerHidden || temp.alpha == 0) {
// this surface is now hidden, so it shouldn't hold a freeze lock
@@ -402,65 +317,10 @@ uint32_t Layer::doTransaction(uint32_t flags)
return LayerBase::doTransaction(flags);
}
-status_t Layer::resize(
- int32_t clientBackBufferIndex,
- uint32_t width, uint32_t height,
- const char* what)
-{
- /*
- * handle resize (backbuffer and frontbuffer reallocation)
- * this is called from post() or from doTransaction()
- */
-
- const LayerBitmap& clientBackBuffer(mBuffers[clientBackBufferIndex]);
-
- // if the new (transaction) size is != from the the backbuffer
- // then we need to reallocate the backbuffer
- bool backbufferChanged = (clientBackBuffer.getWidth() != width) ||
- (clientBackBuffer.getHeight() != height);
-
- LOGD_IF(!backbufferChanged,
- "(%s) eResizeRequested (layer=%p), but size not changed: "
- "requested (%dx%d), drawing (%d,%d), current (%d,%d),"
- "state=%08lx, index=%d, (%dx%d), (%dx%d)",
- what, this,
- int(width), int(height),
- int(drawingState().w), int(drawingState().h),
- int(currentState().w), int(currentState().h),
- long(lcblk->swapState),
- int(clientBackBufferIndex),
- int(mBuffers[0].getWidth()), int(mBuffers[0].getHeight()),
- int(mBuffers[1].getWidth()), int(mBuffers[1].getHeight()));
-
- // this can happen when changing the size back and forth quickly
- status_t err = NO_ERROR;
- if (backbufferChanged) {
-
- LOGD_IF(DEBUG_RESIZE,
- "resize (layer=%p), requested (%dx%d), "
- "index=%d, (%dx%d), (%dx%d)",
- this, int(width), int(height), int(clientBackBufferIndex),
- int(mBuffers[0].getWidth()), int(mBuffers[0].getHeight()),
- int(mBuffers[1].getWidth()), int(mBuffers[1].getHeight()));
-
- err = mBuffers[clientBackBufferIndex].setSize(width, height);
- if (UNLIKELY(err != NO_ERROR)) {
- // This really should never happen
- LOGE("resizing buffer %d to (%u,%u) failed [%08x] %s",
- clientBackBufferIndex, width, height, err, strerror(err));
- // couldn't reallocate the surface
- android_atomic_write(eInvalidSurface, &lcblk->swapState);
- }
- }
- return err;
-}
-
-void Layer::setSizeChanged(uint32_t w, uint32_t h)
-{
- LOGD_IF(DEBUG_RESIZE,
- "setSizeChanged w=%d, h=%d (old: w=%d, h=%d)",
- w, h, mCurrentState.w, mCurrentState.h);
- android_atomic_or(eResizeRequested, &(lcblk->swapState));
+void Layer::setDrawingSize(uint32_t w, uint32_t h) {
+ Mutex::Autolock _l(mLock);
+ mWidth = w;
+ mHeight = h;
}
// ----------------------------------------------------------------------------
@@ -469,139 +329,26 @@ void Layer::setSizeChanged(uint32_t w, uint32_t h)
void Layer::lockPageFlip(bool& recomputeVisibleRegions)
{
- uint32_t state = android_atomic_or(eBusy, &(lcblk->swapState));
- // preemptively block the client, because he might set
- // eFlipRequested at any time and want to use this buffer
- // for the next frame. This will be unset below if it
- // turns out we didn't need it.
-
- uint32_t mask = eInvalidSurface | eFlipRequested | eResizeRequested;
- if (!(state & mask))
- return;
-
- if (UNLIKELY(state & eInvalidSurface)) {
- // if eInvalidSurface is set, this means the surface
- // became invalid during a transaction (NO_MEMORY for instance)
- scheduleBroadcast();
+ ssize_t buf = lcblk->retireAndLock();
+ if (buf < NO_ERROR) {
+ //LOGW("nothing to retire (%s)", strerror(-buf));
+ // NOTE: here the buffer is locked because we will used
+ // for composition later in the loop
return;
}
-
- if (UNLIKELY(state & eFlipRequested)) {
- uint32_t oldState;
- mPostedDirtyRegion = post(&oldState, recomputeVisibleRegions);
- if (oldState & eNextFlipPending) {
- // Process another round (we know at least a buffer
- // is ready for that client).
- mFlinger->signalEvent();
- }
- }
-}
-
-Region Layer::post(uint32_t* previousSate, bool& recomputeVisibleRegions)
-{
- // atomically swap buffers and (re)set eFlipRequested
- int32_t oldValue, newValue;
- layer_cblk_t * const lcblk = this->lcblk;
- do {
- oldValue = lcblk->swapState;
- // get the current value
-
- LOG_ASSERT(oldValue&eFlipRequested,
- "eFlipRequested not set, yet we're flipping! (state=0x%08lx)",
- long(oldValue));
-
- newValue = (oldValue ^ eIndex);
- // swap buffers
-
- newValue &= ~(eFlipRequested | eNextFlipPending);
- // clear eFlipRequested and eNextFlipPending
-
- if (oldValue & eNextFlipPending)
- newValue |= eFlipRequested;
- // if eNextFlipPending is set (second buffer already has something
- // in it) we need to reset eFlipRequested because the client
- // might never do it
-
- } while(android_atomic_cmpxchg(oldValue, newValue, &(lcblk->swapState)));
- *previousSate = oldValue;
- const int32_t index = (newValue & eIndex) ^ 1;
- mFrontBufferIndex = index;
+ // we retired a buffer, which becomes the new front buffer
+ mFrontBufferIndex = buf;
- /* NOTE: it's safe to set this flag here because this is only touched
- * from LayerBitmap::allocate(), which by construction cannot happen
- * while we're in post().
- */
- lcblk->surface[index].flags &= ~surface_info_t::eBufferDirty;
-
- // ... post the new front-buffer
- Region dirty(lcblk->region + index);
- dirty.andSelf(frontBuffer().getBounds());
-
- //LOGD("Did post oldValue=%08lx, newValue=%08lx, mFrontBufferIndex=%u\n",
- // oldValue, newValue, mFrontBufferIndex);
- //dirty.dump("dirty");
+ // get the dirty region
+ sp<Buffer> newFrontBuffer(getBuffer(buf));
+ const Region dirty(lcblk->getDirtyRegion(buf));
+ mPostedDirtyRegion = dirty.intersect( newFrontBuffer->getBounds() );
- if (UNLIKELY(oldValue & eResizeRequested)) {
-
- LOGD_IF(DEBUG_RESIZE,
- "post (layer=%p), state=%08x, "
- "index=%d, (%dx%d), (%dx%d)",
- this, newValue,
- int(1-index),
- int(mBuffers[0].getWidth()), int(mBuffers[0].getHeight()),
- int(mBuffers[1].getWidth()), int(mBuffers[1].getHeight()));
-
- // here, we just posted the surface and we have resolved
- // the front/back buffer indices. The client is blocked, so
- // it cannot start using the new backbuffer.
-
- // If the backbuffer was resized in THIS round, we actually cannot
- // resize the frontbuffer because it has *just* been drawn (and we
- // would have nothing to draw). In this case we just skip the resize
- // it'll happen after the next page flip or during the next
- // transaction.
-
- const uint32_t mask = (1-index) ? eResizeBuffer1 : eResizeBuffer0;
- if (mResizeTransactionDone && (newValue & mask)) {
- // Resize the layer's second buffer only if the transaction
- // happened. It may not have happened yet if eResizeRequested
- // was set immediately after the "transactionRequested" test,
- // in which case the drawing state's size would be wrong.
- mFreezeLock.clear();
- const Layer::State& s(drawingState());
- if (resize(1-index, s.w, s.h, "post") == NO_ERROR) {
- do {
- oldValue = lcblk->swapState;
- if ((oldValue & eResizeRequested) == eResizeRequested) {
- // ugh, another resize was requested since we processed
- // the first buffer, don't free the client, and let
- // the next transaction handle everything.
- break;
- }
- newValue = oldValue & ~mask;
- } while(android_atomic_cmpxchg(oldValue, newValue, &(lcblk->swapState)));
- }
- mResizeTransactionDone = false;
- recomputeVisibleRegions = true;
- this->contentDirty = true;
- }
- }
+ // FIXME: signal an event if we have more buffers waiting
+ // mFlinger->signalEvent();
- reloadTexture(dirty);
-
- return dirty;
-}
-
-Point Layer::getPhysicalSize() const
-{
- sp<const Buffer> front(frontBuffer().getBuffer());
- Point size(front->getWidth(), front->getHeight());
- if ((size.x | size.y) == 0) {
- // if we don't have a buffer yet, just use the state's size.
- size = LayerBase::getPhysicalSize();
- }
- return size;
+ reloadTexture( mPostedDirtyRegion );
}
void Layer::unlockPageFlip(
@@ -622,21 +369,15 @@ void Layer::unlockPageFlip(
// is in screen space as well).
dirtyRegion.andSelf(visibleRegionScreen);
outDirtyRegion.orSelf(dirtyRegion);
-
- // client could be blocked, so signal them so they get a
- // chance to reevaluate their condition.
- scheduleBroadcast();
}
}
void Layer::finishPageFlip()
{
- if (LIKELY(!(lcblk->swapState & eInvalidSurface))) {
- LOGE_IF(!(lcblk->swapState & eBusy),
- "layer %p wasn't locked!", this);
- android_atomic_and(~eBusy, &(lcblk->swapState));
- }
- scheduleBroadcast();
+ status_t err = lcblk->unlock( mFrontBufferIndex );
+ LOGE_IF(err!=NO_ERROR,
+ "layer %p, buffer=%d wasn't locked!",
+ this, mFrontBufferIndex);
}
// ---------------------------------------------------------------------------
@@ -651,12 +392,16 @@ Layer::SurfaceLayer::~SurfaceLayer()
{
}
-sp<SurfaceBuffer> Layer::SurfaceLayer::getBuffer(int usage)
+sp<SurfaceBuffer> Layer::SurfaceLayer::requestBuffer(int index, int usage)
{
- sp<SurfaceBuffer> buffer = 0;
+ sp<SurfaceBuffer> buffer;
sp<Layer> owner(getOwner());
if (owner != 0) {
- buffer = owner->peekBuffer(usage);
+ LOGE_IF(uint32_t(index)>=NUM_BUFFERS,
+ "getBuffer() index (%d) out of range", index);
+ if (uint32_t(index) < NUM_BUFFERS) {
+ buffer = owner->requestBuffer(index, usage);
+ }
}
return buffer;
}
diff --git a/libs/surfaceflinger/Layer.h b/libs/surfaceflinger/Layer.h
index add5d50..3b4489e 100644
--- a/libs/surfaceflinger/Layer.h
+++ b/libs/surfaceflinger/Layer.h
@@ -21,10 +21,6 @@
#include <sys/types.h>
#include <ui/PixelFormat.h>
-
-#include <private/ui/SharedState.h>
-#include <private/ui/LayerState.h>
-
#include <pixelflinger/pixelflinger.h>
#include <EGL/egl.h>
@@ -32,7 +28,7 @@
#include <GLES/gl.h>
#include <GLES/glext.h>
-#include "LayerBitmap.h"
+#include "Buffer.h"
#include "LayerBase.h"
#include "Transform.h"
@@ -41,12 +37,12 @@ namespace android {
// ---------------------------------------------------------------------------
class Client;
-class LayerBitmap;
class FreezeLock;
+class Buffer;
// ---------------------------------------------------------------------------
-const int NUM_BUFFERS = 2;
+const size_t NUM_BUFFERS = 2;
class Layer : public LayerBaseClient
{
@@ -56,23 +52,22 @@ public:
virtual char const* getTypeID() const { return typeID; }
virtual uint32_t getTypeInfo() const { return typeInfo; }
+
+ SharedBufferServer* lcblk;
+
+
Layer(SurfaceFlinger* flinger, DisplayID display,
const sp<Client>& client, int32_t i);
virtual ~Layer();
- inline PixelFormat pixelFormat() const {
- return frontBuffer().getPixelFormat();
- }
+ status_t setBuffers(uint32_t w, uint32_t h,
+ PixelFormat format, uint32_t flags=0);
- status_t setBuffers( uint32_t w, uint32_t h,
- PixelFormat format, uint32_t flags=0);
+ void setDrawingSize(uint32_t w, uint32_t h);
virtual void onDraw(const Region& clip) const;
- virtual void initStates(uint32_t w, uint32_t h, uint32_t flags);
- virtual void setSizeChanged(uint32_t w, uint32_t h);
virtual uint32_t doTransaction(uint32_t transactionFlags);
- virtual Point getPhysicalSize() const;
virtual void lockPageFlip(bool& recomputeVisibleRegions);
virtual void unlockPageFlip(const Transform& planeTransform, Region& outDirtyRegion);
virtual void finishPageFlip();
@@ -80,42 +75,31 @@ public:
virtual bool isSecure() const { return mSecure; }
virtual sp<Surface> createSurface() const;
virtual status_t ditch();
-
- const LayerBitmap& getBuffer(int i) const { return mBuffers[i]; }
- LayerBitmap& getBuffer(int i) { return mBuffers[i]; }
-
+
// only for debugging
- const sp<FreezeLock>& getFreezeLock() const { return mFreezeLock; }
+ inline sp<Buffer> getBuffer(int i) { return mBuffers[i]; }
+ // only for debugging
+ inline const sp<FreezeLock>& getFreezeLock() const { return mFreezeLock; }
+ // only for debugging
+ inline PixelFormat pixelFormat() const { return mFormat; }
private:
- inline const LayerBitmap&
- frontBuffer() const { return getBuffer(mFrontBufferIndex); }
- inline LayerBitmap&
- frontBuffer() { return getBuffer(mFrontBufferIndex); }
- inline const LayerBitmap&
- backBuffer() const { return getBuffer(1-mFrontBufferIndex); }
- inline LayerBitmap&
- backBuffer() { return getBuffer(1-mFrontBufferIndex); }
-
+ inline sp<Buffer> getFrontBuffer() {
+ return mBuffers[mFrontBufferIndex];
+ }
+
void reloadTexture(const Region& dirty);
- status_t resize(int32_t index, uint32_t w, uint32_t h, const char* what);
- Region post(uint32_t* oldState, bool& recomputeVisibleRegions);
- sp<SurfaceBuffer> peekBuffer(int usage);
+ sp<SurfaceBuffer> requestBuffer(int index, int usage);
void destroy();
- void scheduleBroadcast();
-
- class SurfaceLayer : public LayerBaseClient::Surface
- {
+ class SurfaceLayer : public LayerBaseClient::Surface {
public:
- SurfaceLayer(const sp<SurfaceFlinger>& flinger,
- SurfaceID id, const sp<Layer>& owner);
- ~SurfaceLayer();
-
+ SurfaceLayer(const sp<SurfaceFlinger>& flinger,
+ SurfaceID id, const sp<Layer>& owner);
+ ~SurfaceLayer();
private:
- virtual sp<SurfaceBuffer> getBuffer(int usage);
-
+ virtual sp<SurfaceBuffer> requestBuffer(int index, int usage);
sp<Layer> getOwner() const {
return static_cast<Layer*>(Surface::getOwner().get());
}
@@ -125,13 +109,20 @@ private:
sp<Surface> mSurface;
bool mSecure;
- LayerBitmap mBuffers[NUM_BUFFERS];
- Texture mTextures[NUM_BUFFERS];
int32_t mFrontBufferIndex;
bool mNeedsBlending;
- bool mResizeTransactionDone;
Region mPostedDirtyRegion;
sp<FreezeLock> mFreezeLock;
+ PixelFormat mFormat;
+ uint32_t mBufferFlags;
+
+ // protected by mLock
+ sp<Buffer> mBuffers[NUM_BUFFERS];
+ Texture mTextures[NUM_BUFFERS];
+ uint32_t mWidth;
+ uint32_t mHeight;
+
+ mutable Mutex mLock;
};
// ---------------------------------------------------------------------------
diff --git a/libs/surfaceflinger/LayerBase.cpp b/libs/surfaceflinger/LayerBase.cpp
index ec38fe9..62e41b0 100644
--- a/libs/surfaceflinger/LayerBase.cpp
+++ b/libs/surfaceflinger/LayerBase.cpp
@@ -30,7 +30,6 @@
#include "clz.h"
#include "LayerBase.h"
-#include "LayerBlur.h"
#include "SurfaceFlinger.h"
#include "DisplayHardware/DisplayHardware.h"
@@ -127,9 +126,6 @@ uint32_t LayerBase::setTransactionFlags(uint32_t flags) {
return android_atomic_or(flags, &mTransactionFlags);
}
-void LayerBase::setSizeChanged(uint32_t w, uint32_t h) {
-}
-
bool LayerBase::setPosition(int32_t x, int32_t y) {
if (mCurrentState.transform.tx() == x && mCurrentState.transform.ty() == y)
return false;
@@ -149,7 +145,6 @@ bool LayerBase::setLayer(uint32_t z) {
bool LayerBase::setSize(uint32_t w, uint32_t h) {
if (mCurrentState.w == w && mCurrentState.h == h)
return false;
- setSizeChanged(w, h);
mCurrentState.w = w;
mCurrentState.h = h;
requestTransaction();
@@ -219,21 +214,14 @@ uint32_t LayerBase::doTransaction(uint32_t flags)
return flags;
}
-Point LayerBase::getPhysicalSize() const
-{
- const Layer::State& front(drawingState());
- return Point(front.w, front.h);
-}
-
void LayerBase::validateVisibility(const Transform& planeTransform)
{
const Layer::State& s(drawingState());
const Transform tr(planeTransform * s.transform);
const bool transformed = tr.transformed();
- const Point size(getPhysicalSize());
- uint32_t w = size.x;
- uint32_t h = size.y;
+ uint32_t w = s.w;
+ uint32_t h = s.h;
tr.transform(mVertices[0], 0, 0);
tr.transform(mVertices[1], 0, h);
tr.transform(mVertices[2], w, h);
@@ -655,9 +643,7 @@ int32_t LayerBaseClient::sIdentity = 0;
LayerBaseClient::LayerBaseClient(SurfaceFlinger* flinger, DisplayID display,
const sp<Client>& client, int32_t i)
: LayerBase(flinger, display), client(client),
- lcblk( client!=0 ? &(client->ctrlblk->layers[i]) : 0 ),
- mIndex(i),
- mIdentity(uint32_t(android_atomic_inc(&sIdentity)))
+ mIndex(i), mIdentity(uint32_t(android_atomic_inc(&sIdentity)))
{
}
@@ -666,11 +652,8 @@ void LayerBaseClient::onFirstRef()
sp<Client> client(this->client.promote());
if (client != 0) {
client->bindLayer(this, mIndex);
- // Initialize this layer's control block
- memset(this->lcblk, 0, sizeof(layer_cblk_t));
- this->lcblk->identity = mIdentity;
- Region::writeEmpty(&(this->lcblk->region[0]), sizeof(flat_region_t));
- Region::writeEmpty(&(this->lcblk->region[1]), sizeof(flat_region_t));
+ // Initialize this layer's identity
+ client->ctrlblk->setIdentity(mIndex, mIdentity);
}
}
@@ -759,7 +742,7 @@ status_t LayerBaseClient::Surface::onTransact(
return BnSurface::onTransact(code, data, reply, flags);
}
-sp<SurfaceBuffer> LayerBaseClient::Surface::getBuffer(int)
+sp<SurfaceBuffer> LayerBaseClient::Surface::requestBuffer(int index, int usage)
{
return NULL;
}
diff --git a/libs/surfaceflinger/LayerBase.h b/libs/surfaceflinger/LayerBase.h
index 2168de0..78bb4bf 100644
--- a/libs/surfaceflinger/LayerBase.h
+++ b/libs/surfaceflinger/LayerBase.h
@@ -23,6 +23,7 @@
#include <EGL/egl.h>
#include <EGL/eglext.h>
+#include <private/ui/SharedBufferStack.h>
#include <private/ui/LayerState.h>
#include <utils/RefBase.h>
@@ -137,11 +138,6 @@ public:
virtual void initStates(uint32_t w, uint32_t h, uint32_t flags);
/**
- * setSizeChanged - called when the *current* state's size is changed.
- */
- virtual void setSizeChanged(uint32_t w, uint32_t h);
-
- /**
* doTransaction - process the transaction. This is a good place to figure
* out which attributes of the surface have changed.
*/
@@ -161,13 +157,6 @@ public:
virtual void setCoveredRegion(const Region& coveredRegion);
/**
- * getPhysicalSize - returns the physical size of the drawing state of
- * the surface. If the surface is backed by a bitmap, this is the size of
- * the bitmap (as opposed to the size of the drawing state).
- */
- virtual Point getPhysicalSize() const;
-
- /**
* validateVisibility - cache a bunch of things
*/
virtual void validateVisibility(const Transform& globalTransform);
@@ -308,8 +297,8 @@ public:
virtual ~LayerBaseClient();
virtual void onFirstRef();
- wp<Client> client;
- layer_cblk_t* const lcblk;
+ wp<Client> client;
+// SharedBufferServer* lcblk;
inline uint32_t getIdentity() const { return mIdentity; }
inline int32_t clientIndex() const { return mIndex; }
@@ -336,7 +325,7 @@ public:
sp<LayerBaseClient> getOwner() const;
private:
- virtual sp<SurfaceBuffer> getBuffer(int usage);
+ virtual sp<SurfaceBuffer> requestBuffer(int index, int usage);
virtual status_t registerBuffers(const ISurface::BufferHeap& buffers);
virtual void postBuffer(ssize_t offset);
virtual void unregisterBuffers();
diff --git a/libs/surfaceflinger/LayerBuffer.cpp b/libs/surfaceflinger/LayerBuffer.cpp
index 8a55a3f..433b48e 100644
--- a/libs/surfaceflinger/LayerBuffer.cpp
+++ b/libs/surfaceflinger/LayerBuffer.cpp
@@ -28,6 +28,7 @@
#include <hardware/copybit.h>
+#include "Buffer.h"
#include "BufferAllocator.h"
#include "LayerBuffer.h"
#include "SurfaceFlinger.h"
@@ -58,7 +59,7 @@ LayerBuffer::~LayerBuffer()
void LayerBuffer::onFirstRef()
{
LayerBaseClient::onFirstRef();
- mSurface = new SurfaceBuffer(mFlinger, clientIndex(),
+ mSurface = new SurfaceLayerBuffer(mFlinger, clientIndex(),
const_cast<LayerBuffer *>(this));
}
@@ -181,21 +182,21 @@ sp<LayerBuffer::Source> LayerBuffer::clearSource() {
}
// ============================================================================
-// LayerBuffer::SurfaceBuffer
+// LayerBuffer::SurfaceLayerBuffer
// ============================================================================
-LayerBuffer::SurfaceBuffer::SurfaceBuffer(const sp<SurfaceFlinger>& flinger,
+LayerBuffer::SurfaceLayerBuffer::SurfaceLayerBuffer(const sp<SurfaceFlinger>& flinger,
SurfaceID id, const sp<LayerBuffer>& owner)
: LayerBaseClient::Surface(flinger, id, owner->getIdentity(), owner)
{
}
-LayerBuffer::SurfaceBuffer::~SurfaceBuffer()
+LayerBuffer::SurfaceLayerBuffer::~SurfaceLayerBuffer()
{
unregisterBuffers();
}
-status_t LayerBuffer::SurfaceBuffer::registerBuffers(
+status_t LayerBuffer::SurfaceLayerBuffer::registerBuffers(
const ISurface::BufferHeap& buffers)
{
sp<LayerBuffer> owner(getOwner());
@@ -204,21 +205,21 @@ status_t LayerBuffer::SurfaceBuffer::registerBuffers(
return NO_INIT;
}
-void LayerBuffer::SurfaceBuffer::postBuffer(ssize_t offset)
+void LayerBuffer::SurfaceLayerBuffer::postBuffer(ssize_t offset)
{
sp<LayerBuffer> owner(getOwner());
if (owner != 0)
owner->postBuffer(offset);
}
-void LayerBuffer::SurfaceBuffer::unregisterBuffers()
+void LayerBuffer::SurfaceLayerBuffer::unregisterBuffers()
{
sp<LayerBuffer> owner(getOwner());
if (owner != 0)
owner->unregisterBuffers();
}
-sp<OverlayRef> LayerBuffer::SurfaceBuffer::createOverlay(
+sp<OverlayRef> LayerBuffer::SurfaceLayerBuffer::createOverlay(
uint32_t w, uint32_t h, int32_t format) {
sp<OverlayRef> result;
sp<LayerBuffer> owner(getOwner());
@@ -462,8 +463,8 @@ void LayerBuffer::BufferSource::onDraw(const Region& clip) const
const int tmp_h = floorf(src_height * yscale);
if (mTempBitmap==0 ||
- mTempBitmap->getWidth() < tmp_w ||
- mTempBitmap->getHeight() < tmp_h) {
+ mTempBitmap->getWidth() < size_t(tmp_w) ||
+ mTempBitmap->getHeight() < size_t(tmp_h)) {
mTempBitmap.clear();
mTempBitmap = new android::Buffer(
tmp_w, tmp_h, src.img.format,
diff --git a/libs/surfaceflinger/LayerBuffer.h b/libs/surfaceflinger/LayerBuffer.h
index 8057219..e539f68 100644
--- a/libs/surfaceflinger/LayerBuffer.h
+++ b/libs/surfaceflinger/LayerBuffer.h
@@ -24,7 +24,6 @@
#include <private/ui/LayerState.h>
#include "LayerBase.h"
-#include "LayerBitmap.h"
struct copybit_device_t;
@@ -32,9 +31,12 @@ namespace android {
// ---------------------------------------------------------------------------
+class Buffer;
class Region;
class OverlayRef;
+// ---------------------------------------------------------------------------
+
class LayerBuffer : public LayerBaseClient
{
class Source : public LightRefBase<Source> {
@@ -179,12 +181,12 @@ private:
};
- class SurfaceBuffer : public LayerBaseClient::Surface
+ class SurfaceLayerBuffer : public LayerBaseClient::Surface
{
public:
- SurfaceBuffer(const sp<SurfaceFlinger>& flinger,
+ SurfaceLayerBuffer(const sp<SurfaceFlinger>& flinger,
SurfaceID id, const sp<LayerBuffer>& owner);
- virtual ~SurfaceBuffer();
+ virtual ~SurfaceLayerBuffer();
virtual status_t registerBuffers(const ISurface::BufferHeap& buffers);
virtual void postBuffer(ssize_t offset);
diff --git a/libs/surfaceflinger/LayerDim.cpp b/libs/surfaceflinger/LayerDim.cpp
index f613767..8ba0a9d 100644
--- a/libs/surfaceflinger/LayerDim.cpp
+++ b/libs/surfaceflinger/LayerDim.cpp
@@ -21,6 +21,7 @@
#include <utils/Errors.h>
#include <utils/Log.h>
+#include "Buffer.h"
#include "BufferAllocator.h"
#include "LayerDim.h"
#include "SurfaceFlinger.h"
diff --git a/libs/surfaceflinger/LayerDim.h b/libs/surfaceflinger/LayerDim.h
index 33bd49d..d4672a1 100644
--- a/libs/surfaceflinger/LayerDim.h
+++ b/libs/surfaceflinger/LayerDim.h
@@ -24,12 +24,11 @@
#include <EGL/eglext.h>
#include "LayerBase.h"
-#include "LayerBitmap.h"
-
-namespace android {
// ---------------------------------------------------------------------------
+namespace android {
+
class LayerDim : public LayerBaseClient
{
static bool sUseTexture;
diff --git a/libs/surfaceflinger/SurfaceFlinger.cpp b/libs/surfaceflinger/SurfaceFlinger.cpp
index c78921a..b368db6 100644
--- a/libs/surfaceflinger/SurfaceFlinger.cpp
+++ b/libs/surfaceflinger/SurfaceFlinger.cpp
@@ -44,12 +44,12 @@
#include <GLES/gl.h>
#include "clz.h"
+#include "Buffer.h"
#include "BufferAllocator.h"
#include "Layer.h"
#include "LayerBlur.h"
#include "LayerBuffer.h"
#include "LayerDim.h"
-#include "LayerBitmap.h"
#include "SurfaceFlinger.h"
#include "DisplayHardware/DisplayHardware.h"
@@ -173,12 +173,12 @@ SurfaceFlinger::SurfaceFlinger()
: BnSurfaceComposer(), Thread(false),
mTransactionFlags(0),
mTransactionCount(0),
+ mResizeTransationPending(false),
mLayersRemoved(false),
mBootTime(systemTime()),
mHardwareTest("android.permission.HARDWARE_TEST"),
mAccessSurfaceFlinger("android.permission.ACCESS_SURFACE_FLINGER"),
mDump("android.permission.DUMP"),
- mLastScheduledBroadcast(NULL),
mVisibleRegionsDirty(false),
mDeferReleaseConsole(false),
mFreezeDisplay(false),
@@ -497,13 +497,11 @@ bool SurfaceFlinger::threadLoop()
// release the clients before we flip ('cause flip might block)
unlockClients();
- executeScheduledBroadcasts();
postFramebuffer();
} else {
// pretend we did the post
unlockClients();
- executeScheduledBroadcasts();
usleep(16667); // 60 fps period
}
return true;
@@ -773,7 +771,8 @@ void SurfaceFlinger::computeVisibleRegions(
void SurfaceFlinger::commitTransaction()
{
mDrawingState = mCurrentState;
- mTransactionCV.signal();
+ mResizeTransationPending = false;
+ mTransactionCV.broadcast();
}
void SurfaceFlinger::handlePageFlip()
@@ -910,37 +909,6 @@ void SurfaceFlinger::unlockClients()
}
}
-void SurfaceFlinger::scheduleBroadcast(const sp<Client>& client)
-{
- if (mLastScheduledBroadcast != client) {
- mLastScheduledBroadcast = client;
- mScheduledBroadcasts.add(client);
- }
-}
-
-void SurfaceFlinger::executeScheduledBroadcasts()
-{
- SortedVector< wp<Client> >& list(mScheduledBroadcasts);
- size_t count = list.size();
- while (count--) {
- sp<Client> client = list[count].promote();
- if (client != 0) {
- per_client_cblk_t* const cblk = client->ctrlblk;
- if (cblk->lock.tryLock() == NO_ERROR) {
- cblk->cv.broadcast();
- list.removeAt(count);
- cblk->lock.unlock();
- } else {
- // schedule another round
- LOGW("executeScheduledBroadcasts() skipped, "
- "contention on the client. We'll try again later...");
- signalDelayedEvent(ms2ns(4));
- }
- }
- }
- mLastScheduledBroadcast = 0;
-}
-
void SurfaceFlinger::debugFlashRegions()
{
const DisplayHardware& hw(graphicPlane(0).displayHardware());
@@ -1129,18 +1097,10 @@ void SurfaceFlinger::free_resources_l()
mLayersRemoved = false;
// free resources associated with disconnected clients
- SortedVector< wp<Client> >& scheduledBroadcasts(mScheduledBroadcasts);
Vector< sp<Client> >& disconnectedClients(mDisconnectedClients);
const size_t count = disconnectedClients.size();
for (size_t i=0 ; i<count ; i++) {
sp<Client> client = disconnectedClients[i];
- // if this client is the scheduled broadcast list,
- // remove it from there (and we don't need to signal it
- // since it is dead).
- int32_t index = scheduledBroadcasts.indexOf(client);
- if (index >= 0) {
- scheduledBroadcasts.removeItemsAt(index);
- }
mTokens.release(client->cid);
}
disconnectedClients.clear();
@@ -1173,6 +1133,13 @@ void SurfaceFlinger::closeGlobalTransaction()
{
if (android_atomic_dec(&mTransactionCount) == 1) {
signalEvent();
+
+ // if there is a transaction with a resize, wait for it to
+ // take effect before returning.
+ Mutex::Autolock _l(mStateLock);
+ while (mResizeTransationPending) {
+ mTransactionCV.wait(mStateLock);
+ }
}
}
@@ -1424,8 +1391,10 @@ status_t SurfaceFlinger::setClientState(
}
}
if (what & eSizeChanged) {
- if (layer->setSize(s.w, s.h))
+ if (layer->setSize(s.w, s.h)) {
flags |= eTraversalNeeded;
+ mResizeTransationPending = true;
+ }
}
if (what & eAlphaChanged) {
if (layer->setAlpha(uint8_t(255.0f*s.alpha+0.5f)))
@@ -1543,28 +1512,27 @@ status_t SurfaceFlinger::dump(int fd, const Vector<String16>& args)
"id=0x%08x, client=0x%08x, identity=%u\n",
lbc->clientIndex(), client.get() ? client->cid : 0,
lbc->getIdentity());
+
+ result.append(buffer);
+ buffer[0] = 0;
}
- result.append(buffer);
- buffer[0] = 0;
/*** Layer ***/
sp<Layer> l = LayerBase::dynamicCast< Layer* >(layer.get());
if (l != 0) {
- const LayerBitmap& buf0(l->getBuffer(0));
- const LayerBitmap& buf1(l->getBuffer(1));
+ result.append( l->lcblk->dump(" ") );
+ sp<const Buffer> buf0(l->getBuffer(0));
+ sp<const Buffer> buf1(l->getBuffer(1));
snprintf(buffer, SIZE,
" "
"format=%2d, [%3ux%3u:%3u] [%3ux%3u:%3u],"
- " freezeLock=%p, swapState=0x%08x\n",
+ " freezeLock=%p\n",
l->pixelFormat(),
- buf0.getWidth(), buf0.getHeight(),
- buf0.getBuffer()->getStride(),
- buf1.getWidth(), buf1.getHeight(),
- buf1.getBuffer()->getStride(),
- l->getFreezeLock().get(),
- l->lcblk->swapState);
+ buf0->getWidth(), buf0->getHeight(), buf0->getStride(),
+ buf1->getWidth(), buf1->getHeight(), buf1->getStride(),
+ l->getFreezeLock().get());
+ result.append(buffer);
+ buffer[0] = 0;
}
- result.append(buffer);
- buffer[0] = 0;
s.transparentRegion.dump(result, "transparentRegion");
layer->transparentRegionScreen.dump(result, "transparentRegionScreen");
layer->visibleRegionScreen.dump(result, "visibleRegionScreen");
@@ -1657,8 +1625,12 @@ status_t SurfaceFlinger::onTransact(
const DisplayHardware& hw(graphicPlane(0).displayHardware());
mDirtyRegion.set(hw.bounds()); // careful that's not thread-safe
signalEvent();
+ return NO_ERROR;
+ }
+ case 1005:{ // force transaction
+ setTransactionFlags(eTransactionNeeded|eTraversalNeeded);
+ return NO_ERROR;
}
- return NO_ERROR;
case 1007: // set mFreezeCount
mFreezeCount = data.readInt32();
return NO_ERROR;
@@ -1688,21 +1660,20 @@ Client::Client(ClientID clientID, const sp<SurfaceFlinger>& flinger)
: ctrlblk(0), cid(clientID), mPid(0), mBitmap(0), mFlinger(flinger)
{
const int pgsize = getpagesize();
- const int cblksize = ((sizeof(per_client_cblk_t)+(pgsize-1))&~(pgsize-1));
+ const int cblksize = ((sizeof(SharedClient)+(pgsize-1))&~(pgsize-1));
mCblkHeap = new MemoryHeapBase(cblksize, 0,
"SurfaceFlinger Client control-block");
- ctrlblk = static_cast<per_client_cblk_t *>(mCblkHeap->getBase());
+ ctrlblk = static_cast<SharedClient *>(mCblkHeap->getBase());
if (ctrlblk) { // construct the shared structure in-place.
- new(ctrlblk) per_client_cblk_t;
+ new(ctrlblk) SharedClient;
}
}
Client::~Client() {
if (ctrlblk) {
- const int pgsize = getpagesize();
- ctrlblk->~per_client_cblk_t(); // destroy our shared-structure.
+ ctrlblk->~SharedClient(); // destroy our shared-structure.
}
}
diff --git a/libs/surfaceflinger/SurfaceFlinger.h b/libs/surfaceflinger/SurfaceFlinger.h
index 69e2f2e..f207f85 100644
--- a/libs/surfaceflinger/SurfaceFlinger.h
+++ b/libs/surfaceflinger/SurfaceFlinger.h
@@ -34,7 +34,7 @@
#include <ui/ISurfaceComposer.h>
#include <ui/ISurfaceFlingerClient.h>
-#include <private/ui/SharedState.h>
+#include <private/ui/SharedBufferStack.h>
#include <private/ui/LayerState.h>
#include "Barrier.h"
@@ -87,7 +87,7 @@ public:
}
// pointer to this client's control block
- per_client_cblk_t* ctrlblk;
+ SharedClient* ctrlblk;
ClientID cid;
@@ -268,8 +268,6 @@ private:
bool lockPageFlip(const LayerVector& currentLayers);
void unlockPageFlip(const LayerVector& currentLayers);
void handleRepaint();
- void scheduleBroadcast(const sp<Client>& client);
- void executeScheduledBroadcasts();
void postFramebuffer();
void composeSurfaces(const Region& dirty);
void unlockClients();
@@ -313,6 +311,7 @@ private:
volatile int32_t mTransactionFlags;
volatile int32_t mTransactionCount;
Condition mTransactionCV;
+ bool mResizeTransationPending;
// protected by mStateLock (but we could use another lock)
Tokenizer mTokens;
@@ -337,8 +336,6 @@ private:
Region mDirtyRegionRemovedLayer;
Region mInvalidRegion;
Region mWormholeRegion;
- wp<Client> mLastScheduledBroadcast;
- SortedVector< wp<Client> > mScheduledBroadcasts;
bool mVisibleRegionsDirty;
bool mDeferReleaseConsole;
bool mFreezeDisplay;