Merge changes Id79430f9,I541d3046

* changes:
  BufferQueue: check before tracing buffer index
  SurfaceTexture: shrink all sides when cropping
diff --git a/include/gui/SurfaceTextureClient.h b/include/gui/SurfaceTextureClient.h
index c0e90b3..6644751 100644
--- a/include/gui/SurfaceTextureClient.h
+++ b/include/gui/SurfaceTextureClient.h
@@ -26,6 +26,7 @@
 
 #include <utils/RefBase.h>
 #include <utils/threads.h>
+#include <utils/KeyedVector.h>
 
 struct ANativeWindow_Buffer;
 
@@ -113,6 +114,11 @@
     void freeAllBuffers();
     int getSlotFromBufferLocked(android_native_buffer_t* buffer) const;
 
+    struct BufferSlot {
+        sp<GraphicBuffer> buffer;
+        Region dirtyRegion;
+    };
+
     // mSurfaceTexture is the interface to the surface texture server. All
     // operations on the surface texture client ultimately translate into
     // interactions with the server using this interface.
@@ -124,7 +130,7 @@
     // slot that has not yet been used. The buffer allocated to a slot will also
     // be replaced if the requested buffer usage or geometry differs from that
     // of the buffer allocated to a slot.
-    sp<GraphicBuffer> mSlots[NUM_BUFFER_SLOTS];
+    BufferSlot mSlots[NUM_BUFFER_SLOTS];
 
     // mReqWidth is the buffer width that will be requested at the next dequeue
     // operation. It is initialized to 1.
@@ -189,8 +195,10 @@
     // must be used from the lock/unlock thread
     sp<GraphicBuffer>           mLockedBuffer;
     sp<GraphicBuffer>           mPostedBuffer;
-    mutable Region              mOldDirtyRegion;
     bool                        mConnectedToCpu;
+
+    // must be accessed from lock/unlock thread only
+    Region mDirtyRegion;
 };
 
 }; // namespace android
