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
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 @@
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
similarity index 60%
rename from libs/surfaceflinger/LayerBitmap.cpp
rename to 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 @@
// 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 @@
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 @@
*
*/
- 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 @@
}
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 @@
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/Buffer.h b/libs/surfaceflinger/Buffer.h
new file mode 100644
index 0000000..79f4eeb
--- /dev/null
+++ b/libs/surfaceflinger/Buffer.h
@@ -0,0 +1,94 @@
+/*
+ * Copyright (C) 2007 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.
+ */
+
+#ifndef ANDROID_LAYER_BITMAP_H
+#define ANDROID_LAYER_BITMAP_H
+
+#include <stdint.h>
+#include <sys/types.h>
+
+#include <hardware/gralloc.h>
+
+#include <utils/Atomic.h>
+
+#include <ui/PixelFormat.h>
+#include <ui/Rect.h>
+#include <ui/Surface.h>
+
+#include <pixelflinger/pixelflinger.h>
+
+#include <private/ui/SharedBufferStack.h>
+#include <private/ui/SurfaceBuffer.h>
+
+class copybit_image_t;
+struct android_native_buffer_t;
+
+namespace android {
+
+// ===========================================================================
+// Buffer
+// ===========================================================================
+
+class NativeBuffer;
+
+class Buffer : public SurfaceBuffer
+{
+public:
+ enum {
+ DONT_CLEAR = 0x00000001,
+ SECURE = 0x00000004
+ };
+
+ Buffer();
+
+ // creates w * h buffer
+ Buffer(uint32_t w, uint32_t h, PixelFormat format,
+ uint32_t reqUsage, uint32_t flags = 0);
+
+ // return status
+ status_t initCheck() const;
+
+ uint32_t getWidth() const { return width; }
+ uint32_t getHeight() const { return height; }
+ uint32_t getStride() const { return stride; }
+ uint32_t getUsage() const { return usage; }
+ PixelFormat getPixelFormat() const { return format; }
+ Rect getBounds() const { return Rect(width, height); }
+
+ status_t lock(GGLSurface* surface, uint32_t usage);
+
+ 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);
+ virtual ~Buffer();
+ Buffer& operator = (const Buffer& rhs);
+ const Buffer& operator = (const Buffer& rhs) const;
+
+ status_t initSize(uint32_t w, uint32_t h, PixelFormat format,
+ uint32_t reqUsage, uint32_t flags);
+
+ ssize_t mInitCheck;
+ uint32_t mVStride;
+};
+
+}; // namespace android
+
+#endif // ANDROID_LAYER_BITMAP_H
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 @@
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 @@
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 @@
*/
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 @@
*/
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 @@
// ---------------------------------------------------------------------------
-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 @@
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 @@
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 @@
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,195 +199,113 @@
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;
- }
-
- 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?
+ 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();
+ }
+
+ 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 {
+ LOGD_IF(DEBUG_RESIZE,
+ "Layer::requestBuffer(this=%p), index=%d, w=%d, h=%d",
+ this, index, w, h);
+ }
+
+ if (err == NO_ERROR && buffer->handle != 0) {
// 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);
+ mTextures[index].dirty = true;
}
return buffer;
}
-void Layer::scheduleBroadcast()
-{
- sp<Client> ourClient(client.promote());
- if (ourClient != 0) {
- mFlinger->scheduleBroadcast(ourClient);
- }
-}
-
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()));
+ 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;
+ // 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);
- // 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();
- }
- }
+ // 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 @@
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::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;
+ // get the dirty region
+ sp<Buffer> newFrontBuffer(getBuffer(buf));
+ const Region dirty(lcblk->getDirtyRegion(buf));
+ mPostedDirtyRegion = dirty.intersect( newFrontBuffer->getBounds() );
- // ... post the new front-buffer
- Region dirty(lcblk->region + index);
- dirty.andSelf(frontBuffer().getBounds());
+ // FIXME: signal an event if we have more buffers waiting
+ // mFlinger->signalEvent();
- //LOGD("Did post oldValue=%08lx, newValue=%08lx, mFrontBufferIndex=%u\n",
- // oldValue, newValue, mFrontBufferIndex);
- //dirty.dump("dirty");
-
- 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;
- }
- }
-
- 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 @@
// 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 @@
{
}
-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 @@
// ---------------------------------------------------------------------------
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 @@
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 @@
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 @@
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 @@
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::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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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/LayerBitmap.h b/libs/surfaceflinger/LayerBitmap.h
deleted file mode 100644
index 87e8f42..0000000
--- a/libs/surfaceflinger/LayerBitmap.h
+++ /dev/null
@@ -1,134 +0,0 @@
-/*
- * Copyright (C) 2007 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.
- */
-
-#ifndef ANDROID_LAYER_BITMAP_H
-#define ANDROID_LAYER_BITMAP_H
-
-#include <stdint.h>
-#include <sys/types.h>
-
-#include <hardware/gralloc.h>
-
-#include <utils/Atomic.h>
-
-#include <ui/PixelFormat.h>
-#include <ui/Rect.h>
-#include <ui/Surface.h>
-
-#include <pixelflinger/pixelflinger.h>
-
-#include <private/ui/SharedState.h>
-#include <private/ui/SurfaceBuffer.h>
-
-class copybit_image_t;
-struct android_native_buffer_t;
-
-namespace android {
-
-// ---------------------------------------------------------------------------
-class IMemory;
-class LayerBitmap;
-
-// ===========================================================================
-// Buffer
-// ===========================================================================
-
-class NativeBuffer;
-
-class Buffer : public SurfaceBuffer
-{
-public:
- enum {
- DONT_CLEAR = 0x00000001,
- SECURE = 0x00000004
- };
-
- // creates w * h buffer
- Buffer(uint32_t w, uint32_t h, PixelFormat format,
- uint32_t reqUsage, uint32_t flags = 0);
-
- // return status
- status_t initCheck() const;
-
- uint32_t getWidth() const { return width; }
- uint32_t getHeight() const { return height; }
- uint32_t getStride() const { return stride; }
- uint32_t getUsage() const { return usage; }
- PixelFormat getPixelFormat() const { return format; }
- Rect getBounds() const { return Rect(width, height); }
-
- status_t lock(GGLSurface* surface, uint32_t usage);
-
- android_native_buffer_t* getNativeBuffer() const;
-
-private:
- friend class LightRefBase<Buffer>;
- Buffer(const Buffer& rhs);
- virtual ~Buffer();
- 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
-// ===========================================================================
-
-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;
-};
-
-}; // namespace android
-
-#endif // ANDROID_LAYER_BITMAP_H
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 @@
void LayerBuffer::onFirstRef()
{
LayerBaseClient::onFirstRef();
- mSurface = new SurfaceBuffer(mFlinger, clientIndex(),
+ mSurface = new SurfaceLayerBuffer(mFlinger, clientIndex(),
const_cast<LayerBuffer *>(this));
}
@@ -181,21 +182,21 @@
}
// ============================================================================
-// 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 @@
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 @@
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 @@
// ---------------------------------------------------------------------------
+class Buffer;
class Region;
class OverlayRef;
+// ---------------------------------------------------------------------------
+
class LayerBuffer : public LayerBaseClient
{
class Source : public LightRefBase<Source> {
@@ -179,12 +181,12 @@
};
- 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 @@
: 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 @@
// 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::commitTransaction()
{
mDrawingState = mCurrentState;
- mTransactionCV.signal();
+ mResizeTransationPending = false;
+ mTransactionCV.broadcast();
}
void SurfaceFlinger::handlePageFlip()
@@ -910,37 +909,6 @@
}
}
-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 @@
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 @@
{
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 @@
}
}
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 @@
"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 @@
const DisplayHardware& hw(graphicPlane(0).displayHardware());
mDirtyRegion.set(hw.bounds()); // careful that's not thread-safe
signalEvent();
+ return NO_ERROR;
}
- return NO_ERROR;
+ case 1005:{ // force transaction
+ setTransactionFlags(eTransactionNeeded|eTraversalNeeded);
+ return NO_ERROR;
+ }
case 1007: // set mFreezeCount
mFreezeCount = data.readInt32();
return NO_ERROR;
@@ -1688,21 +1660,20 @@
: 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 @@
}
// pointer to this client's control block
- per_client_cblk_t* ctrlblk;
+ SharedClient* ctrlblk;
ClientID cid;
@@ -268,8 +268,6 @@
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 @@
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 @@
Region mDirtyRegionRemovedLayer;
Region mInvalidRegion;
Region mWormholeRegion;
- wp<Client> mLastScheduledBroadcast;
- SortedVector< wp<Client> > mScheduledBroadcasts;
bool mVisibleRegionsDirty;
bool mDeferReleaseConsole;
bool mFreezeDisplay;