summaryrefslogtreecommitdiffstats
path: root/libs/surfaceflinger/SurfaceFlinger.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'libs/surfaceflinger/SurfaceFlinger.cpp')
-rw-r--r--libs/surfaceflinger/SurfaceFlinger.cpp548
1 files changed, 254 insertions, 294 deletions
diff --git a/libs/surfaceflinger/SurfaceFlinger.cpp b/libs/surfaceflinger/SurfaceFlinger.cpp
index 0722fda..4dea62f 100644
--- a/libs/surfaceflinger/SurfaceFlinger.cpp
+++ b/libs/surfaceflinger/SurfaceFlinger.cpp
@@ -206,8 +206,8 @@ void SurfaceFlinger::init()
property_get("debug.sf.showbackground", value, "0");
mDebugBackground = atoi(value);
- LOGI_IF(mDebugRegion, "showupdates enabled");
- LOGI_IF(mDebugBackground, "showbackground enabled");
+ LOGI_IF(mDebugRegion, "showupdates enabled");
+ LOGI_IF(mDebugBackground, "showbackground enabled");
}
SurfaceFlinger::~SurfaceFlinger()
@@ -225,56 +225,29 @@ sp<IMemoryHeap> SurfaceFlinger::getCblk() const
return mServerHeap;
}
-sp<ISurfaceFlingerClient> SurfaceFlinger::createConnection()
+sp<ISurfaceComposerClient> SurfaceFlinger::createConnection()
{
- Mutex::Autolock _l(mStateLock);
- uint32_t token = mTokens.acquire();
-
- sp<Client> client = new Client(token, this);
- if (client->ctrlblk == 0) {
- mTokens.release(token);
- return 0;
- }
- status_t err = mClientsMap.add(token, client);
- if (err < 0) {
- mTokens.release(token);
- return 0;
+ sp<ISurfaceComposerClient> bclient;
+ sp<Client> client(new Client(this));
+ status_t err = client->initCheck();
+ if (err == NO_ERROR) {
+ bclient = client;
}
- sp<BClient> bclient =
- new BClient(this, token, client->getControlBlockMemory());
return bclient;
}
-void SurfaceFlinger::destroyConnection(ClientID cid)
+sp<ISurfaceComposerClient> SurfaceFlinger::createClientConnection()
{
- Mutex::Autolock _l(mStateLock);
- sp<Client> client = mClientsMap.valueFor(cid);
- if (client != 0) {
- // free all the layers this client owns
- Vector< wp<LayerBaseClient> > layers(client->getLayers());
- const size_t count = layers.size();
- for (size_t i=0 ; i<count ; i++) {
- sp<LayerBaseClient> layer(layers[i].promote());
- if (layer != 0) {
- purgatorizeLayer_l(layer);
- }
- }
-
- // the resources associated with this client will be freed
- // during the next transaction, after these surfaces have been
- // properly removed from the screen
-
- // remove this client from our ClientID->Client mapping.
- mClientsMap.removeItem(cid);
-
- // and add it to the list of disconnected clients
- mDisconnectedClients.add(client);
-
- // request a transaction
- setTransactionFlags(eTransactionNeeded);
+ sp<ISurfaceComposerClient> bclient;
+ sp<UserClient> client(new UserClient(this));
+ status_t err = client->initCheck();
+ if (err == NO_ERROR) {
+ bclient = client;
}
+ return bclient;
}
+
const GraphicPlane& SurfaceFlinger::graphicPlane(int dpy) const
{
LOGE_IF(uint32_t(dpy) >= DISPLAY_COUNT, "Invalid DisplayID %d", dpy);
@@ -357,7 +330,6 @@ status_t SurfaceFlinger::readyToRun()
dcblk->ydpi = hw.getDpiY();
dcblk->fps = hw.getRefreshRate();
dcblk->density = hw.getDensity();
- asm volatile ("":::"memory");
// Initialize OpenGL|ES
glActiveTexture(GL_TEXTURE0);
@@ -427,7 +399,7 @@ void SurfaceFlinger::waitForEvent()
timeout = waitTime>0 ? waitTime : 0;
}
- MessageList::value_type msg = mEventQueue.waitMessage(timeout);
+ sp<MessageBase> msg = mEventQueue.waitMessage(timeout);
// see if we timed out
if (isFrozen()) {
@@ -462,9 +434,20 @@ void SurfaceFlinger::signal() const {
const_cast<SurfaceFlinger*>(this)->signalEvent();
}
-void SurfaceFlinger::signalDelayedEvent(nsecs_t delay)
+status_t SurfaceFlinger::postMessageAsync(const sp<MessageBase>& msg,
+ nsecs_t reltime, uint32_t flags)
{
- mEventQueue.postMessage( new MessageBase(MessageQueue::INVALIDATE), delay);
+ return mEventQueue.postMessage(msg, reltime, flags);
+}
+
+status_t SurfaceFlinger::postMessageSync(const sp<MessageBase>& msg,
+ nsecs_t reltime, uint32_t flags)
+{
+ status_t res = mEventQueue.postMessage(msg, reltime, flags);
+ if (res == NO_ERROR) {
+ msg->wait();
+ }
+ return res;
}
// ----------------------------------------------------------------------------
@@ -655,10 +638,6 @@ void SurfaceFlinger::handleTransactionLocked(
}
}
}
-
- // get rid of all resources we don't need anymore
- // (layers and clients)
- free_resources_l();
}
commitTransaction();
@@ -805,7 +784,8 @@ void SurfaceFlinger::commitTransaction()
void SurfaceFlinger::handlePageFlip()
{
bool visibleRegions = mVisibleRegionsDirty;
- LayerVector& currentLayers = const_cast<LayerVector&>(mDrawingState.layersSortedByZ);
+ LayerVector& currentLayers = const_cast<LayerVector&>(
+ mDrawingState.layersSortedByZ);
visibleRegions |= lockPageFlip(currentLayers);
const DisplayHardware& hw = graphicPlane(0).displayHardware();
@@ -827,7 +807,7 @@ bool SurfaceFlinger::lockPageFlip(const LayerVector& currentLayers)
size_t count = currentLayers.size();
sp<LayerBase> const* layers = currentLayers.array();
for (size_t i=0 ; i<count ; i++) {
- const sp<LayerBase>& layer = layers[i];
+ const sp<LayerBase>& layer(layers[i]);
layer->lockPageFlip(recomputeVisibleRegions);
}
return recomputeVisibleRegions;
@@ -840,7 +820,7 @@ void SurfaceFlinger::unlockPageFlip(const LayerVector& currentLayers)
size_t count = currentLayers.size();
sp<LayerBase> const* layers = currentLayers.array();
for (size_t i=0 ; i<count ; i++) {
- const sp<LayerBase>& layer = layers[i];
+ const sp<LayerBase>& layer(layers[i]);
layer->unlockPageFlip(planeTransform, mDirtyRegion);
}
}
@@ -872,7 +852,7 @@ void SurfaceFlinger::handleRepaint()
// takes a rectangle, we must make sure to update that whole
// rectangle in that case
if (flags & DisplayHardware::SWAP_RECTANGLE) {
- // FIXME: we really should be able to pass a region to
+ // TODO: we really should be able to pass a region to
// SWAP_RECTANGLE so that we don't have to redraw all this.
mDirtyRegion.set(mInvalidRegion.bounds());
} else {
@@ -1061,6 +1041,27 @@ status_t SurfaceFlinger::addLayer(const sp<LayerBase>& layer)
return NO_ERROR;
}
+status_t SurfaceFlinger::addLayer_l(const sp<LayerBase>& layer)
+{
+ ssize_t i = mCurrentState.layersSortedByZ.add(
+ layer, &LayerBase::compareCurrentStateZ);
+ return (i < 0) ? status_t(i) : status_t(NO_ERROR);
+}
+
+ssize_t SurfaceFlinger::addClientLayer(const sp<Client>& client,
+ const sp<LayerBaseClient>& lbc)
+{
+ Mutex::Autolock _l(mStateLock);
+
+ // attach this layer to the client
+ ssize_t name = client->attachLayer(lbc);
+
+ // add this layer to the current state list
+ addLayer_l(lbc);
+
+ return name;
+}
+
status_t SurfaceFlinger::removeLayer(const sp<LayerBase>& layer)
{
Mutex::Autolock _l(mStateLock);
@@ -1070,36 +1071,15 @@ status_t SurfaceFlinger::removeLayer(const sp<LayerBase>& layer)
return err;
}
-status_t SurfaceFlinger::invalidateLayerVisibility(const sp<LayerBase>& layer)
-{
- layer->forceVisibilityTransaction();
- setTransactionFlags(eTraversalNeeded);
- return NO_ERROR;
-}
-
-status_t SurfaceFlinger::addLayer_l(const sp<LayerBase>& layer)
+status_t SurfaceFlinger::removeLayer_l(const sp<LayerBase>& layerBase)
{
- if (layer == 0)
- return BAD_VALUE;
- ssize_t i = mCurrentState.layersSortedByZ.add(
- layer, &LayerBase::compareCurrentStateZ);
- sp<LayerBaseClient> lbc = LayerBase::dynamicCast< LayerBaseClient* >(layer.get());
+ sp<LayerBaseClient> lbc(layerBase->getLayerBaseClient());
if (lbc != 0) {
- mLayerMap.add(lbc->serverIndex(), lbc);
+ mLayerMap.removeItem( lbc->getSurface()->asBinder() );
}
- return NO_ERROR;
-}
-
-status_t SurfaceFlinger::removeLayer_l(const sp<LayerBase>& layerBase)
-{
ssize_t index = mCurrentState.layersSortedByZ.remove(layerBase);
if (index >= 0) {
mLayersRemoved = true;
- sp<LayerBaseClient> layer =
- LayerBase::dynamicCast< LayerBaseClient* >(layerBase.get());
- if (layer != 0) {
- mLayerMap.removeItem(layer->serverIndex());
- }
return NO_ERROR;
}
return status_t(index);
@@ -1114,22 +1094,16 @@ status_t SurfaceFlinger::purgatorizeLayer_l(const sp<LayerBase>& layerBase)
// it's possible that we don't find a layer, because it might
// have been destroyed already -- this is not technically an error
- // from the user because there is a race between BClient::destroySurface(),
- // ~BClient() and ~ISurface().
+ // from the user because there is a race between Client::destroySurface(),
+ // ~Client() and ~ISurface().
return (err == NAME_NOT_FOUND) ? status_t(NO_ERROR) : err;
}
-
-void SurfaceFlinger::free_resources_l()
+status_t SurfaceFlinger::invalidateLayerVisibility(const sp<LayerBase>& layer)
{
- // free resources associated with disconnected clients
- Vector< sp<Client> >& disconnectedClients(mDisconnectedClients);
- const size_t count = disconnectedClients.size();
- for (size_t i=0 ; i<count ; i++) {
- sp<Client> client = disconnectedClients[i];
- mTokens.release(client->cid);
- }
- disconnectedClients.clear();
+ layer->forceVisibilityTransaction();
+ setTransactionFlags(eTraversalNeeded);
+ return NO_ERROR;
}
uint32_t SurfaceFlinger::getTransactionFlags(uint32_t flags)
@@ -1137,15 +1111,11 @@ uint32_t SurfaceFlinger::getTransactionFlags(uint32_t flags)
return android_atomic_and(~flags, &mTransactionFlags) & flags;
}
-uint32_t SurfaceFlinger::setTransactionFlags(uint32_t flags, nsecs_t delay)
+uint32_t SurfaceFlinger::setTransactionFlags(uint32_t flags)
{
uint32_t old = android_atomic_or(flags, &mTransactionFlags);
if ((old & flags)==0) { // wake the server up
- if (delay > 0) {
- signalDelayedEvent(delay);
- } else {
- signalEvent();
- }
+ signalEvent();
}
return old;
}
@@ -1224,8 +1194,8 @@ int SurfaceFlinger::setOrientation(DisplayID dpy,
return orientation;
}
-sp<ISurface> SurfaceFlinger::createSurface(ClientID clientId, int pid,
- const String8& name, ISurfaceFlingerClient::surface_data_t* params,
+sp<ISurface> SurfaceFlinger::createSurface(const sp<Client>& client, int pid,
+ const String8& name, ISurfaceComposerClient::surface_data_t* params,
DisplayID d, uint32_t w, uint32_t h, PixelFormat format,
uint32_t flags)
{
@@ -1238,57 +1208,52 @@ sp<ISurface> SurfaceFlinger::createSurface(ClientID clientId, int pid,
return surfaceHandle;
}
- Mutex::Autolock _l(mStateLock);
- sp<Client> client = mClientsMap.valueFor(clientId);
- if (UNLIKELY(client == 0)) {
- LOGE("createSurface() failed, client not found (id=%d)", clientId);
- return surfaceHandle;
- }
-
//LOGD("createSurface for pid %d (%d x %d)", pid, w, h);
- int32_t id = client->generateId(pid);
- if (uint32_t(id) >= NUM_LAYERS_MAX) {
- LOGE("createSurface() failed, generateId = %d", id);
- return surfaceHandle;
- }
-
+ sp<Layer> normalLayer;
switch (flags & eFXSurfaceMask) {
case eFXSurfaceNormal:
if (UNLIKELY(flags & ePushBuffers)) {
- layer = createPushBuffersSurfaceLocked(client, d, id,
- w, h, flags);
+ layer = createPushBuffersSurface(client, d, w, h, flags);
} else {
- layer = createNormalSurfaceLocked(client, d, id,
- w, h, flags, format);
+ normalLayer = createNormalSurface(client, d, w, h, flags, format);
+ layer = normalLayer;
}
break;
case eFXSurfaceBlur:
- layer = createBlurSurfaceLocked(client, d, id, w, h, flags);
+ layer = createBlurSurface(client, d, w, h, flags);
break;
case eFXSurfaceDim:
- layer = createDimSurfaceLocked(client, d, id, w, h, flags);
+ layer = createDimSurface(client, d, w, h, flags);
break;
}
if (layer != 0) {
+ layer->initStates(w, h, flags);
layer->setName(name);
- setTransactionFlags(eTransactionNeeded);
+ ssize_t token = addClientLayer(client, layer);
+
surfaceHandle = layer->getSurface();
if (surfaceHandle != 0) {
- params->token = surfaceHandle->getToken();
+ params->token = token;
params->identity = surfaceHandle->getIdentity();
params->width = w;
params->height = h;
params->format = format;
+ if (normalLayer != 0) {
+ Mutex::Autolock _l(mStateLock);
+ mLayerMap.add(surfaceHandle->asBinder(), normalLayer);
+ }
}
+
+ setTransactionFlags(eTransactionNeeded);
}
return surfaceHandle;
}
-sp<LayerBaseClient> SurfaceFlinger::createNormalSurfaceLocked(
+sp<Layer> SurfaceFlinger::createNormalSurface(
const sp<Client>& client, DisplayID display,
- int32_t id, uint32_t w, uint32_t h, uint32_t flags,
+ uint32_t w, uint32_t h, uint32_t flags,
PixelFormat& format)
{
// initialize the surfaces
@@ -1298,53 +1263,47 @@ sp<LayerBaseClient> SurfaceFlinger::createNormalSurfaceLocked(
format = PIXEL_FORMAT_RGBA_8888;
break;
case PIXEL_FORMAT_OPAQUE:
- format = PIXEL_FORMAT_RGB_565;
+ format = PIXEL_FORMAT_RGBX_8888;
break;
}
- sp<Layer> layer = new Layer(this, display, client, id);
+ sp<Layer> layer = new Layer(this, display, client);
status_t err = layer->setBuffers(w, h, format, flags);
- if (LIKELY(err == NO_ERROR)) {
- layer->initStates(w, h, flags);
- addLayer_l(layer);
- } else {
+ if (LIKELY(err != NO_ERROR)) {
LOGE("createNormalSurfaceLocked() failed (%s)", strerror(-err));
layer.clear();
}
return layer;
}
-sp<LayerBaseClient> SurfaceFlinger::createBlurSurfaceLocked(
+sp<LayerBlur> SurfaceFlinger::createBlurSurface(
const sp<Client>& client, DisplayID display,
- int32_t id, uint32_t w, uint32_t h, uint32_t flags)
+ uint32_t w, uint32_t h, uint32_t flags)
{
- sp<LayerBlur> layer = new LayerBlur(this, display, client, id);
+ sp<LayerBlur> layer = new LayerBlur(this, display, client);
layer->initStates(w, h, flags);
- addLayer_l(layer);
return layer;
}
-sp<LayerBaseClient> SurfaceFlinger::createDimSurfaceLocked(
+sp<LayerDim> SurfaceFlinger::createDimSurface(
const sp<Client>& client, DisplayID display,
- int32_t id, uint32_t w, uint32_t h, uint32_t flags)
+ uint32_t w, uint32_t h, uint32_t flags)
{
- sp<LayerDim> layer = new LayerDim(this, display, client, id);
+ sp<LayerDim> layer = new LayerDim(this, display, client);
layer->initStates(w, h, flags);
- addLayer_l(layer);
return layer;
}
-sp<LayerBaseClient> SurfaceFlinger::createPushBuffersSurfaceLocked(
+sp<LayerBuffer> SurfaceFlinger::createPushBuffersSurface(
const sp<Client>& client, DisplayID display,
- int32_t id, uint32_t w, uint32_t h, uint32_t flags)
+ uint32_t w, uint32_t h, uint32_t flags)
{
- sp<LayerBuffer> layer = new LayerBuffer(this, display, client, id);
+ sp<LayerBuffer> layer = new LayerBuffer(this, display, client);
layer->initStates(w, h, flags);
- addLayer_l(layer);
return layer;
}
-status_t SurfaceFlinger::removeSurface(SurfaceID index)
+status_t SurfaceFlinger::removeSurface(const sp<Client>& client, SurfaceID sid)
{
/*
* called by the window manager, when a surface should be marked for
@@ -1357,7 +1316,7 @@ status_t SurfaceFlinger::removeSurface(SurfaceID index)
status_t err = NAME_NOT_FOUND;
Mutex::Autolock _l(mStateLock);
- sp<LayerBaseClient> layer = getLayerUser_l(index);
+ sp<LayerBaseClient> layer = client->getLayerUser(sid);
if (layer != 0) {
err = purgatorizeLayer_l(layer);
if (err == NO_ERROR) {
@@ -1397,21 +1356,20 @@ status_t SurfaceFlinger::destroySurface(const sp<LayerBaseClient>& layer)
}
};
- mEventQueue.postMessage( new MessageDestroySurface(this, layer) );
+ postMessageAsync( new MessageDestroySurface(this, layer) );
return NO_ERROR;
}
status_t SurfaceFlinger::setClientState(
- ClientID cid,
+ const sp<Client>& client,
int32_t count,
const layer_state_t* states)
{
Mutex::Autolock _l(mStateLock);
uint32_t flags = 0;
- cid <<= 16;
for (int i=0 ; i<count ; i++) {
- const layer_state_t& s = states[i];
- sp<LayerBaseClient> layer(getLayerUser_l(s.surface | cid));
+ const layer_state_t& s(states[i]);
+ sp<LayerBaseClient> layer(client->getLayerUser(s.surface));
if (layer != 0) {
const uint32_t what = s.what;
if (what & ePositionChanged) {
@@ -1457,12 +1415,6 @@ status_t SurfaceFlinger::setClientState(
return NO_ERROR;
}
-sp<LayerBaseClient> SurfaceFlinger::getLayerUser_l(SurfaceID s) const
-{
- sp<LayerBaseClient> layer = mLayerMap.valueFor(s);
- return layer;
-}
-
void SurfaceFlinger::screenReleased(int dpy)
{
// this may be called by a signal handler, we can't do too much in here
@@ -1512,83 +1464,17 @@ status_t SurfaceFlinger::dump(int fd, const Vector<String16>& args)
result.append(buffer);
}
- size_t s = mClientsMap.size();
- char name[64];
- for (size_t i=0 ; i<s ; i++) {
- sp<Client> client = mClientsMap.valueAt(i);
- sprintf(name, " Client (id=0x%08x)", client->cid);
- client->dump(name);
- }
const LayerVector& currentLayers = mCurrentState.layersSortedByZ;
const size_t count = currentLayers.size();
for (size_t i=0 ; i<count ; i++) {
- /*** LayerBase ***/
- const sp<LayerBase>& layer = currentLayers[i];
- const Layer::State& s = layer->drawingState();
- snprintf(buffer, SIZE,
- "+ %s %p\n"
- " "
- "z=%9d, pos=(%4d,%4d), size=(%4d,%4d), "
- "needsBlending=%1d, needsDithering=%1d, invalidate=%1d, "
- "alpha=0x%02x, flags=0x%08x, tr=[%.2f, %.2f][%.2f, %.2f]\n",
- layer->getTypeID(), layer.get(),
- s.z, layer->tx(), layer->ty(), s.w, s.h,
- layer->needsBlending(), layer->needsDithering(),
- layer->contentDirty,
- s.alpha, s.flags,
- s.transform[0][0], s.transform[0][1],
- s.transform[1][0], s.transform[1][1]);
- result.append(buffer);
- buffer[0] = 0;
- /*** LayerBaseClient ***/
- sp<LayerBaseClient> lbc =
- LayerBase::dynamicCast< LayerBaseClient* >(layer.get());
- if (lbc != 0) {
- sp<Client> client(lbc->client.promote());
- snprintf(buffer, SIZE,
- " name=%s\n", lbc->getName().string());
- result.append(buffer);
- snprintf(buffer, SIZE,
- " id=0x%08x, client=0x%08x, identity=%u\n",
- lbc->clientIndex(), client.get() ? client->cid : 0,
- lbc->getIdentity());
-
- result.append(buffer);
- buffer[0] = 0;
- }
- /*** Layer ***/
- sp<Layer> l = LayerBase::dynamicCast< Layer* >(layer.get());
- if (l != 0) {
- SharedBufferStack::Statistics stats = l->lcblk->getStats();
- result.append( l->lcblk->dump(" ") );
- sp<const GraphicBuffer> buf0(l->getBuffer(0));
- sp<const GraphicBuffer> buf1(l->getBuffer(1));
- uint32_t w0=0, h0=0, s0=0;
- uint32_t w1=0, h1=0, s1=0;
- if (buf0 != 0) {
- w0 = buf0->getWidth();
- h0 = buf0->getHeight();
- s0 = buf0->getStride();
- }
- if (buf1 != 0) {
- w1 = buf1->getWidth();
- h1 = buf1->getHeight();
- s1 = buf1->getStride();
- }
- snprintf(buffer, SIZE,
- " "
- "format=%2d, [%3ux%3u:%3u] [%3ux%3u:%3u],"
- " freezeLock=%p, dq-q-time=%u us\n",
- l->pixelFormat(),
- w0, h0, s0, w1, h1, s1,
- l->getFreezeLock().get(), stats.totalTime);
- result.append(buffer);
- buffer[0] = 0;
- }
+ const sp<LayerBase>& layer(currentLayers[i]);
+ layer->dump(result, buffer, SIZE);
+ const Layer::State& s(layer->drawingState());
s.transparentRegion.dump(result, "transparentRegion");
layer->transparentRegionScreen.dump(result, "transparentRegionScreen");
layer->visibleRegionScreen.dump(result, "visibleRegionScreen");
}
+
mWormholeRegion.dump(result, "WormholeRegion");
const DisplayHardware& hw(graphicPlane(0).displayHardware());
snprintf(buffer, SIZE,
@@ -1601,18 +1487,19 @@ status_t SurfaceFlinger::dump(int fd, const Vector<String16>& args)
" last transaction time : %f us\n",
mLastSwapBufferTime/1000.0, mLastTransactionTime/1000.0);
result.append(buffer);
+
if (inSwapBuffersDuration || !locked) {
snprintf(buffer, SIZE, " eglSwapBuffers time: %f us\n",
inSwapBuffersDuration/1000.0);
result.append(buffer);
}
+
if (inTransactionDuration || !locked) {
snprintf(buffer, SIZE, " transaction time: %f us\n",
inTransactionDuration/1000.0);
result.append(buffer);
}
- snprintf(buffer, SIZE, " client count: %d\n", mClientsMap.size());
- result.append(buffer);
+
const GraphicBufferAllocator& alloc(GraphicBufferAllocator::get());
alloc.dump(result);
@@ -1705,116 +1592,189 @@ status_t SurfaceFlinger::onTransact(
}
// ---------------------------------------------------------------------------
-#if 0
-#pragma mark -
-#endif
-Client::Client(ClientID clientID, const sp<SurfaceFlinger>& flinger)
- : ctrlblk(0), cid(clientID), mPid(0), mBitmap(0), mFlinger(flinger)
+sp<Layer> SurfaceFlinger::getLayer(const sp<ISurface>& sur) const
{
- const int pgsize = getpagesize();
- const int cblksize = ((sizeof(SharedClient)+(pgsize-1))&~(pgsize-1));
+ sp<Layer> result;
+ Mutex::Autolock _l(mStateLock);
+ result = mLayerMap.valueFor( sur->asBinder() ).promote();
+ return result;
+}
- mCblkHeap = new MemoryHeapBase(cblksize, 0,
- "SurfaceFlinger Client control-block");
+// ---------------------------------------------------------------------------
- ctrlblk = static_cast<SharedClient *>(mCblkHeap->getBase());
- if (ctrlblk) { // construct the shared structure in-place.
- new(ctrlblk) SharedClient;
- }
+Client::Client(const sp<SurfaceFlinger>& flinger)
+ : mFlinger(flinger), mNameGenerator(1)
+{
}
-Client::~Client() {
- if (ctrlblk) {
- ctrlblk->~SharedClient(); // destroy our shared-structure.
+Client::~Client()
+{
+ const size_t count = mLayers.size();
+ for (size_t i=0 ; i<count ; i++) {
+ sp<LayerBaseClient> layer(mLayers.valueAt(i).promote());
+ if (layer != 0) {
+ mFlinger->removeLayer(layer);
+ }
}
}
-int32_t Client::generateId(int pid)
-{
- const uint32_t i = clz( ~mBitmap );
- if (i >= NUM_LAYERS_MAX) {
- return NO_MEMORY;
- }
- mPid = pid;
- mInUse.add(uint8_t(i));
- mBitmap |= 1<<(31-i);
- return i;
+status_t Client::initCheck() const {
+ return NO_ERROR;
}
-status_t Client::bindLayer(const sp<LayerBaseClient>& layer, int32_t id)
+ssize_t Client::attachLayer(const sp<LayerBaseClient>& layer)
{
- ssize_t idx = mInUse.indexOf(id);
- if (idx < 0)
- return NAME_NOT_FOUND;
- return mLayers.insertAt(layer, idx);
+ int32_t name = android_atomic_inc(&mNameGenerator);
+ mLayers.add(name, layer);
+ return name;
}
-void Client::free(int32_t id)
+void Client::detachLayer(const LayerBaseClient* layer)
{
- ssize_t idx = mInUse.remove(uint8_t(id));
- if (idx >= 0) {
- mBitmap &= ~(1<<(31-id));
- mLayers.removeItemsAt(idx);
+ // we do a linear search here, because this doesn't happen often
+ const size_t count = mLayers.size();
+ for (size_t i=0 ; i<count ; i++) {
+ if (mLayers.valueAt(i) == layer) {
+ mLayers.removeItemsAt(i, 1);
+ break;
+ }
}
}
-
-bool Client::isValid(int32_t i) const {
- return (uint32_t(i)<NUM_LAYERS_MAX) && (mBitmap & (1<<(31-i)));
-}
-
sp<LayerBaseClient> Client::getLayerUser(int32_t i) const {
sp<LayerBaseClient> lbc;
- ssize_t idx = mInUse.indexOf(uint8_t(i));
- if (idx >= 0) {
- lbc = mLayers[idx].promote();
- LOGE_IF(lbc==0, "getLayerUser(i=%d), idx=%d is dead", int(i), int(idx));
+ const wp<LayerBaseClient>& layer(mLayers.valueFor(i));
+ if (layer != 0) {
+ lbc = layer.promote();
+ LOGE_IF(lbc==0, "getLayerUser(name=%d) is dead", int(i));
}
return lbc;
}
-void Client::dump(const char* what)
+sp<IMemoryHeap> Client::getControlBlock() const {
+ return 0;
+}
+ssize_t Client::getTokenForSurface(const sp<ISurface>& sur) const {
+ return -1;
+}
+sp<ISurface> Client::createSurface(
+ ISurfaceComposerClient::surface_data_t* params, int pid,
+ const String8& name,
+ DisplayID display, uint32_t w, uint32_t h, PixelFormat format,
+ uint32_t flags)
{
+ return mFlinger->createSurface(this, pid, name, params,
+ display, w, h, format, flags);
+}
+status_t Client::destroySurface(SurfaceID sid) {
+ return mFlinger->removeSurface(this, sid);
+}
+status_t Client::setState(int32_t count, const layer_state_t* states) {
+ return mFlinger->setClientState(this, count, states);
}
// ---------------------------------------------------------------------------
-#if 0
-#pragma mark -
-#endif
-BClient::BClient(SurfaceFlinger *flinger, ClientID cid, const sp<IMemoryHeap>& cblk)
- : mId(cid), mFlinger(flinger), mCblk(cblk)
+UserClient::UserClient(const sp<SurfaceFlinger>& flinger)
+ : ctrlblk(0), mBitmap(0), mFlinger(flinger)
{
+ const int pgsize = getpagesize();
+ const int cblksize = ((sizeof(SharedClient)+(pgsize-1))&~(pgsize-1));
+
+ mCblkHeap = new MemoryHeapBase(cblksize, 0,
+ "SurfaceFlinger Client control-block");
+
+ ctrlblk = static_cast<SharedClient *>(mCblkHeap->getBase());
+ if (ctrlblk) { // construct the shared structure in-place.
+ new(ctrlblk) SharedClient;
+ }
}
-BClient::~BClient() {
- // destroy all resources attached to this client
- mFlinger->destroyConnection(mId);
+UserClient::~UserClient()
+{
+ if (ctrlblk) {
+ ctrlblk->~SharedClient(); // destroy our shared-structure.
+ }
+
+ /*
+ * When a UserClient dies, it's unclear what to do exactly.
+ * We could go ahead and destroy all surfaces linked to that client
+ * however, it wouldn't be fair to the main Client
+ * (usually the the window-manager), which might want to re-target
+ * the layer to another UserClient.
+ * I think the best is to do nothing, or not much; in most cases the
+ * WM itself will go ahead and clean things up when it detects a client of
+ * his has died.
+ * The remaining question is what to display? currently we keep
+ * just keep the current buffer.
+ */
}
-sp<IMemoryHeap> BClient::getControlBlock() const {
- return mCblk;
+status_t UserClient::initCheck() const {
+ return ctrlblk == 0 ? NO_INIT : NO_ERROR;
}
-sp<ISurface> BClient::createSurface(
- ISurfaceFlingerClient::surface_data_t* params, int pid,
- const String8& name,
- DisplayID display, uint32_t w, uint32_t h, PixelFormat format,
- uint32_t flags)
+void UserClient::detachLayer(const Layer* layer)
{
- return mFlinger->createSurface(mId, pid, name, params, display, w, h,
- format, flags);
+ int32_t name = layer->getToken();
+ if (name >= 0) {
+ int32_t mask = 1LU<<name;
+ if ((android_atomic_and(~mask, &mBitmap) & mask) == 0) {
+ LOGW("token %d wasn't marked as used %08x", name, int(mBitmap));
+ }
+ }
}
-status_t BClient::destroySurface(SurfaceID sid)
-{
- sid |= (mId << 16); // add the client-part to id
- return mFlinger->removeSurface(sid);
+sp<IMemoryHeap> UserClient::getControlBlock() const {
+ return mCblkHeap;
}
-status_t BClient::setState(int32_t count, const layer_state_t* states)
+ssize_t UserClient::getTokenForSurface(const sp<ISurface>& sur) const
{
- return mFlinger->setClientState(mId, count, states);
+ int32_t name = NAME_NOT_FOUND;
+ sp<Layer> layer(mFlinger->getLayer(sur));
+ if (layer == 0) return name;
+
+ // if this layer already has a token, just return it
+ name = layer->getToken();
+ if ((name >= 0) && (layer->getClient() == this))
+ return name;
+
+ name = 0;
+ do {
+ int32_t mask = 1LU<<name;
+ if ((android_atomic_or(mask, &mBitmap) & mask) == 0) {
+ // we found and locked that name
+ status_t err = layer->setToken(
+ const_cast<UserClient*>(this), ctrlblk, name);
+ if (err != NO_ERROR) {
+ // free the name
+ android_atomic_and(~mask, &mBitmap);
+ name = err;
+ }
+ break;
+ }
+ if (++name > 31)
+ name = NO_MEMORY;
+ } while(name >= 0);
+
+ //LOGD("getTokenForSurface(%p) => %d (client=%p, bitmap=%08lx)",
+ // sur->asBinder().get(), name, this, mBitmap);
+ return name;
+}
+
+sp<ISurface> UserClient::createSurface(
+ ISurfaceComposerClient::surface_data_t* params, int pid,
+ const String8& name,
+ DisplayID display, uint32_t w, uint32_t h, PixelFormat format,
+ uint32_t flags) {
+ return 0;
+}
+status_t UserClient::destroySurface(SurfaceID sid) {
+ return INVALID_OPERATION;
+}
+status_t UserClient::setState(int32_t count, const layer_state_t* states) {
+ return INVALID_OPERATION;
}
// ---------------------------------------------------------------------------