diff --git a/include/private/ui/RegionHelper.h b/include/private/ui/RegionHelper.h
index 8d76533..421bdda 100644
--- a/include/private/ui/RegionHelper.h
+++ b/include/private/ui/RegionHelper.h
@@ -96,6 +96,11 @@
     class SpannerBase
     {
     public:
+        SpannerBase()
+            : lhs_head(max_value), lhs_tail(max_value),
+              rhs_head(max_value), rhs_tail(max_value) {
+        }
+
         enum {
             lhs_before_rhs   = 0,
             lhs_after_rhs    = 1,
@@ -158,12 +163,16 @@
 
     public:
         inline Spanner(const region& lhs, const region& rhs)
-            : lhs(lhs), rhs(rhs) 
+        : lhs(lhs), rhs(rhs)
         {
-            SpannerBase::lhs_head = lhs.rects->top      + lhs.dy;
-            SpannerBase::lhs_tail = lhs.rects->bottom   + lhs.dy;
-            SpannerBase::rhs_head = rhs.rects->top      + rhs.dy;
-            SpannerBase::rhs_tail = rhs.rects->bottom   + rhs.dy;
+            if (lhs.count) {
+                SpannerBase::lhs_head = lhs.rects->top      + lhs.dy;
+                SpannerBase::lhs_tail = lhs.rects->bottom   + lhs.dy;
+            }
+            if (rhs.count) {
+                SpannerBase::rhs_head = rhs.rects->top      + rhs.dy;
+                SpannerBase::rhs_tail = rhs.rects->bottom   + rhs.dy;
+            }
         }
 
         inline bool isDone() const {
@@ -221,20 +230,28 @@
 
         inline void prepare(int inside) {
             if (inside == SpannerBase::lhs_before_rhs) {
-                SpannerBase::lhs_head = lhs.rects->left  + lhs.dx;
-                SpannerBase::lhs_tail = lhs.rects->right + lhs.dx;
+                if (lhs.count) {
+                    SpannerBase::lhs_head = lhs.rects->left  + lhs.dx;
+                    SpannerBase::lhs_tail = lhs.rects->right + lhs.dx;
+                }
                 SpannerBase::rhs_head = max_value;
                 SpannerBase::rhs_tail = max_value;
             } else if (inside == SpannerBase::lhs_after_rhs) {
                 SpannerBase::lhs_head = max_value;
                 SpannerBase::lhs_tail = max_value;
-                SpannerBase::rhs_head = rhs.rects->left  + rhs.dx;
-                SpannerBase::rhs_tail = rhs.rects->right + rhs.dx;
+                if (rhs.count) {
+                    SpannerBase::rhs_head = rhs.rects->left  + rhs.dx;
+                    SpannerBase::rhs_tail = rhs.rects->right + rhs.dx;
+                }
             } else {
-                SpannerBase::lhs_head = lhs.rects->left  + lhs.dx;
-                SpannerBase::lhs_tail = lhs.rects->right + lhs.dx;
-                SpannerBase::rhs_head = rhs.rects->left  + rhs.dx;
-                SpannerBase::rhs_tail = rhs.rects->right + rhs.dx;
+                if (lhs.count) {
+                    SpannerBase::lhs_head = lhs.rects->left  + lhs.dx;
+                    SpannerBase::lhs_tail = lhs.rects->right + lhs.dx;
+                }
+                if (rhs.count) {
+                    SpannerBase::rhs_head = rhs.rects->left  + rhs.dx;
+                    SpannerBase::rhs_tail = rhs.rects->right + rhs.dx;
+                }
             }
         }
 
diff --git a/include/utils/Trace.h b/include/utils/Trace.h
index a2429c0..637c146 100644
--- a/include/utils/Trace.h
+++ b/include/utils/Trace.h
@@ -45,7 +45,8 @@
 #define ATRACE_TAG_GRAPHICS (1<<1)
 #define ATRACE_TAG_INPUT    (1<<2)
 #define ATRACE_TAG_VIEW     (1<<3)
-#define ATRACE_TAG_LAST     ATRACE_TAG_VIEW
+#define ATRACE_TAG_WEBVIEW  (1<<4)
+#define ATRACE_TAG_LAST     ATRACE_TAG_WEBVIEW
 
 #define ATRACE_TAG_VALID_MASK ((ATRACE_TAG_LAST - 1) | ATRACE_TAG_LAST)
 
diff --git a/libs/binder/ProcessState.cpp b/libs/binder/ProcessState.cpp
index 9fa412c..5399e52 100644
--- a/libs/binder/ProcessState.cpp
+++ b/libs/binder/ProcessState.cpp
@@ -73,10 +73,11 @@
 
 sp<ProcessState> ProcessState::self()
 {
-    if (gProcess != NULL) return gProcess;
-    
-    AutoMutex _l(gProcessMutex);
-    if (gProcess == NULL) gProcess = new ProcessState;
+    Mutex::Autolock _l(gProcessMutex);
+    if (gProcess != NULL) {
+        return gProcess;
+    }
+    gProcess = new ProcessState;
     return gProcess;
 }
 
diff --git a/libs/gui/SurfaceTextureClient.cpp b/libs/gui/SurfaceTextureClient.cpp
index 99c025f..b37d821 100644
--- a/libs/gui/SurfaceTextureClient.cpp
+++ b/libs/gui/SurfaceTextureClient.cpp
@@ -171,7 +171,7 @@
              result);
         return result;
     }
-    sp<GraphicBuffer>& gbuf(mSlots[buf]);
+    sp<GraphicBuffer>& gbuf(mSlots[buf].buffer);
     if (result & ISurfaceTexture::RELEASE_ALL_BUFFERS) {
         freeAllBuffers();
     }
@@ -204,7 +204,8 @@
         android_native_buffer_t* buffer) const {
     bool dumpedState = false;
     for (int i = 0; i < NUM_BUFFER_SLOTS; i++) {
-        if (mSlots[i] != NULL && mSlots[i]->handle == buffer->handle) {
+        if (mSlots[i].buffer != NULL &&
+                mSlots[i].buffer->handle == buffer->handle) {
             return i;
         }
     }
@@ -586,7 +587,7 @@
 
 void SurfaceTextureClient::freeAllBuffers() {
     for (int i = 0; i < NUM_BUFFER_SLOTS; i++) {
-        mSlots[i] = 0;
+        mSlots[i].buffer = 0;
     }
 }
 
@@ -691,19 +692,32 @@
 
             if (canCopyBack) {
                 // copy the area that is invalid and not repainted this round
-                const Region copyback(mOldDirtyRegion.subtract(newDirtyRegion));
+                const Region copyback(mDirtyRegion.subtract(newDirtyRegion));
                 if (!copyback.isEmpty())
                     copyBlt(backBuffer, frontBuffer, copyback);
             } else {
                 // if we can't copy-back anything, modify the user's dirty
                 // region to make sure they redraw the whole buffer
                 newDirtyRegion.set(bounds);
+                mDirtyRegion.clear();
+                Mutex::Autolock lock(mMutex);
+                for (size_t i=0 ; i<NUM_BUFFER_SLOTS ; i++) {
+                    mSlots[i].dirtyRegion.clear();
+                }
             }
 
-            // keep track of the are of the buffer that is "clean"
-            // (ie: that will be redrawn)
-            mOldDirtyRegion = newDirtyRegion;
 
+            { // scope for the lock
+                Mutex::Autolock lock(mMutex);
+                int backBufferSlot(getSlotFromBufferLocked(backBuffer.get()));
+                if (backBufferSlot >= 0) {
+                    Region& dirtyRegion(mSlots[backBufferSlot].dirtyRegion);
+                    mDirtyRegion.subtract(dirtyRegion);
+                    dirtyRegion = newDirtyRegion;
+                }
+            }
+
+            mDirtyRegion.orSelf(newDirtyRegion);
             if (inOutDirtyBounds) {
                 *inOutDirtyBounds = newDirtyRegion.getBounds();
             }
diff --git a/libs/ui/Region.cpp b/libs/ui/Region.cpp
index 6e2e731..2c7cdf0 100644
--- a/libs/ui/Region.cpp
+++ b/libs/ui/Region.cpp
@@ -619,7 +619,15 @@
 }
 
 Region::const_iterator Region::end() const {
-    return isRect() ? ((&mBounds) + 1) : (mStorage.array() + mStorage.size());
+    if (isRect()) {
+        if (isEmpty()) {
+            return &mBounds;
+        } else {
+            return &mBounds + 1;
+        }
+    } else {
+        return mStorage.array() + mStorage.size();
+    }
 }
 
 Rect const* Region::getArray(size_t* count) const {
diff --git a/services/surfaceflinger/DisplayHardware/DisplayHardware.cpp b/services/surfaceflinger/DisplayHardware/DisplayHardware.cpp
index c46e630..48651b6 100644
--- a/services/surfaceflinger/DisplayHardware/DisplayHardware.cpp
+++ b/services/surfaceflinger/DisplayHardware/DisplayHardware.cpp
@@ -280,12 +280,6 @@
                 EGL_SWAP_BEHAVIOR, EGL_BUFFER_DESTROYED);
     }
 
