diff options
Diffstat (limited to 'libs/surfaceflinger/SurfaceFlinger.cpp')
-rw-r--r-- | libs/surfaceflinger/SurfaceFlinger.cpp | 548 |
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; } // --------------------------------------------------------------------------- |