auto import from //depot/cupcake/@135843
diff --git a/libs/surfaceflinger/Layer.cpp b/libs/surfaceflinger/Layer.cpp
new file mode 100644
index 0000000..f65d669
--- /dev/null
+++ b/libs/surfaceflinger/Layer.cpp
@@ -0,0 +1,568 @@
+/*
+ * 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 "SurfaceFlinger"
+
+#include <stdlib.h>
+#include <stdint.h>
+#include <sys/types.h>
+
+#include <cutils/properties.h>
+
+#include <utils/Errors.h>
+#include <utils/Log.h>
+#include <utils/StopWatch.h>
+
+#include <ui/PixelFormat.h>
+#include <ui/EGLDisplaySurface.h>
+
+#include "clz.h"
+#include "Layer.h"
+#include "LayerBitmap.h"
+#include "SurfaceFlinger.h"
+#include "VRamHeap.h"
+#include "DisplayHardware/DisplayHardware.h"
+
+
+#define DEBUG_RESIZE    0
+
+
+namespace android {
+
+// ---------------------------------------------------------------------------
+
+const uint32_t Layer::typeInfo = LayerBaseClient::typeInfo | 4;
+const char* const Layer::typeID = "Layer";
+
+// ---------------------------------------------------------------------------
+
+Layer::Layer(SurfaceFlinger* flinger, DisplayID display, Client* c, int32_t i)
+    :   LayerBaseClient(flinger, display, c, i),
+        mSecure(false),
+        mFrontBufferIndex(1),
+        mNeedsBlending(true),
+        mResizeTransactionDone(false),
+        mTextureName(-1U), mTextureWidth(0), mTextureHeight(0)
+{
+    // no OpenGL operation is possible here, since we might not be
+    // in the OpenGL thread.
+}
+
+Layer::~Layer()
+{
+    client->free(clientIndex());
+    // this should always be called from the OpenGL thread
+    if (mTextureName != -1U) {
+        //glDeleteTextures(1, &mTextureName);
+        deletedTextures.add(mTextureName);
+    }
+}
+
+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::getSurface() const
+{
+    return mSurface;
+}
+
+status_t Layer::setBuffers( Client* client,
+                            uint32_t w, uint32_t h,
+                            PixelFormat format, uint32_t flags)
+{
+    PixelFormatInfo info;
+    status_t err = getPixelFormatInfo(format, &info);
+    if (err) return err;
+
+    // TODO: if eHardware is explicitly requested, we should fail
+    // on systems where we can't allocate memory that can be used with
+    // DMA engines for instance.
+    
+    // FIXME: we always ask for hardware for now (this should come from copybit)
+    flags |= ISurfaceComposer::eHardware;
+
+    const uint32_t memory_flags = flags & 
+            (ISurfaceComposer::eGPU | 
+             ISurfaceComposer::eHardware | 
+             ISurfaceComposer::eSecure);
+    
+    // pixel-alignment. the final alignment may be bigger because
+    // we always force a 4-byte aligned bpr.
+    uint32_t alignment = 1;
+
+    if (flags & ISurfaceComposer::eGPU) {
+        // FIXME: this value should come from the h/w
+        alignment = 8; 
+        // FIXME: this is msm7201A specific, as its GPU only supports
+        // BGRA_8888.
+        if (format == PIXEL_FORMAT_RGBA_8888) {
+            format = PIXEL_FORMAT_BGRA_8888;
+        }
+    }
+
+    mSecure = (flags & ISurfaceComposer::eSecure) ? true : false;
+    mNeedsBlending = (info.h_alpha - info.l_alpha) > 0;
+    sp<MemoryDealer> allocators[2];
+    for (int i=0 ; i<2 ; i++) {
+        allocators[i] = client->createAllocator(memory_flags);
+        if (allocators[i] == 0)
+            return NO_MEMORY;
+        mBuffers[i].init(allocators[i]);
+        int err = mBuffers[i].setBits(w, h, alignment, format, LayerBitmap::SECURE_BITS);
+        if (err != NO_ERROR)
+            return err;
+        mBuffers[i].clear(); // clear the bits for security
+        mBuffers[i].getInfo(lcblk->surface + i);
+    }
+
+    mSurface = new Surface(clientIndex(),
+            allocators[0]->getMemoryHeap(),
+            allocators[1]->getMemoryHeap(),
+            mIdentity);
+
+    return NO_ERROR;
+}
+
+void Layer::reloadTexture(const Region& dirty)
+{
+    if (UNLIKELY(mTextureName == -1U)) {
+        // create the texture name the first time
+        // can't do that in the ctor, because it runs in another thread.
+        mTextureName = createTexture();
+    }
+    const GGLSurface& t(frontBuffer().surface());
+    loadTexture(dirty, mTextureName, t, mTextureWidth, mTextureHeight);
+}
+
+
+void Layer::onDraw(const Region& clip) const
+{
+    if (UNLIKELY(mTextureName == -1LU)) {
+        //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;
+    }
+
+    const DisplayHardware& hw(graphicPlane(0).displayHardware());
+    const LayerBitmap& front(frontBuffer());
+    const GGLSurface& t(front.surface());
+
+    status_t err = NO_ERROR;
+    const int can_use_copybit = canUseCopybit();
+    if (can_use_copybit)  {
+        // StopWatch watch("copybit");
+        const State& s(drawingState());
+
+        copybit_image_t dst;
+        hw.getDisplaySurface(&dst);
+        const copybit_rect_t& drect
+            = reinterpret_cast<const copybit_rect_t&>(mTransformedBounds);
+
+        copybit_image_t src;
+        front.getBitmapSurface(&src);
+        copybit_rect_t srect = { 0, 0, t.width, t.height };
+
+        copybit_device_t* copybit = mFlinger->getBlitEngine();
+        copybit->set_parameter(copybit, COPYBIT_TRANSFORM, getOrientation());
+        copybit->set_parameter(copybit, COPYBIT_PLANE_ALPHA, s.alpha);
+        copybit->set_parameter(copybit, COPYBIT_DITHER,
+                s.flags & ISurfaceComposer::eLayerDither ?
+                        COPYBIT_ENABLE : COPYBIT_DISABLE);
+
+        region_iterator it(clip);
+        err = copybit->stretch(copybit, &dst, &src, &drect, &srect, &it);
+    }
+
+    if (!can_use_copybit || err) {
+        drawWithOpenGL(clip, mTextureName, t);
+    }
+}
+
+status_t Layer::reallocateBuffer(int32_t index, uint32_t w, uint32_t h)
+{
+    LOGD_IF(DEBUG_RESIZE,
+                "reallocateBuffer (layer=%p), "
+                "requested (%dx%d), "
+                "index=%d, (%dx%d), (%dx%d)",
+                this,
+                int(w), int(h),
+                int(index),
+                int(mBuffers[0].width()), int(mBuffers[0].height()),
+                int(mBuffers[1].width()), int(mBuffers[1].height()));
+
+    status_t err = mBuffers[index].resize(w, h);
+    if (err == NO_ERROR) {
+        mBuffers[index].getInfo(lcblk->surface + index);
+    } else {
+        LOGE("resizing buffer %d to (%u,%u) failed [%08x] %s",
+            index, w, h, err, strerror(err));
+        // XXX: what to do, what to do? We could try to free some
+        // hidden surfaces, instead of killing this one?
+    }
+    return err;
+}
+
+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. resze() 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].width()), int(mBuffers[0].height()),
+                int(mBuffers[1].width()), int(mBuffers[1].height()));
+        // 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.
+
+        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),
+                    int(drawingState().w), int(drawingState().h),
+                    int(clientBackBufferIndex),
+                    int(mBuffers[0].width()), int(mBuffers[0].height()),
+                    int(mBuffers[1].width()), int(mBuffers[1].height()));
+
+        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...
+                mFlinger->scheduleBroadcast(client);
+                mResizeTransactionDone = true;
+
+                // 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();
+                    }
+                }
+            }
+        }
+    }
+    
+    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
+            // (it may never redraw, which is fine if it is hidden)
+            mFreezeLock.clear();
+        }
+    }
+        
+    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)
+     */
+
+    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.width()  != width) ||
+                             (clientBackBuffer.height() != 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].width()), int(mBuffers[0].height()),
+            int(mBuffers[1].width()), int(mBuffers[1].height()));
+
+    // this can happen when changing the size back and forth quickly
+    status_t err = NO_ERROR;
+    if (backbufferChanged) {
+        err = reallocateBuffer(clientBackBufferIndex, width, height);
+    }
+    if (UNLIKELY(err != NO_ERROR)) {
+        // couldn't reallocate the surface
+        android_atomic_write(eInvalidSurface, &lcblk->swapState);
+        memset(lcblk->surface+clientBackBufferIndex, 0, sizeof(surface_info_t));
+    }
+    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));
+}
+
+// ----------------------------------------------------------------------------
+// pageflip handling...
+// ----------------------------------------------------------------------------
+
+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)
+        mFlinger->scheduleBroadcast(client);
+        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;
+
+    // ... post the new front-buffer
+    Region dirty(lcblk->region + index);
+    dirty.andSelf(frontBuffer().bounds());
+
+    //LOGI("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].width()), int(mBuffers[0].height()),
+                     int(mBuffers[1].width()), int(mBuffers[1].height()));
+
+        // 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
+{
+    const LayerBitmap& front(frontBuffer());
+    return Point(front.width(), front.height());
+}
+
+void Layer::unlockPageFlip(
+        const Transform& planeTransform, Region& outDirtyRegion)
+{
+    Region dirtyRegion(mPostedDirtyRegion);
+    if (!dirtyRegion.isEmpty()) {
+        mPostedDirtyRegion.clear();
+        // The dirty region is given in the layer's coordinate space
+        // transform the dirty region by the surface's transformation
+        // and the global transformation.
+        const Layer::State& s(drawingState());
+        const Transform tr(planeTransform * s.transform);
+        dirtyRegion = tr.transform(dirtyRegion);
+
+        // At this point, the dirty region is in screen space.
+        // Make sure it's constrained by the visible region (which
+        // 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.
+        mFlinger->scheduleBroadcast(client);
+    }
+}
+
+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));
+    }
+    mFlinger->scheduleBroadcast(client);
+}
+
+
+// ---------------------------------------------------------------------------
+
+
+}; // namespace android