-    if (eglQuerySurface(display, surface, EGL_SWAP_BEHAVIOR, &dummy) == EGL_TRUE) {
-        if (dummy == EGL_BUFFER_PRESERVED) {
-            mFlags |= BUFFER_PRESERVED;
-        }
-    }
-
     /*
      * Create our OpenGL ES context
      */
diff --git a/services/surfaceflinger/DisplayHardware/DisplayHardware.h b/services/surfaceflinger/DisplayHardware/DisplayHardware.h
index 84a3eff..f1dee91 100644
--- a/services/surfaceflinger/DisplayHardware/DisplayHardware.h
+++ b/services/surfaceflinger/DisplayHardware/DisplayHardware.h
@@ -51,7 +51,6 @@
 
     enum {
         COPY_BITS_EXTENSION         = 0x00000008,
-        BUFFER_PRESERVED            = 0x00010000,
         PARTIAL_UPDATES             = 0x00020000,   // video driver feature
         SLOW_CONFIG                 = 0x00040000,   // software
         SWAP_RECTANGLE              = 0x00080000,
diff --git a/services/surfaceflinger/LayerBase.cpp b/services/surfaceflinger/LayerBase.cpp
index e764001..694ecde 100644
--- a/services/surfaceflinger/LayerBase.cpp
+++ b/services/surfaceflinger/LayerBase.cpp
@@ -43,7 +43,7 @@
     : dpy(display), contentDirty(false),
       sequence(uint32_t(android_atomic_inc(&sSequence))),
       mFlinger(flinger), mFiltering(false),
-      mNeedsFiltering(false), mInOverlay(false),
+      mNeedsFiltering(false),
       mOrientation(0),
       mPlaneOrientation(0),
       mTransactionFlags(0),
@@ -231,7 +231,9 @@
     const uint32_t hw_h = hw.getHeight();
 
     uint32_t w = s.w;
-    uint32_t h = s.h;    
+    uint32_t h = s.h;
+
+    mNumVertices = 4;
     tr.transform(mVertices[0], 0, 0);
     tr.transform(mVertices[1], 0, h);
     tr.transform(mVertices[2], w, h);
@@ -268,27 +270,6 @@
         const Transform& planeTransform, Region& outDirtyRegion) {
 }
 
-void LayerBase::drawRegion(const Region& reg) const
-{
-    Region::const_iterator it = reg.begin();
-    Region::const_iterator const end = reg.end();
-    if (it != end) {
-        Rect r;
-        const DisplayHardware& hw(graphicPlane(0).displayHardware());
-        const int32_t fbWidth  = hw.getWidth();
-        const int32_t fbHeight = hw.getHeight();
-        const GLshort vertices[][2] = { { 0, 0 }, { fbWidth, 0 }, 
-                { fbWidth, fbHeight }, { 0, fbHeight }  };
-        glVertexPointer(2, GL_SHORT, 0, vertices);
-        while (it != end) {
-            const Rect& r = *it++;
-            const GLint sy = fbHeight - (r.top + r.height());
-            glScissor(r.left, sy, r.width(), r.height());
-            glDrawArrays(GL_TRIANGLE_FAN, 0, 4); 
-        }
-    }
-}
-
 void LayerBase::setGeometry(hwc_layer_t* hwcl)
 {
     hwcl->compositionType = HWC_FRAMEBUFFER;
@@ -333,14 +314,6 @@
     hwcl->handle = NULL;
 }
 
