diff options
author | The Android Open Source Project <initial-contribution@android.com> | 2009-03-03 18:28:45 -0800 |
---|---|---|
committer | The Android Open Source Project <initial-contribution@android.com> | 2009-03-03 18:28:45 -0800 |
commit | d83a98f4ce9cfa908f5c54bbd70f03eec07e7553 (patch) | |
tree | 4b825dc642cb6eb9a060e54bf8d69288fbee4904 /libs/ui/SurfaceComposerClient.cpp | |
parent | 076357b8567458d4b6dfdcf839ef751634cd2bfb (diff) | |
download | frameworks_base-d83a98f4ce9cfa908f5c54bbd70f03eec07e7553.zip frameworks_base-d83a98f4ce9cfa908f5c54bbd70f03eec07e7553.tar.gz frameworks_base-d83a98f4ce9cfa908f5c54bbd70f03eec07e7553.tar.bz2 |
auto import from //depot/cupcake/@135843
Diffstat (limited to 'libs/ui/SurfaceComposerClient.cpp')
-rw-r--r-- | libs/ui/SurfaceComposerClient.cpp | 1026 |
1 files changed, 0 insertions, 1026 deletions
diff --git a/libs/ui/SurfaceComposerClient.cpp b/libs/ui/SurfaceComposerClient.cpp deleted file mode 100644 index 9354a7a..0000000 --- a/libs/ui/SurfaceComposerClient.cpp +++ /dev/null @@ -1,1026 +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. - */ - -#define LOG_TAG "SurfaceComposerClient" - -#include <stdint.h> -#include <unistd.h> -#include <fcntl.h> -#include <errno.h> -#include <sys/types.h> -#include <sys/stat.h> - -#include <cutils/memory.h> - -#include <utils/Atomic.h> -#include <utils/Errors.h> -#include <utils/threads.h> -#include <utils/KeyedVector.h> -#include <utils/IPCThreadState.h> -#include <utils/IServiceManager.h> -#include <utils/IMemory.h> -#include <utils/Log.h> - -#include <ui/ISurfaceComposer.h> -#include <ui/ISurfaceFlingerClient.h> -#include <ui/ISurface.h> -#include <ui/SurfaceComposerClient.h> -#include <ui/DisplayInfo.h> -#include <ui/Rect.h> -#include <ui/Point.h> - -#include <private/ui/SharedState.h> -#include <private/ui/LayerState.h> -#include <private/ui/SurfaceFlingerSynchro.h> - -#include <pixelflinger/pixelflinger.h> - -#include <utils/BpBinder.h> - -#define VERBOSE(...) ((void)0) -//#define VERBOSE LOGD - -#define LIKELY( exp ) (__builtin_expect( (exp) != 0, true )) -#define UNLIKELY( exp ) (__builtin_expect( (exp) != 0, false )) - -namespace android { - -// --------------------------------------------------------------------------- - -// Must not be holding SurfaceComposerClient::mLock when acquiring gLock here. -static Mutex gLock; -static sp<ISurfaceComposer> gSurfaceManager; -static DefaultKeyedVector< sp<IBinder>, sp<SurfaceComposerClient> > gActiveConnections; -static SortedVector<sp<SurfaceComposerClient> > gOpenTransactions; -static sp<IMemory> gServerCblkMemory; -static volatile surface_flinger_cblk_t* gServerCblk; - -const sp<ISurfaceComposer>& _get_surface_manager() -{ - if (gSurfaceManager != 0) { - return gSurfaceManager; - } - - sp<IBinder> binder; - sp<IServiceManager> sm = defaultServiceManager(); - do { - binder = sm->getService(String16("SurfaceFlinger")); - if (binder == 0) { - LOGW("SurfaceFlinger not published, waiting..."); - usleep(500000); // 0.5 s - } - } while(binder == 0); - sp<ISurfaceComposer> sc(interface_cast<ISurfaceComposer>(binder)); - - Mutex::Autolock _l(gLock); - if (gSurfaceManager == 0) { - gSurfaceManager = sc; - } - return gSurfaceManager; -} - -static volatile surface_flinger_cblk_t const * get_cblk() -{ - if (gServerCblk == 0) { - const sp<ISurfaceComposer>& sm(_get_surface_manager()); - Mutex::Autolock _l(gLock); - if (gServerCblk == 0) { - gServerCblkMemory = sm->getCblk(); - LOGE_IF(gServerCblkMemory==0, "Can't get server control block"); - gServerCblk = (surface_flinger_cblk_t *)gServerCblkMemory->pointer(); - LOGE_IF(gServerCblk==0, "Can't get server control block address"); - } - } - return gServerCblk; -} - -// --------------------------------------------------------------------------- - -static void copyBlt(const GGLSurface& dst, - const GGLSurface& src, const Region& reg) -{ - Region::iterator iterator(reg); - if (iterator) { - // NOTE: dst and src must be the same format - Rect r; - const size_t bpp = bytesPerPixel(src.format); - const size_t dbpr = dst.stride * bpp; - const size_t sbpr = src.stride * bpp; - while (iterator.iterate(&r)) { - ssize_t h = r.bottom - r.top; - if (h) { - size_t size = (r.right - r.left) * bpp; - uint8_t* s = src.data + (r.left + src.stride * r.top) * bpp; - uint8_t* d = dst.data + (r.left + dst.stride * r.top) * bpp; - if (dbpr==sbpr && size==sbpr) { - size *= h; - h = 1; - } - do { - memcpy(d, s, size); - d += dbpr; - s += sbpr; - } while (--h > 0); - } - } - } -} - -// --------------------------------------------------------------------------- - -surface_flinger_cblk_t::surface_flinger_cblk_t() -{ -} - -// --------------------------------------------------------------------------- - -per_client_cblk_t::per_client_cblk_t() -{ -} - -// these functions are used by the clients -inline status_t per_client_cblk_t::validate(size_t i) const { - if (uint32_t(i) >= NUM_LAYERS_MAX) - return BAD_INDEX; - if (layers[i].swapState & eInvalidSurface) - return NO_MEMORY; - return NO_ERROR; -} - -int32_t per_client_cblk_t::lock_layer(size_t i, uint32_t flags) -{ - int32_t index; - uint32_t state; - int timeout = 0; - status_t result; - layer_cblk_t * const layer = layers + i; - const bool blocking = flags & BLOCKING; - const bool inspect = flags & INSPECT; - - do { - state = layer->swapState; - - if (UNLIKELY((state&(eFlipRequested|eNextFlipPending)) == eNextFlipPending)) { - LOGE("eNextFlipPending set but eFlipRequested not set, " - "layer=%d (lcblk=%p), state=%08x", - int(i), layer, int(state)); - return INVALID_OPERATION; - } - - if (UNLIKELY(state&eLocked)) { - LOGE("eLocked set when entering lock_layer(), " - "layer=%d (lcblk=%p), state=%08x", - int(i), layer, int(state)); - return WOULD_BLOCK; - } - - - if (state & (eFlipRequested | eNextFlipPending | eResizeRequested - | eInvalidSurface)) - { - int32_t resizeIndex; - Mutex::Autolock _l(lock); - // might block for a very short amount of time - // will never cause the server to block (trylock()) - - goto start_loop_here; - - // We block the client if: - // eNextFlipPending: we've used both buffers already, so we need to - // wait for one to become availlable. - // eResizeRequested: the buffer we're going to acquire is being - // resized. Block until it is done. - // eFlipRequested && eBusy: the buffer we're going to acquire is - // currently in use by the server. - // eInvalidSurface: this is a special case, we don't block in this - // case, we just return an error. - - while((state & (eNextFlipPending|eInvalidSurface)) || - (state & ((resizeIndex) ? eResizeBuffer1 : eResizeBuffer0)) || - ((state & (eFlipRequested|eBusy)) == (eFlipRequested|eBusy)) ) - { - if (state & eInvalidSurface) - return NO_MEMORY; - - if (!blocking) - return WOULD_BLOCK; - - timeout = 0; - result = cv.waitRelative(lock, seconds(1)); - if (__builtin_expect(result!=NO_ERROR, false)) { - const int newState = layer->swapState; - LOGW( "lock_layer timed out (is the CPU pegged?) " - "layer=%d, lcblk=%p, state=%08x (was %08x)", - int(i), layer, newState, int(state)); - timeout = newState != int(state); - } - - start_loop_here: - state = layer->swapState; - resizeIndex = (state&eIndex) ^ ((state&eFlipRequested)>>1); - } - - LOGW_IF(timeout, - "lock_layer() timed out but didn't appear to need " - "to be locked and we recovered " - "(layer=%d, lcblk=%p, state=%08x)", - int(i), layer, int(state)); - } - - // eFlipRequested is not set and cannot be set by another thread: it's - // safe to use the first buffer without synchronization. - - // Choose the index depending on eFlipRequested. - // When it's set, choose the 'other' buffer. - index = (state&eIndex) ^ ((state&eFlipRequested)>>1); - - // make sure this buffer is valid - if (layer->surface[index].bits_offset < 0) { - return status_t(layer->surface[index].bits_offset); - } - - if (inspect) { - // we just want to inspect this layer. don't lock it. - goto done; - } - - // last thing before we're done, we need to atomically lock the state - } while (android_atomic_cmpxchg(state, state|eLocked, &(layer->swapState))); - - VERBOSE("locked layer=%d (lcblk=%p), buffer=%d, state=0x%08x", - int(i), layer, int(index), int(state)); - - // store the index of the locked buffer (for client use only) - layer->flags &= ~eBufferIndex; - layer->flags |= ((index << eBufferIndexShift) & eBufferIndex); - -done: - return index; -} - -uint32_t per_client_cblk_t::unlock_layer_and_post(size_t i) -{ - // atomically set eFlipRequested and clear eLocked and optionnaly - // set eNextFlipPending if eFlipRequested was already set - - layer_cblk_t * const layer = layers + i; - int32_t oldvalue, newvalue; - do { - oldvalue = layer->swapState; - // get current value - - newvalue = oldvalue & ~eLocked; - // clear eLocked - - newvalue |= eFlipRequested; - // set eFlipRequested - - if (oldvalue & eFlipRequested) - newvalue |= eNextFlipPending; - // if eFlipRequested was alread set, set eNextFlipPending - - } while (android_atomic_cmpxchg(oldvalue, newvalue, &(layer->swapState))); - - VERBOSE("request pageflip for layer=%d, buffer=%d, state=0x%08x", - int(i), int((layer->flags & eBufferIndex) >> eBufferIndexShift), - int(newvalue)); - - // from this point, the server can kick in at anytime and use the first - // buffer, so we cannot use it anymore, and we must use the 'other' - // buffer instead (or wait if it is not availlable yet, see lock_layer). - - return newvalue; -} - -void per_client_cblk_t::unlock_layer(size_t i) -{ - layer_cblk_t * const layer = layers + i; - android_atomic_and(~eLocked, &layer->swapState); -} - -// --------------------------------------------------------------------------- - -static inline int compare_type( const layer_state_t& lhs, - const layer_state_t& rhs) { - if (lhs.surface < rhs.surface) return -1; - if (lhs.surface > rhs.surface) return 1; - return 0; -} - -SurfaceComposerClient::SurfaceComposerClient() -{ - const sp<ISurfaceComposer>& sm(_get_surface_manager()); - if (sm == 0) { - _init(0, 0); - return; - } - - _init(sm, sm->createConnection()); - - if (mClient != 0) { - Mutex::Autolock _l(gLock); - VERBOSE("Adding client %p to map", this); - gActiveConnections.add(mClient->asBinder(), this); - } -} - -SurfaceComposerClient::SurfaceComposerClient( - const sp<ISurfaceComposer>& sm, const sp<IBinder>& conn) -{ - _init(sm, interface_cast<ISurfaceFlingerClient>(conn)); -} - -void SurfaceComposerClient::_init( - const sp<ISurfaceComposer>& sm, const sp<ISurfaceFlingerClient>& conn) -{ - VERBOSE("Creating client %p, conn %p", this, conn.get()); - - mSignalServer = 0; - mPrebuiltLayerState = 0; - mTransactionOpen = 0; - mStatus = NO_ERROR; - mControl = 0; - - mClient = conn; - if (mClient == 0) { - mStatus = NO_INIT; - return; - } - - mClient->getControlBlocks(&mControlMemory); - mSignalServer = new SurfaceFlingerSynchro(sm); - mControl = static_cast<per_client_cblk_t *>(mControlMemory->pointer()); -} - -SurfaceComposerClient::~SurfaceComposerClient() -{ - VERBOSE("Destroying client %p, conn %p", this, mClient.get()); - dispose(); -} - -status_t SurfaceComposerClient::initCheck() const -{ - return mStatus; -} - -status_t SurfaceComposerClient::validateSurface( - per_client_cblk_t const* cblk, Surface const * surface) -{ - SurfaceID index = surface->ID(); - if (cblk == 0) { - LOGE("cblk is null (surface id=%d, identity=%u)", - index, surface->getIdentity()); - return NO_INIT; - } - - status_t err = cblk->validate(index); - if (err != NO_ERROR) { - LOGE("surface (id=%d, identity=%u) is invalid, err=%d (%s)", - index, surface->getIdentity(), err, strerror(-err)); - return err; - } - - if (surface->getIdentity() != uint32_t(cblk->layers[index].identity)) { - LOGE("using an invalid surface id=%d, identity=%u should be %d", - index, surface->getIdentity(), cblk->layers[index].identity); - return NO_INIT; - } - - return NO_ERROR; -} - -sp<IBinder> SurfaceComposerClient::connection() const -{ - return (mClient != 0) ? mClient->asBinder() : 0; -} - -sp<SurfaceComposerClient> -SurfaceComposerClient::clientForConnection(const sp<IBinder>& conn) -{ - sp<SurfaceComposerClient> client; - - { // scope for lock - Mutex::Autolock _l(gLock); - client = gActiveConnections.valueFor(conn); - } - - if (client == 0) { - // Need to make a new client. - const sp<ISurfaceComposer>& sm(_get_surface_manager()); - client = new SurfaceComposerClient(sm, conn); - if (client != 0 && client->initCheck() == NO_ERROR) { - Mutex::Autolock _l(gLock); - gActiveConnections.add(conn, client); - //LOGD("we have %d connections", gActiveConnections.size()); - } else { - client.clear(); - } - } - - return client; -} - -void SurfaceComposerClient::dispose() -{ - // this can be called more than once. - - sp<IMemory> controlMemory; - sp<ISurfaceFlingerClient> client; - sp<IMemoryHeap> surfaceHeap; - - { - Mutex::Autolock _lg(gLock); - Mutex::Autolock _lm(mLock); - - delete mSignalServer; - mSignalServer = 0; - - if (mClient != 0) { - client = mClient; - mClient.clear(); - - ssize_t i = gActiveConnections.indexOfKey(client->asBinder()); - if (i >= 0 && gActiveConnections.valueAt(i) == this) { - VERBOSE("Removing client %p from map at %d", this, int(i)); - gActiveConnections.removeItemsAt(i); - } - } - - delete mPrebuiltLayerState; - mPrebuiltLayerState = 0; - controlMemory = mControlMemory; - surfaceHeap = mSurfaceHeap; - mControlMemory.clear(); - mSurfaceHeap.clear(); - mControl = 0; - mStatus = NO_INIT; - } -} - -status_t SurfaceComposerClient::getDisplayInfo( - DisplayID dpy, DisplayInfo* info) -{ - if (uint32_t(dpy)>=NUM_DISPLAY_MAX) - return BAD_VALUE; - - volatile surface_flinger_cblk_t const * cblk = get_cblk(); - volatile display_cblk_t const * dcblk = cblk->displays + dpy; - - info->w = dcblk->w; - info->h = dcblk->h; - info->orientation = dcblk->orientation; - info->xdpi = dcblk->xdpi; - info->ydpi = dcblk->ydpi; - info->fps = dcblk->fps; - info->density = dcblk->density; - return getPixelFormatInfo(dcblk->format, &(info->pixelFormatInfo)); -} - -ssize_t SurfaceComposerClient::getDisplayWidth(DisplayID dpy) -{ - if (uint32_t(dpy)>=NUM_DISPLAY_MAX) - return BAD_VALUE; - volatile surface_flinger_cblk_t const * cblk = get_cblk(); - volatile display_cblk_t const * dcblk = cblk->displays + dpy; - return dcblk->w; -} - -ssize_t SurfaceComposerClient::getDisplayHeight(DisplayID dpy) -{ - if (uint32_t(dpy)>=NUM_DISPLAY_MAX) - return BAD_VALUE; - volatile surface_flinger_cblk_t const * cblk = get_cblk(); - volatile display_cblk_t const * dcblk = cblk->displays + dpy; - return dcblk->h; -} - -ssize_t SurfaceComposerClient::getDisplayOrientation(DisplayID dpy) -{ - if (uint32_t(dpy)>=NUM_DISPLAY_MAX) - return BAD_VALUE; - volatile surface_flinger_cblk_t const * cblk = get_cblk(); - volatile display_cblk_t const * dcblk = cblk->displays + dpy; - return dcblk->orientation; -} - -ssize_t SurfaceComposerClient::getNumberOfDisplays() -{ - volatile surface_flinger_cblk_t const * cblk = get_cblk(); - uint32_t connected = cblk->connected; - int n = 0; - while (connected) { - if (connected&1) n++; - connected >>= 1; - } - return n; -} - -sp<Surface> SurfaceComposerClient::createSurface( - int pid, - DisplayID display, - uint32_t w, - uint32_t h, - PixelFormat format, - uint32_t flags) -{ - sp<Surface> result; - if (mStatus == NO_ERROR) { - ISurfaceFlingerClient::surface_data_t data; - sp<ISurface> surface = mClient->createSurface(&data, pid, - display, w, h, format, flags); - if (surface != 0) { - if (uint32_t(data.token) < NUM_LAYERS_MAX) { - result = new Surface(this, surface, data, w, h, format, flags); - } - } - } - return result; -} - -status_t SurfaceComposerClient::destroySurface(SurfaceID sid) -{ - if (mStatus != NO_ERROR) - return mStatus; - - // it's okay to destroy a surface while a transaction is open, - // (transactions really are a client-side concept) - // however, this indicates probably a misuse of the API or a bug - // in the client code. - LOGW_IF(mTransactionOpen, - "Destroying surface while a transaction is open. " - "Client %p: destroying surface %d, mTransactionOpen=%d", - this, sid, mTransactionOpen); - - status_t err = mClient->destroySurface(sid); - return err; -} - -status_t SurfaceComposerClient::nextBuffer(Surface* surface, - Surface::SurfaceInfo* info) -{ - SurfaceID index = surface->ID(); - per_client_cblk_t* const cblk = mControl; - status_t err = validateSurface(cblk, surface); - if (err != NO_ERROR) - return err; - - int32_t backIdx = surface->mBackbufferIndex; - layer_cblk_t* const lcblk = &(cblk->layers[index]); - const surface_info_t* const front = lcblk->surface + (1-backIdx); - info->w = front->w; - info->h = front->h; - info->format = front->format; - info->base = surface->heapBase(1-backIdx); - info->bits = reinterpret_cast<void*>(intptr_t(info->base) + front->bits_offset); - info->bpr = front->bpr; - - return 0; -} - -status_t SurfaceComposerClient::lockSurface( - Surface* surface, - Surface::SurfaceInfo* other, - Region* dirty, - bool blocking) -{ - Mutex::Autolock _l(surface->getLock()); - - SurfaceID index = surface->ID(); - per_client_cblk_t* const cblk = mControl; - status_t err = validateSurface(cblk, surface); - if (err != NO_ERROR) - return err; - - int32_t backIdx = cblk->lock_layer(size_t(index), - per_client_cblk_t::BLOCKING); - if (backIdx >= 0) { - surface->mBackbufferIndex = backIdx; - layer_cblk_t* const lcblk = &(cblk->layers[index]); - const surface_info_t* const back = lcblk->surface + backIdx; - const surface_info_t* const front = lcblk->surface + (1-backIdx); - other->w = back->w; - other->h = back->h; - other->format = back->format; - other->base = surface->heapBase(backIdx); - other->bits = reinterpret_cast<void*>(intptr_t(other->base) + back->bits_offset); - other->bpr = back->bpr; - - const Rect bounds(other->w, other->h); - Region newDirtyRegion; - - if (back->flags & surface_info_t::eBufferDirty) { - /* it is safe to write *back here, because we're guaranteed - * SurfaceFlinger is not touching it (since it just granted - * access to us) */ - const_cast<surface_info_t*>(back)->flags &= - ~surface_info_t::eBufferDirty; - - // content is meaningless in this case and the whole surface - // needs to be redrawn. - - newDirtyRegion.set(bounds); - if (dirty) { - *dirty = newDirtyRegion; - } - - //if (bytesPerPixel(other->format) == 4) { - // android_memset32( - // (uint32_t*)other->bits, 0xFF00FF00, other->h * other->bpr); - //} else { - // android_memset16( // fill with green - // (uint16_t*)other->bits, 0x7E0, other->h * other->bpr); - //} - } - else - { - if (dirty) { - dirty->andSelf(Region(bounds)); - newDirtyRegion = *dirty; - } else { - newDirtyRegion.set(bounds); - } - - Region copyback; - if (!(lcblk->flags & eNoCopyBack)) { - const Region previousDirtyRegion(surface->dirtyRegion()); - copyback = previousDirtyRegion.subtract(newDirtyRegion); - } - - if (!copyback.isEmpty()) { - // copy front to back - GGLSurface cb; - cb.version = sizeof(GGLSurface); - cb.width = back->w; - cb.height = back->h; - cb.stride = back->stride; - cb.data = (GGLubyte*)surface->heapBase(backIdx); - cb.data += back->bits_offset; - cb.format = back->format; - - GGLSurface t; - t.version = sizeof(GGLSurface); - t.width = front->w; - t.height = front->h; - t.stride = front->stride; - t.data = (GGLubyte*)surface->heapBase(1-backIdx); - t.data += front->bits_offset; - t.format = front->format; - - //const Region copyback(lcblk->region + 1-backIdx); - copyBlt(cb, t, copyback); - } - } - - // update dirty region - surface->setDirtyRegion(newDirtyRegion); - } - return (backIdx < 0) ? status_t(backIdx) : status_t(NO_ERROR); -} - -void SurfaceComposerClient::_signal_server() -{ - mSignalServer->signal(); -} - -void SurfaceComposerClient::_send_dirty_region( - layer_cblk_t* lcblk, const Region& dirty) -{ - const int32_t index = (lcblk->flags & eBufferIndex) >> eBufferIndexShift; - flat_region_t* flat_region = lcblk->region + index; - status_t err = dirty.write(flat_region, sizeof(flat_region_t)); - if (err < NO_ERROR) { - // region doesn't fit, use the bounds - const Region reg(dirty.bounds()); - reg.write(flat_region, sizeof(flat_region_t)); - } -} - -status_t SurfaceComposerClient::unlockAndPostSurface(Surface* surface) -{ - Mutex::Autolock _l(surface->getLock()); - - SurfaceID index = surface->ID(); - per_client_cblk_t* const cblk = mControl; - status_t err = validateSurface(cblk, surface); - if (err != NO_ERROR) - return err; - - Region dirty(surface->dirtyRegion()); - const Rect& swapRect(surface->swapRectangle()); - if (swapRect.isValid()) { - dirty.set(swapRect); - } - - // transmit the dirty region - layer_cblk_t* const lcblk = &(cblk->layers[index]); - _send_dirty_region(lcblk, dirty); - uint32_t newstate = cblk->unlock_layer_and_post(size_t(index)); - if (!(newstate & eNextFlipPending)) - _signal_server(); - return NO_ERROR; -} - -status_t SurfaceComposerClient::unlockSurface(Surface* surface) -{ - Mutex::Autolock _l(surface->getLock()); - - SurfaceID index = surface->ID(); - per_client_cblk_t* const cblk = mControl; - status_t err = validateSurface(cblk, surface); - if (err != NO_ERROR) - return err; - - layer_cblk_t* const lcblk = &(cblk->layers[index]); - cblk->unlock_layer(size_t(index)); - return NO_ERROR; -} - -void SurfaceComposerClient::openGlobalTransaction() -{ - Mutex::Autolock _l(gLock); - - if (gOpenTransactions.size()) { - LOGE("openGlobalTransaction() called more than once. skipping."); - return; - } - - const size_t N = gActiveConnections.size(); - VERBOSE("openGlobalTransaction (%ld clients)", N); - for (size_t i=0; i<N; i++) { - sp<SurfaceComposerClient> client(gActiveConnections.valueAt(i)); - if (gOpenTransactions.indexOf(client) < 0) { - if (client->openTransaction() == NO_ERROR) { - if (gOpenTransactions.add(client) < 0) { - // Ooops! - LOGE( "Unable to add a SurfaceComposerClient " - "to the global transaction set (out of memory?)"); - client->closeTransaction(); - // let it go, it'll fail later when the user - // tries to do something with the transaction - } - } else { - LOGE("openTransaction on client %p failed", client.get()); - // let it go, it'll fail later when the user - // tries to do something with the transaction - } - } - } -} - -void SurfaceComposerClient::closeGlobalTransaction() -{ - gLock.lock(); - SortedVector< sp<SurfaceComposerClient> > clients(gOpenTransactions); - gOpenTransactions.clear(); - gLock.unlock(); - - const size_t N = clients.size(); - VERBOSE("closeGlobalTransaction (%ld clients)", N); - if (N == 1) { - clients[0]->closeTransaction(); - } else { - const sp<ISurfaceComposer>& sm(_get_surface_manager()); - sm->openGlobalTransaction(); - for (size_t i=0; i<N; i++) { - clients[i]->closeTransaction(); - } - sm->closeGlobalTransaction(); - } -} - -status_t SurfaceComposerClient::freezeDisplay(DisplayID dpy, uint32_t flags) -{ - const sp<ISurfaceComposer>& sm(_get_surface_manager()); - return sm->freezeDisplay(dpy, flags); -} - -status_t SurfaceComposerClient::unfreezeDisplay(DisplayID dpy, uint32_t flags) -{ - const sp<ISurfaceComposer>& sm(_get_surface_manager()); - return sm->unfreezeDisplay(dpy, flags); -} - -int SurfaceComposerClient::setOrientation(DisplayID dpy, int orientation) -{ - const sp<ISurfaceComposer>& sm(_get_surface_manager()); - return sm->setOrientation(dpy, orientation); -} - -status_t SurfaceComposerClient::openTransaction() -{ - if (mStatus != NO_ERROR) - return mStatus; - Mutex::Autolock _l(mLock); - VERBOSE( "openTransaction (client %p, mTransactionOpen=%d)", - this, mTransactionOpen); - mTransactionOpen++; - if (mPrebuiltLayerState == 0) { - mPrebuiltLayerState = new layer_state_t; - } - return NO_ERROR; -} - - -status_t SurfaceComposerClient::closeTransaction() -{ - if (mStatus != NO_ERROR) - return mStatus; - - Mutex::Autolock _l(mLock); - - VERBOSE( "closeTransaction (client %p, mTransactionOpen=%d)", - this, mTransactionOpen); - - if (mTransactionOpen <= 0) { - LOGE( "closeTransaction (client %p, mTransactionOpen=%d) " - "called more times than openTransaction()", - this, mTransactionOpen); - return INVALID_OPERATION; - } - - if (mTransactionOpen >= 2) { - mTransactionOpen--; - return NO_ERROR; - } - - mTransactionOpen = 0; - const ssize_t count = mStates.size(); - if (count) { - mClient->setState(count, mStates.array()); - mStates.clear(); - } - return NO_ERROR; -} - -layer_state_t* SurfaceComposerClient::_get_state_l(const sp<Surface>& surface) -{ - SurfaceID index = surface->ID(); - per_client_cblk_t* const cblk = mControl; - status_t err = validateSurface(cblk, surface.get()); - if (err != NO_ERROR) - return 0; - - // API usage error, do nothing. - if (mTransactionOpen<=0) { - LOGE("Not in transaction (client=%p, SurfaceID=%d, mTransactionOpen=%d", - this, int(index), mTransactionOpen); - return 0; - } - - // use mPrebuiltLayerState just to find out if we already have it - layer_state_t& dummy = *mPrebuiltLayerState; - dummy.surface = index; - ssize_t i = mStates.indexOf(dummy); - if (i < 0) { - // we don't have it, add an initialized layer_state to our list - i = mStates.add(dummy); - } - return mStates.editArray() + i; -} - -layer_state_t* SurfaceComposerClient::_lockLayerState(const sp<Surface>& surface) -{ - layer_state_t* s; - mLock.lock(); - s = _get_state_l(surface); - if (!s) mLock.unlock(); - return s; -} - -void SurfaceComposerClient::_unlockLayerState() -{ - mLock.unlock(); -} - -status_t SurfaceComposerClient::setPosition(Surface* surface, int32_t x, int32_t y) -{ - layer_state_t* s = _lockLayerState(surface); - if (!s) return BAD_INDEX; - s->what |= ISurfaceComposer::ePositionChanged; - s->x = x; - s->y = y; - _unlockLayerState(); - return NO_ERROR; -} - -status_t SurfaceComposerClient::setSize(Surface* surface, uint32_t w, uint32_t h) -{ - layer_state_t* s = _lockLayerState(surface); - if (!s) return BAD_INDEX; - s->what |= ISurfaceComposer::eSizeChanged; - s->w = w; - s->h = h; - _unlockLayerState(); - return NO_ERROR; -} - -status_t SurfaceComposerClient::setLayer(Surface* surface, int32_t z) -{ - layer_state_t* s = _lockLayerState(surface); - if (!s) return BAD_INDEX; - s->what |= ISurfaceComposer::eLayerChanged; - s->z = z; - _unlockLayerState(); - return NO_ERROR; -} - -status_t SurfaceComposerClient::hide(Surface* surface) -{ - return setFlags(surface, ISurfaceComposer::eLayerHidden, - ISurfaceComposer::eLayerHidden); -} - -status_t SurfaceComposerClient::show(Surface* surface, int32_t) -{ - return setFlags(surface, 0, ISurfaceComposer::eLayerHidden); -} - -status_t SurfaceComposerClient::freeze(Surface* surface) -{ - return setFlags(surface, ISurfaceComposer::eLayerFrozen, - ISurfaceComposer::eLayerFrozen); -} - -status_t SurfaceComposerClient::unfreeze(Surface* surface) -{ - return setFlags(surface, 0, ISurfaceComposer::eLayerFrozen); -} - -status_t SurfaceComposerClient::setFlags(Surface* surface, - uint32_t flags, uint32_t mask) -{ - layer_state_t* s = _lockLayerState(surface); - if (!s) return BAD_INDEX; - s->what |= ISurfaceComposer::eVisibilityChanged; - s->flags &= ~mask; - s->flags |= (flags & mask); - s->mask |= mask; - _unlockLayerState(); - return NO_ERROR; -} - - -status_t SurfaceComposerClient::setTransparentRegionHint( - Surface* surface, const Region& transparentRegion) -{ - layer_state_t* s = _lockLayerState(surface); - if (!s) return BAD_INDEX; - s->what |= ISurfaceComposer::eTransparentRegionChanged; - s->transparentRegion = transparentRegion; - _unlockLayerState(); - return NO_ERROR; -} - -status_t SurfaceComposerClient::setAlpha(Surface* surface, float alpha) -{ - layer_state_t* s = _lockLayerState(surface); - if (!s) return BAD_INDEX; - s->what |= ISurfaceComposer::eAlphaChanged; - s->alpha = alpha; - _unlockLayerState(); - return NO_ERROR; -} - -status_t SurfaceComposerClient::setMatrix( - Surface* surface, - float dsdx, float dtdx, - float dsdy, float dtdy ) -{ - layer_state_t* s = _lockLayerState(surface); - if (!s) return BAD_INDEX; - s->what |= ISurfaceComposer::eMatrixChanged; - layer_state_t::matrix22_t matrix; - matrix.dsdx = dsdx; - matrix.dtdx = dtdx; - matrix.dsdy = dsdy; - matrix.dtdy = dtdy; - s->matrix = matrix; - _unlockLayerState(); - return NO_ERROR; -} - -status_t SurfaceComposerClient::setFreezeTint(Surface* surface, uint32_t tint) -{ - layer_state_t* s = _lockLayerState(surface); - if (!s) return BAD_INDEX; - s->what |= ISurfaceComposer::eFreezeTintChanged; - s->tint = tint; - _unlockLayerState(); - return NO_ERROR; -} - -}; // namespace android - |