split surface management from surface's buffers management
Change-Id: If3c5655d1231f8f0c49ba68f972b1b20c93b3f87
diff --git a/libs/surfaceflinger/Layer.cpp b/libs/surfaceflinger/Layer.cpp
index 85149f5..a94fdd4 100644
--- a/libs/surfaceflinger/Layer.cpp
+++ b/libs/surfaceflinger/Layer.cpp
@@ -50,10 +50,9 @@
Layer::Layer(SurfaceFlinger* flinger,
DisplayID display, const sp<Client>& client)
: LayerBaseClient(flinger, display, client),
- lcblk(NULL),
- mSecure(false),
mNeedsBlending(true),
mNeedsDithering(false),
+ mSecure(false),
mTextureManager(mFlags),
mBufferManager(mTextureManager),
mWidth(0), mHeight(0), mFixedSize(false)
@@ -66,32 +65,43 @@
EGLDisplay dpy(mFlinger->graphicPlane(0).getEGLDisplay());
mBufferManager.destroy(dpy);
- // the actual buffers will be destroyed here
- delete lcblk;
+ // we can use getUserClientUnsafe here because we know we're
+ // single-threaded at that point.
+ sp<UserClient> ourClient(mUserClientRef.getUserClientUnsafe());
+ if (ourClient != 0) {
+ ourClient->detachLayer(this);
+ }
}
-// TODO: get rid of this
-void Layer::setToken(int32_t token)
+status_t Layer::setToken(const sp<UserClient>& userClient,
+ SharedClient* sharedClient, int32_t token)
{
- sp<Client> ourClient(client.promote());
-
- mToken = token;
-
- // no OpenGL operation is possible here, since we might not be
- // in the OpenGL thread.
- lcblk = new SharedBufferServer(
- ourClient->ctrlblk, token, mBufferManager.getDefaultBufferCount(),
+ SharedBufferServer* lcblk = new SharedBufferServer(
+ sharedClient, token, mBufferManager.getDefaultBufferCount(),
getIdentity());
- mBufferManager.setActiveBufferIndex( lcblk->getFrontBuffer() );
+ status_t err = mUserClientRef.setToken(userClient, lcblk, token);
+ if (err != NO_ERROR) {
+ LOGE("ClientRef::setToken(%p, %p, %u) failed",
+ userClient.get(), lcblk, token);
+ delete lcblk;
+ }
+
+ return err;
+}
+
+int32_t Layer::getToken() const
+{
+ return mUserClientRef.getToken();
}
// called with SurfaceFlinger::mStateLock as soon as the layer is entered
// in the purgatory list
void Layer::onRemoved()
{
- sp<Client> ourClient(client.promote());
- if (ourClient != 0) {
+ ClientRef::Access sharedClient(mUserClientRef);
+ SharedBufferServer* lcblk(sharedClient.get());
+ if (lcblk) {
// wake up the condition
lcblk->setStatus(NO_INIT);
}
@@ -237,10 +247,9 @@
status_t Layer::setBufferCount(int bufferCount)
{
- // Ensures our client doesn't go away while we're accessing
- // the shared area.
- sp<Client> ourClient(client.promote());
- if (ourClient == 0) {
+ ClientRef::Access sharedClient(mUserClientRef);
+ SharedBufferServer* lcblk(sharedClient.get());
+ if (!lcblk) {
// oops, the client is already gone
return DEAD_OBJECT;
}
@@ -259,7 +268,7 @@
{
sp<GraphicBuffer> buffer;
- if ((reqWidth | reqHeight | reqFormat) < 0)
+ if (int32_t(reqWidth | reqHeight | reqFormat) < 0)
return buffer;
if ((!reqWidth && reqHeight) || (reqWidth && !reqHeight))
@@ -267,8 +276,9 @@
// this ensures our client doesn't go away while we're accessing
// the shared area.
- sp<Client> ourClient(client.promote());
- if (ourClient == 0) {
+ ClientRef::Access sharedClient(mUserClientRef);
+ SharedBufferServer* lcblk(sharedClient.get());
+ if (!lcblk) {
// oops, the client is already gone
return buffer;
}
@@ -403,8 +413,9 @@
// a buffer, it'll get the new size.
setBufferSize(temp.requested_w, temp.requested_h);
- sp<Client> ourClient(client.promote());
- if (ourClient != 0) {
+ ClientRef::Access sharedClient(mUserClientRef);
+ SharedBufferServer* lcblk(sharedClient.get());
+ if (lcblk) {
// all buffers need reallocation
lcblk->reallocateAll();
}
@@ -442,8 +453,9 @@
void Layer::lockPageFlip(bool& recomputeVisibleRegions)
{
- sp<Client> ourClient(client.promote());
- if (ourClient == 0) {
+ ClientRef::Access sharedClient(mUserClientRef);
+ SharedBufferServer* lcblk(sharedClient.get());
+ if (!lcblk) {
// client died
recomputeVisibleRegions = true;
return;
@@ -458,14 +470,14 @@
}
if (buf < NO_ERROR) {
- LOGE("retireAndLock() buffer index (%d) out of range", buf);
+ LOGE("retireAndLock() buffer index (%d) out of range", int(buf));
mPostedDirtyRegion.clear();
return;
}
// we retired a buffer, which becomes the new front buffer
if (mBufferManager.setActiveBufferIndex(buf) < NO_ERROR) {
- LOGE("retireAndLock() buffer index (%d) out of range", buf);
+ LOGE("retireAndLock() buffer index (%d) out of range", int(buf));
mPostedDirtyRegion.clear();
return;
}
@@ -560,11 +572,16 @@
void Layer::finishPageFlip()
{
- sp<Client> ourClient(client.promote());
- if (ourClient != 0) {
+ ClientRef::Access sharedClient(mUserClientRef);
+ SharedBufferServer* lcblk(sharedClient.get());
+ if (lcblk) {
int buf = mBufferManager.getActiveBufferIndex();
- status_t err = lcblk->unlock( buf );
- LOGE_IF(err!=NO_ERROR, "layer %p, buffer=%d wasn't locked!", this, buf);
+ if (buf >= 0) {
+ status_t err = lcblk->unlock( buf );
+ LOGE_IF(err!=NO_ERROR,
+ "layer %p, buffer=%d wasn't locked!",
+ this, buf);
+ }
}
}
@@ -573,8 +590,15 @@
{
LayerBaseClient::dump(result, buffer, SIZE);
- SharedBufferStack::Statistics stats = lcblk->getStats();
- result.append( lcblk->dump(" ") );
+ ClientRef::Access sharedClient(mUserClientRef);
+ SharedBufferServer* lcblk(sharedClient.get());
+ uint32_t totalTime = 0;
+ if (lcblk) {
+ SharedBufferStack::Statistics stats = lcblk->getStats();
+ totalTime= stats.totalTime;
+ result.append( lcblk->dump(" ") );
+ }
+
sp<const GraphicBuffer> buf0(getBuffer(0));
sp<const GraphicBuffer> buf1(getBuffer(1));
uint32_t w0=0, h0=0, s0=0;
@@ -593,18 +617,59 @@
" "
"format=%2d, [%3ux%3u:%3u] [%3ux%3u:%3u],"
" freezeLock=%p, dq-q-time=%u us\n",
- pixelFormat(),
- w0, h0, s0, w1, h1, s1,
- getFreezeLock().get(), stats.totalTime);
+ mFormat, w0, h0, s0, w1, h1, s1,
+ getFreezeLock().get(), totalTime);
result.append(buffer);
}
// ---------------------------------------------------------------------------
+Layer::ClientRef::ClientRef()
+ : mToken(-1) {
+}
+
+Layer::ClientRef::~ClientRef() {
+ delete lcblk;
+}
+
+int32_t Layer::ClientRef::getToken() const {
+ Mutex::Autolock _l(mLock);
+ return mToken;
+}
+
+status_t Layer::ClientRef::setToken(const sp<UserClient>& uc,
+ SharedBufferServer* sharedClient, int32_t token) {
+ Mutex::Autolock _l(mLock);
+ if (mToken >= 0)
+ return INVALID_OPERATION;
+ mUserClient = uc;
+ mToken = token;
+ lcblk = sharedClient;
+ return NO_ERROR;
+}
+
+sp<UserClient> Layer::ClientRef::getUserClientUnsafe() const {
+ return mUserClient.promote();
+}
+
+// this class gives us access to SharedBufferServer safely
+// it makes sure the UserClient (and its associated shared memory)
+// won't go away while we're accessing it.
+Layer::ClientRef::Access::Access(const ClientRef& ref)
+ : lcblk(0)
+{
+ Mutex::Autolock _l(ref.mLock);
+ mUserClientStrongRef = ref.mUserClient.promote();
+ if (mUserClientStrongRef != 0)
+ lcblk = ref.lcblk;
+}
+
+// ---------------------------------------------------------------------------
+
Layer::BufferManager::BufferManager(TextureManager& tm)
: mNumBuffers(NUM_BUFFERS), mTextureManager(tm),
- mActiveBuffer(0), mFailover(false)
+ mActiveBuffer(-1), mFailover(false)
{
}
@@ -625,7 +690,6 @@
}
status_t Layer::BufferManager::setActiveBufferIndex(size_t index) {
- // TODO: need to validate 'index'
mActiveBuffer = index;
return NO_ERROR;
}
@@ -636,7 +700,7 @@
Texture Layer::BufferManager::getActiveTexture() const {
Texture res;
- if (mFailover) {
+ if (mFailover || mActiveBuffer<0) {
res = mFailoverTexture;
} else {
static_cast<Image&>(res) = mBufferData[mActiveBuffer].texture;
@@ -645,10 +709,14 @@
}
sp<GraphicBuffer> Layer::BufferManager::getActiveBuffer() const {
- const size_t activeBuffer = mActiveBuffer;
- BufferData const * const buffers = mBufferData;
- Mutex::Autolock _l(mLock);
- return buffers[activeBuffer].buffer;
+ sp<GraphicBuffer> result;
+ const ssize_t activeBuffer = mActiveBuffer;
+ if (activeBuffer >= 0) {
+ BufferData const * const buffers = mBufferData;
+ Mutex::Autolock _l(mLock);
+ result = buffers[activeBuffer].buffer;
+ }
+ return result;
}
sp<GraphicBuffer> Layer::BufferManager::detachBuffer(size_t index)
@@ -692,19 +760,22 @@
status_t Layer::BufferManager::initEglImage(EGLDisplay dpy,
const sp<GraphicBuffer>& buffer)
{
- size_t index = mActiveBuffer;
- Image& texture(mBufferData[index].texture);
- status_t err = mTextureManager.initEglImage(&texture, dpy, buffer);
- // if EGLImage fails, we switch to regular texture mode, and we
- // free all resources associated with using EGLImages.
- if (err == NO_ERROR) {
- mFailover = false;
- destroyTexture(&mFailoverTexture, dpy);
- } else {
- mFailover = true;
- const size_t num = mNumBuffers;
- for (size_t i=0 ; i<num ; i++) {
- destroyTexture(&mBufferData[i].texture, dpy);
+ status_t err = NO_INIT;
+ ssize_t index = mActiveBuffer;
+ if (index >= 0) {
+ Image& texture(mBufferData[index].texture);
+ err = mTextureManager.initEglImage(&texture, dpy, buffer);
+ // if EGLImage fails, we switch to regular texture mode, and we
+ // free all resources associated with using EGLImages.
+ if (err == NO_ERROR) {
+ mFailover = false;
+ destroyTexture(&mFailoverTexture, dpy);
+ } else {
+ mFailover = true;
+ const size_t num = mNumBuffers;
+ for (size_t i=0 ; i<num ; i++) {
+ destroyTexture(&mBufferData[i].texture, dpy);
+ }
}
}
return err;