-void LayerBase::setOverlay(bool inOverlay) {
-    mInOverlay = inOverlay;
-}
-
-bool LayerBase::isOverlay() const {
-    return mInOverlay;
-}
-
 void LayerBase::setFiltering(bool filtering)
 {
     mFiltering = filtering;
@@ -353,9 +326,6 @@
 
 void LayerBase::draw(const Region& clip) const
 {
-    // reset GL state
-    glEnable(GL_SCISSOR_TEST);
-
     onDraw(clip);
 }
 
@@ -379,16 +349,8 @@
     glDisable(GL_TEXTURE_2D);
     glDisable(GL_BLEND);
 
-    Region::const_iterator it = clip.begin();
-    Region::const_iterator const end = clip.end();
-    glEnable(GL_SCISSOR_TEST);
     glVertexPointer(2, GL_FLOAT, 0, mVertices);
-    while (it != end) {
-        const Rect& r = *it++;
-        const GLint sy = fbHeight - (r.top + r.height());
-        glScissor(r.left, sy, r.width(), r.height());
-        glDrawArrays(GL_TRIANGLE_FAN, 0, 4); 
-    }
+    glDrawArrays(GL_TRIANGLE_FAN, 0, mNumVertices);
 }
 
 void LayerBase::clearWithOpenGL(const Region& clip) const
@@ -442,15 +404,8 @@
     glEnableClientState(GL_TEXTURE_COORD_ARRAY);
     glVertexPointer(2, GL_FLOAT, 0, mVertices);
     glTexCoordPointer(2, GL_FLOAT, 0, texCoords);
+    glDrawArrays(GL_TRIANGLE_FAN, 0, mNumVertices);
 
-    Region::const_iterator it = clip.begin();
-    Region::const_iterator const end = clip.end();
-    while (it != end) {
-        const Rect& r = *it++;
-        const GLint sy = fbHeight - (r.top + r.height());
-        glScissor(r.left, sy, r.width(), r.height());
-        glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
-    }
     glDisableClientState(GL_TEXTURE_COORD_ARRAY);
     glDisable(GL_BLEND);
 }
diff --git a/services/surfaceflinger/LayerBase.h b/services/surfaceflinger/LayerBase.h
index cd6efdd..d123d9b 100644
--- a/services/surfaceflinger/LayerBase.h
+++ b/services/surfaceflinger/LayerBase.h
@@ -100,7 +100,6 @@
             uint32_t setTransactionFlags(uint32_t flags);
             
             Rect visibleBounds() const;
-            void drawRegion(const Region& reg) const;
 
     virtual sp<LayerBaseClient> getLayerBaseClient() const { return 0; }
     virtual sp<Layer> getLayer() const { return 0; }
@@ -109,8 +108,6 @@
 
     virtual void setGeometry(hwc_layer_t* hwcl);
     virtual void setPerFrameData(hwc_layer_t* hwcl);
-            void setOverlay(bool inOverlay);
-            bool isOverlay() const;
 
 
     /**
@@ -230,14 +227,15 @@
 
     int32_t  getOrientation() const { return mOrientation; }
     int32_t  getPlaneOrientation() const { return mPlaneOrientation; }
-    
+
+    void clearWithOpenGL(const Region& clip) const;
+
 protected:
     const GraphicPlane& graphicPlane(int dpy) const;
           GraphicPlane& graphicPlane(int dpy);
 
           void clearWithOpenGL(const Region& clip, GLclampf r, GLclampf g,
                                GLclampf b, GLclampf alpha) const;
-          void clearWithOpenGL(const Region& clip) const;
           void drawWithOpenGL(const Region& clip) const;
 
           void setFiltering(bool filtering);
@@ -255,17 +253,13 @@
                 // Whether filtering is needed b/c of the drawingstate
                 bool            mNeedsFiltering;
 
-                // this layer is currently handled by the hwc. this is
-                // updated at composition time, always frmo the composition
-                // thread.
-                bool            mInOverlay;
-
 protected:
                 // cached during validateVisibility()
                 int32_t         mOrientation;
                 int32_t         mPlaneOrientation;
                 Transform       mTransform;
                 GLfloat         mVertices[4][2];
+                size_t          mNumVertices;
                 Rect            mTransformedBounds;
             
                 // these are protected by an external lock
diff --git a/services/surfaceflinger/LayerDim.cpp b/services/surfaceflinger/LayerDim.cpp
index e665d7a..96a310f 100644
--- a/services/surfaceflinger/LayerDim.cpp
+++ b/services/surfaceflinger/LayerDim.cpp
@@ -43,9 +43,7 @@
 void LayerDim::onDraw(const Region& clip) const
 {
     const State& s(drawingState());
-    Region::const_iterator it = clip.begin();
-    Region::const_iterator const end = clip.end();
-    if (s.alpha>0 && (it != end)) {
+    if (s.alpha>0) {
         const DisplayHardware& hw(graphicPlane(0).displayHardware());
         const GLfloat alpha = s.alpha/255.0f;
         const uint32_t fbHeight = hw.getHeight();
@@ -62,13 +60,8 @@
         glColor4f(0, 0, 0, alpha);
 
         glVertexPointer(2, GL_FLOAT, 0, mVertices);
+        glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
 
-        while (it != end) {
-            const Rect& r = *it++;
-            const GLint sy = fbHeight - (r.top + r.height());
-            glScissor(r.left, sy, r.width(), r.height());
-            glDrawArrays(GL_TRIANGLE_FAN, 0, 4); 
-        }
         glDisable(GL_BLEND);
         glDisableClientState(GL_TEXTURE_COORD_ARRAY);
     }
diff --git a/services/surfaceflinger/LayerScreenshot.cpp b/services/surfaceflinger/LayerScreenshot.cpp
index c7cf46e..b42353c 100644
--- a/services/surfaceflinger/LayerScreenshot.cpp
+++ b/services/surfaceflinger/LayerScreenshot.cpp
@@ -70,8 +70,6 @@
     glBindTexture(GL_TEXTURE_2D, mTextureName);
     glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
     glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
-    glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
-    glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
     mTexCoords[0] = 0;         mTexCoords[1] = v;
     mTexCoords[2] = 0;         mTexCoords[3] = 0;
     mTexCoords[4] = u;         mTexCoords[5] = 0;
@@ -111,9 +109,7 @@
 void LayerScreenshot::onDraw(const Region& clip) const
 {
     const State& s(drawingState());
-    Region::const_iterator it = clip.begin();
-    Region::const_iterator const end = clip.end();
-    if (s.alpha>0 && (it != end)) {
+    if (s.alpha>0) {
         const DisplayHardware& hw(graphicPlane(0).displayHardware());
         const GLfloat alpha = s.alpha/255.0f;
         const uint32_t fbHeight = hw.getHeight();
@@ -139,13 +135,7 @@
         glEnableClientState(GL_TEXTURE_COORD_ARRAY);
         glTexCoordPointer(2, GL_FLOAT, 0, mTexCoords);
         glVertexPointer(2, GL_FLOAT, 0, mVertices);
-
-        while (it != end) {
-            const Rect& r = *it++;
-            const GLint sy = fbHeight - (r.top + r.height());
-            glScissor(r.left, sy, r.width(), r.height());
-            glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
-        }
+        glDrawArrays(GL_TRIANGLE_FAN, 0, mNumVertices);
 
         glDisable(GL_BLEND);
         glDisable(GL_TEXTURE_2D);
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index fb0c305..93dd3a4 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -265,7 +265,6 @@
     glPixelStorei(GL_UNPACK_ALIGNMENT, 4);
     glPixelStorei(GL_PACK_ALIGNMENT, 4);
     glEnableClientState(GL_VERTEX_ARRAY);
-    glEnable(GL_SCISSOR_TEST);
     glShadeModel(GL_FLAT);
     glDisable(GL_DITHER);
     glDisable(GL_CULL_FACE);
@@ -834,22 +833,11 @@
     glLoadIdentity();
 
     uint32_t flags = hw.getFlags();
-    if ((flags & DisplayHardware::SWAP_RECTANGLE) ||
-        (flags & DisplayHardware::BUFFER_PRESERVED))
-    {
+    if (flags & DisplayHardware::SWAP_RECTANGLE) {
         // we can redraw only what's dirty, but since SWAP_RECTANGLE only
         // takes a rectangle, we must make sure to update that whole
         // rectangle in that case
-        if (flags & DisplayHardware::SWAP_RECTANGLE) {
-            // 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(mSwapRegion.bounds());
-        } else {
-            // in the BUFFER_PRESERVED case, obviously, we can update only
-            // what's needed and nothing more.
-            // NOTE: this is NOT a common case, as preserving the backbuffer
-            // is costly and usually involves copying the whole update back.
-        }
+        mDirtyRegion.set(mSwapRegion.bounds());
     } else {
         if (flags & DisplayHardware::PARTIAL_UPDATES) {
             // We need to redraw the rectangle that will be updated
@@ -864,7 +852,7 @@
         }
     }
 
-    setupHardwareComposer(mDirtyRegion);
+    setupHardwareComposer();
     composeSurfaces(mDirtyRegion);
 
     // update the swap region and clear the dirty region
@@ -872,7 +860,7 @@
     mDirtyRegion.clear();
 }
 
-void SurfaceFlinger::setupHardwareComposer(Region& dirtyInOut)
+void SurfaceFlinger::setupHardwareComposer()
 {
     const DisplayHardware& hw(graphicPlane(0).displayHardware());
     HWComposer& hwc(hw.getHwComposer());
@@ -901,75 +889,8 @@
         const sp<LayerBase>& layer(layers[i]);
         layer->setPerFrameData(&cur[i]);
     }
-    const size_t fbLayerCount = hwc.getLayerCount(HWC_FRAMEBUFFER);
     status_t err = hwc.prepare();
     ALOGE_IF(err, "HWComposer::prepare failed (%s)", strerror(-err));
-
-    if (err == NO_ERROR) {
-        // what's happening here is tricky.
-        // we want to clear all the layers with the CLEAR_FB flags
-        // that are opaque.
-        // however, since some GPU are efficient at preserving
-        // the backbuffer, we want to take advantage of that so we do the
-        // clear only in the dirty region (other areas will be preserved
-        // on those GPUs).
-        //   NOTE: on non backbuffer preserving GPU, the dirty region
-        //   has already been expanded as needed, so the code is correct
-        //   there too.
-        //
-        // However, the content of the framebuffer cannot be trusted when
-        // we switch to/from FB/OVERLAY, in which case we need to
-        // expand the dirty region to those areas too.
-        //
-        // Note also that there is a special case when switching from
-        // "no layers in FB" to "some layers in FB", where we need to redraw
-        // the entire FB, since some areas might contain uninitialized
-        // data.
-        //
-        // Also we want to make sure to not clear areas that belong to
-        // layers above that won't redraw (we would just be erasing them),
-        // that is, we can't erase anything outside the dirty region.
-
-        Region transparent;
-
-        if (!fbLayerCount && hwc.getLayerCount(HWC_FRAMEBUFFER)) {
-            transparent.set(hw.getBounds());
-            dirtyInOut = transparent;
-        } else {
-            for (size_t i=0 ; i<count ; i++) {
-                const sp<LayerBase>& layer(layers[i]);
-                if ((cur[i].hints & HWC_HINT_CLEAR_FB) && layer->isOpaque()) {
-                    transparent.orSelf(layer->visibleRegionScreen);
-                }
-                bool isOverlay = (cur[i].compositionType != HWC_FRAMEBUFFER);
-                if (isOverlay != layer->isOverlay()) {
-                    // we transitioned to/from overlay, so add this layer
-                    // to the dirty region so the framebuffer can be either
-                    // cleared or redrawn.
-                    dirtyInOut.orSelf(layer->visibleRegionScreen);
-                }
-                layer->setOverlay(isOverlay);
-            }
-            // don't erase stuff outside the dirty region
-            transparent.andSelf(dirtyInOut);
-        }
-
-        /*
-         *  clear the area of the FB that need to be transparent
-         */
-        if (!transparent.isEmpty()) {
-            glClearColor(0,0,0,0);
-            Region::const_iterator it = transparent.begin();
-            Region::const_iterator const end = transparent.end();
-            const int32_t height = hw.getHeight();
-            while (it != end) {
-                const Rect& r(*it++);
-                const GLint sy = height - (r.top + r.height());
-                glScissor(r.left, sy, r.width(), r.height());
-                glClear(GL_COLOR_BUFFER_BIT);
-            }
-        }
-    }
 }
 
 void SurfaceFlinger::composeSurfaces(const Region& dirty)
@@ -978,45 +899,38 @@
     HWComposer& hwc(hw.getHwComposer());
 
     const size_t fbLayerCount = hwc.getLayerCount(HWC_FRAMEBUFFER);
-    if (CC_UNLIKELY(fbLayerCount && !mWormholeRegion.isEmpty())) {
-        // should never happen unless the window manager has a bug
-        // draw something...
-        drawWormhole();
-    }
+    if (fbLayerCount) {
+        // Never touch the framebuffer if we don't have any framebuffer layers
 
-    /*
-     * and then, render the layers targeted at the framebuffer
-     */
+        if (!mWormholeRegion.isEmpty()) {
+            // can happen with SurfaceView
+            drawWormhole();
+        }
 
-    hwc_layer_t* const cur(hwc.getLayers());
-    const Vector< sp<LayerBase> >& layers(mVisibleLayersSortedByZ);
-    size_t count = layers.size();
+        /*
+         * and then, render the layers targeted at the framebuffer
+         */
 
+        hwc_layer_t* const cur(hwc.getLayers());
+        const Vector< sp<LayerBase> >& layers(mVisibleLayersSortedByZ);
+        const size_t count = layers.size();
 
-    // FIXME: workaround for b/6020860
-    if (hw.getFlags() & DisplayHardware::BUFFER_PRESERVED) {
         for (size_t i=0 ; i<count ; i++) {
-            if (cur && (cur[i].compositionType == HWC_FRAMEBUFFER)) {
-                glEnable(GL_SCISSOR_TEST);
-                glScissor(0,0,0,0);
-                glClear(GL_COLOR_BUFFER_BIT);
-                break;
+            const sp<LayerBase>& layer(layers[i]);
+            const Region clip(dirty.intersect(layer->visibleRegionScreen));
+            if (!clip.isEmpty()) {
+                if (cur && (cur[i].compositionType != HWC_FRAMEBUFFER)) {
+                    if ((cur[i].hints & HWC_HINT_CLEAR_FB)
+                            && layer->isOpaque()) {
+                        layer->clearWithOpenGL(clip);
+                    }
+                    continue;
+                }
+                // render the layer
+                layer->draw(clip);
             }
         }
     }
-    // FIXME: bug6020860 for b/6020860
-
-
-    for (size_t i=0 ; i<count ; i++) {
-        if (cur && (cur[i].compositionType != HWC_FRAMEBUFFER)) {
-            continue;
-        }
-        const sp<LayerBase>& layer(layers[i]);
-        const Region clip(dirty.intersect(layer->visibleRegionScreen));
-        if (!clip.isEmpty()) {
-            layer->draw(clip);
-        }
-    }
 }
 
 void SurfaceFlinger::debugFlashRegions()
@@ -1028,8 +942,7 @@
         return;
     }
 
-    if (!((flags & DisplayHardware::SWAP_RECTANGLE) ||
-            (flags & DisplayHardware::BUFFER_PRESERVED))) {
+    if (!(flags & DisplayHardware::SWAP_RECTANGLE)) {
         const Region repaint((flags & DisplayHardware::PARTIAL_UPDATES) ?
                 mDirtyRegion.bounds() : hw.bounds());
         composeSurfaces(repaint);
@@ -1066,8 +979,6 @@
 
     if (mDebugRegion > 1)
         usleep(mDebugRegion * 1000);
-
-    glEnable(GL_SCISSOR_TEST);
 }
 
 void SurfaceFlinger::drawWormhole() const
@@ -1076,52 +987,48 @@
     if (region.isEmpty())
         return;
 
-    const DisplayHardware& hw(graphicPlane(0).displayHardware());
-    const int32_t width = hw.getWidth();
-    const int32_t height = hw.getHeight();
+    glDisable(GL_TEXTURE_EXTERNAL_OES);
+    glDisable(GL_BLEND);
 
     if (CC_LIKELY(!mDebugBackground)) {
-        glClearColor(0,0,0,0);
-        Region::const_iterator it = region.begin();
-        Region::const_iterator const end = region.end();
-        while (it != end) {
-            const Rect& r = *it++;
-            const GLint sy = height - (r.top + r.height());
-            glScissor(r.left, sy, r.width(), r.height());
-            glClear(GL_COLOR_BUFFER_BIT);
-        }
+        glDisable(GL_TEXTURE_2D);
+        glColor4f(0,0,0,0);
     } else {
-        const GLshort vertices[][2] = { { 0, 0 }, { width, 0 },
-                { width, height }, { 0, height }  };
-        const GLshort tcoords[][2] = { { 0, 0 }, { 1, 0 },  { 1, 1 }, { 0, 1 } };
-
-        glVertexPointer(2, GL_SHORT, 0, vertices);
-        glTexCoordPointer(2, GL_SHORT, 0, tcoords);
+        const DisplayHardware& hw(graphicPlane(0).displayHardware());
+        const int32_t width = hw.getWidth();
+        const int32_t height = hw.getHeight();
+        const GLfloat tcoords[][2] = { { 0, 0 }, { 1, 0 },  { 1, 1 }, { 0, 1 } };
+        glTexCoordPointer(2, GL_FLOAT, 0, tcoords);
         glEnableClientState(GL_TEXTURE_COORD_ARRAY);
-
-        glDisable(GL_TEXTURE_EXTERNAL_OES);
         glEnable(GL_TEXTURE_2D);
         glBindTexture(GL_TEXTURE_2D, mWormholeTexName);
         glTexEnvx(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
         glMatrixMode(GL_TEXTURE);
         glLoadIdentity();
-
-        glDisable(GL_BLEND);
-
         glScalef(width*(1.0f/32.0f), height*(1.0f/32.0f), 1);
-        Region::const_iterator it = region.begin();
-        Region::const_iterator const end = region.end();
-        while (it != end) {
-            const Rect& r = *it++;
-            const GLint sy = height - (r.top + r.height());
-            glScissor(r.left, sy, r.width(), r.height());
-            glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
-        }
-        glDisableClientState(GL_TEXTURE_COORD_ARRAY);
-        glDisable(GL_TEXTURE_2D);
-        glLoadIdentity();
-        glMatrixMode(GL_MODELVIEW);
     }
+
+    GLfloat vertices[4][2];
+    glVertexPointer(2, GL_FLOAT, 0, vertices);
+    Region::const_iterator it = region.begin();
+    Region::const_iterator const end = region.end();
+    while (it != end) {
+        const Rect& r = *it++;
+        vertices[0][0] = r.left;
+        vertices[0][1] = r.top;
+        vertices[1][0] = r.right;
+        vertices[1][1] = r.top;
+        vertices[2][0] = r.right;
+        vertices[2][1] = r.bottom;
+        vertices[3][0] = r.left;
+        vertices[3][1] = r.bottom;
+        glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
+    }
+
+    glDisableClientState(GL_TEXTURE_COORD_ARRAY);
+    glDisable(GL_TEXTURE_2D);
+    glLoadIdentity();
+    glMatrixMode(GL_MODELVIEW);
 }
 
 status_t SurfaceFlinger::addLayer(const sp<LayerBase>& layer)
@@ -1903,6 +1810,8 @@
     GLuint name, tname;
     glGenTextures(1, &tname);
     glBindTexture(GL_TEXTURE_2D, tname);
+    glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
+    glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB,
             hw_w, hw_h, 0, GL_RGB, GL_UNSIGNED_BYTE, 0);
     if (glGetError() != GL_NO_ERROR) {
@@ -1925,7 +1834,6 @@
     glDisable(GL_SCISSOR_TEST);
     glClearColor(0,0,0,1);
     glClear(GL_COLOR_BUFFER_BIT);
-    glEnable(GL_SCISSOR_TEST);
     glMatrixMode(GL_MODELVIEW);
     glLoadIdentity();
     const Vector< sp<LayerBase> >& layers(mVisibleLayersSortedByZ);
@@ -2110,11 +2018,11 @@
     }
 
     glColorMask(1,1,1,1);
-    glEnable(GL_SCISSOR_TEST);
     glDisableClientState(GL_TEXTURE_COORD_ARRAY);
     glDeleteTextures(1, &tname);
     glDisable(GL_TEXTURE_2D);
     glDisable(GL_BLEND);
+    glDisable(GL_SCISSOR_TEST);
     return NO_ERROR;
 }
 
@@ -2253,11 +2161,11 @@
     }
 
     glColorMask(1,1,1,1);
-    glEnable(GL_SCISSOR_TEST);
     glDisableClientState(GL_TEXTURE_COORD_ARRAY);
     glDeleteTextures(1, &tname);
     glDisable(GL_TEXTURE_2D);
     glDisable(GL_BLEND);
+    glDisable(GL_SCISSOR_TEST);
 
     return NO_ERROR;
 }
@@ -2287,7 +2195,6 @@
     glClearColor(0,0,0,1);
     glDisable(GL_SCISSOR_TEST);
     glClear(GL_COLOR_BUFFER_BIT);
-    glEnable(GL_SCISSOR_TEST);
     hw.flip( Region(hw.bounds()) );
 
     return NO_ERROR;
@@ -2425,7 +2332,6 @@
         // invert everything, b/c glReadPixel() below will invert the FB
         glViewport(0, 0, sw, sh);
         glScissor(0, 0, sw, sh);
-        glEnable(GL_SCISSOR_TEST);
         glMatrixMode(GL_PROJECTION);
         glPushMatrix();
         glLoadIdentity();
@@ -2478,7 +2384,7 @@
                 result = NO_MEMORY;
             }
         }
-        glEnable(GL_SCISSOR_TEST);
+        glDisable(GL_SCISSOR_TEST);
         glViewport(0, 0, hw_w, hw_h);
         glMatrixMode(GL_PROJECTION);
         glPopMatrix();
diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h
index 46bbab2..1aea452 100644
--- a/services/surfaceflinger/SurfaceFlinger.h
+++ b/services/surfaceflinger/SurfaceFlinger.h
@@ -318,7 +318,7 @@
             void        handleWorkList();
             void        handleRepaint();
             void        postFramebuffer();
-            void        setupHardwareComposer(Region& dirtyInOut);
+            void        setupHardwareComposer();
             void        composeSurfaces(const Region& dirty);
 
 
diff --git a/services/surfaceflinger/SurfaceTextureLayer.cpp b/services/surfaceflinger/SurfaceTextureLayer.cpp
index d7fd39e..2b647bb 100644
--- a/services/surfaceflinger/SurfaceTextureLayer.cpp
+++ b/services/surfaceflinger/SurfaceTextureLayer.cpp
@@ -40,10 +40,6 @@
             outWidth, outHeight, outTransform);
     if (err == NO_ERROR) {
         switch(api) {
-            case NATIVE_WINDOW_API_CPU:
-                // SurfaceTextureClient supports only 2 buffers for CPU connections
-                this->setBufferCountServer(2);
-                break;
             case NATIVE_WINDOW_API_MEDIA:
             case NATIVE_WINDOW_API_CAMERA:
                 // Camera preview and videos are rate-limited on the producer