Merge "Allow blaming a single uid for work done" into klp-dev
diff --git a/include/gui/GLConsumer.h b/include/gui/GLConsumer.h
index 75ee30c..a5fdfb9 100644
--- a/include/gui/GLConsumer.h
+++ b/include/gui/GLConsumer.h
@@ -273,7 +273,7 @@
 private:
     // createImage creates a new EGLImage from a GraphicBuffer.
     EGLImageKHR createImage(EGLDisplay dpy,
-            const sp<GraphicBuffer>& graphicBuffer);
+            const sp<GraphicBuffer>& graphicBuffer, const Rect& crop);
 
     // freeBufferLocked frees up the given buffer slot.  If the slot has been
     // initialized this will release the reference to the GraphicBuffer in that
@@ -386,6 +386,10 @@
         // mEglImage is the EGLImage created from mGraphicBuffer.
         EGLImageKHR mEglImage;
 
+        // mCropRect is the crop rectangle passed to EGL when mEglImage was
+        // created.
+        Rect mCropRect;
+
         // mFence is the EGL sync object that must signal before the buffer
         // associated with this buffer slot may be dequeued. It is initialized
         // to EGL_NO_SYNC_KHR when the buffer is created and (optionally, based
diff --git a/include/media/hardware/HardwareAPI.h b/include/media/hardware/HardwareAPI.h
index ac67f94..de3aeb1 100644
--- a/include/media/hardware/HardwareAPI.h
+++ b/include/media/hardware/HardwareAPI.h
@@ -89,6 +89,31 @@
   buffer_handle_t pHandle;
 };
 
+// A pointer to this struct is passed to OMX_SetParameter() when the extension
+// index "OMX.google.android.index.prepareForAdaptivePlayback" is given.
+//
+// This method is used to signal a video decoder, that the user has requested
+// seamless resolution change support (if bEnable is set to OMX_TRUE).
+// nMaxFrameWidth and nMaxFrameHeight are the dimensions of the largest
+// anticipated frames in the video.  If bEnable is OMX_FALSE, no resolution
+// change is expected, and the nMaxFrameWidth/Height fields are unused.
+//
+// If the decoder supports dynamic output buffers, it may ignore this
+// request.  Otherwise, it shall request resources in such a way so that it
+// avoids full port-reconfiguration (due to output port-definition change)
+// during resolution changes.
+//
+// DO NOT USE THIS STRUCTURE AS IT WILL BE REMOVED.  INSTEAD, IMPLEMENT
+// METADATA SUPPORT FOR VIDEO DECODERS.
+struct PrepareForAdaptivePlaybackParams {
+    OMX_U32 nSize;
+    OMX_VERSIONTYPE nVersion;
+    OMX_U32 nPortIndex;
+    OMX_BOOL bEnable;
+    OMX_U32 nMaxFrameWidth;
+    OMX_U32 nMaxFrameHeight;
+};
+
 // A pointer to this struct is passed to OMX_SetParameter when the extension
 // index for the 'OMX.google.android.index.useAndroidNativeBuffer' extension is
 // given.  This call will only be performed if a prior call was made with the
diff --git a/libs/gui/BufferQueue.cpp b/libs/gui/BufferQueue.cpp
index 87d66e2..c165a68 100644
--- a/libs/gui/BufferQueue.cpp
+++ b/libs/gui/BufferQueue.cpp
@@ -668,11 +668,15 @@
                 mConnectedApi = api;
                 output->inflate(mDefaultWidth, mDefaultHeight, mTransformHint, mQueue.size());
 
-                // set-up a death notification so that we can disconnect automatically
-                // when/if the remote producer dies.
-                // This will fail with INVALID_OPERATION if the "token" is local to our process.
-                if (token->linkToDeath(static_cast<IBinder::DeathRecipient*>(this)) == NO_ERROR) {
-                    mConnectedProducerToken = token;
+                // set-up a death notification so that we can disconnect
+                // automatically when/if the remote producer dies.
+                if (token != NULL && token->remoteBinder() != NULL) {
+                    status_t err = token->linkToDeath(static_cast<IBinder::DeathRecipient*>(this));
+                    if (err == NO_ERROR) {
+                        mConnectedProducerToken = token;
+                    } else {
+                        ALOGE("linkToDeath failed: %s (%d)", strerror(-err), err);
+                    }
                 }
             }
             break;
diff --git a/libs/gui/GLConsumer.cpp b/libs/gui/GLConsumer.cpp
index cf3f12a..7ee3081 100644
--- a/libs/gui/GLConsumer.cpp
+++ b/libs/gui/GLConsumer.cpp
@@ -41,6 +41,9 @@
 #include <utils/String8.h>
 #include <utils/Trace.h>
 
+EGLAPI const char* eglQueryStringImplementationANDROID(EGLDisplay dpy, EGLint name);
+#define CROP_EXT_STR "EGL_ANDROID_image_crop"
+
 namespace android {
 
 // Macros for including the GLConsumer name in log messages
@@ -89,6 +92,30 @@
 Mutex GLConsumer::sStaticInitLock;
 sp<GraphicBuffer> GLConsumer::sReleasedTexImageBuffer;
 
+static bool hasEglAndroidImageCropImpl() {
+    EGLDisplay dpy = eglGetDisplay(EGL_DEFAULT_DISPLAY);
+    const char* exts = eglQueryStringImplementationANDROID(dpy, EGL_EXTENSIONS);
+    size_t cropExtLen = strlen(CROP_EXT_STR);
+    size_t extsLen = strlen(exts);
+    bool equal = !strcmp(CROP_EXT_STR, exts);
+    bool atStart = !strncmp(CROP_EXT_STR " ", exts, cropExtLen+1);
+    bool atEnd = (cropExtLen+1) < extsLen &&
+            !strcmp(" " CROP_EXT_STR, exts + extsLen - (cropExtLen+1));
+    bool inMiddle = strstr(exts, " " CROP_EXT_STR " ");
+    return equal || atStart || atEnd || inMiddle;
+}
+
+static bool hasEglAndroidImageCrop() {
+    // Only compute whether the extension is present once the first time this
+    // function is called.
+    static bool hasIt = hasEglAndroidImageCropImpl();
+    return hasIt;
+}
+
+static bool isEglImageCroppable(const Rect& crop) {
+    return hasEglAndroidImageCrop() && (crop.left == 0 && crop.top == 0);
+}
+
 GLConsumer::GLConsumer(const sp<IGraphicBufferConsumer>& bq, uint32_t tex,
         uint32_t texTarget, bool useFenceSync, bool isControlledByApp) :
     ConsumerBase(bq, isControlledByApp),
@@ -279,19 +306,30 @@
     }
 
     int slot = item->mBuf;
-    if (item->mGraphicBuffer != NULL) {
-        // This buffer has not been acquired before, so we must assume
-        // that any EGLImage in mEglSlots is stale.
-        if (mEglSlots[slot].mEglImage != EGL_NO_IMAGE_KHR) {
-            if (!eglDestroyImageKHR(mEglDisplay, mEglSlots[slot].mEglImage)) {
-                ST_LOGW("acquireBufferLocked: eglDestroyImageKHR failed for slot=%d",
-                      slot);
-                // keep going
-            }
-            mEglSlots[slot].mEglImage = EGL_NO_IMAGE_KHR;
+    bool destroyEglImage = false;
+
+    if (mEglSlots[slot].mEglImage != EGL_NO_IMAGE_KHR) {
+        if (item->mGraphicBuffer != NULL) {
+            // This buffer has not been acquired before, so we must assume
+            // that any EGLImage in mEglSlots is stale.
+            destroyEglImage = true;
+        } else if (mEglSlots[slot].mCropRect != item->mCrop) {
+            // We've already seen this buffer before, but it now has a
+            // different crop rect, so we'll need to recreate the EGLImage if
+            // we're using the EGL_ANDROID_image_crop extension.
+            destroyEglImage = hasEglAndroidImageCrop();
         }
     }
 
+    if (destroyEglImage) {
+        if (!eglDestroyImageKHR(mEglDisplay, mEglSlots[slot].mEglImage)) {
+            ST_LOGW("acquireBufferLocked: eglDestroyImageKHR failed for slot=%d",
+                  slot);
+            // keep going
+        }
+        mEglSlots[slot].mEglImage = EGL_NO_IMAGE_KHR;
+    }
+
     return NO_ERROR;
 }
 
@@ -334,13 +372,15 @@
     // EGLImage when detaching from a context but the buffer has not been
     // re-allocated.
     if (mEglSlots[buf].mEglImage == EGL_NO_IMAGE_KHR) {
-        EGLImageKHR image = createImage(mEglDisplay, mSlots[buf].mGraphicBuffer);
+        EGLImageKHR image = createImage(mEglDisplay,
+                mSlots[buf].mGraphicBuffer, item.mCrop);
         if (image == EGL_NO_IMAGE_KHR) {
             ST_LOGW("updateAndRelease: unable to createImage on display=%p slot=%d",
                   mEglDisplay, buf);
             return UNKNOWN_ERROR;
         }
         mEglSlots[buf].mEglImage = image;
+        mEglSlots[buf].mCropRect = item.mCrop;
     }
 
     // Do whatever sync ops we need to do before releasing the old slot.
@@ -581,7 +621,8 @@
             mCurrentTexture, mCurrentTextureBuf.get());
 
     // Create a temporary EGLImageKHR.
-    EGLImageKHR image = createImage(dpy, mCurrentTextureBuf);
+    Rect crop;
+    EGLImageKHR image = createImage(dpy, mCurrentTextureBuf, mCurrentCrop);
     if (image == EGL_NO_IMAGE_KHR) {
         return UNKNOWN_ERROR;
     }
@@ -753,60 +794,66 @@
         ST_LOGD("computeCurrentTransformMatrixLocked: mCurrentTextureBuf is NULL");
     }
 
-    Rect cropRect = mCurrentCrop;
-    float tx = 0.0f, ty = 0.0f, sx = 1.0f, sy = 1.0f;
-    float bufferWidth = buf->getWidth();
-    float bufferHeight = buf->getHeight();
-    if (!cropRect.isEmpty()) {
-        float shrinkAmount = 0.0f;
-        if (mFilteringEnabled) {
-            // In order to prevent bilinear sampling beyond the edge of the
-            // crop rectangle we may need to shrink it by 2 texels in each
-            // dimension.  Normally this would just need to take 1/2 a texel
-            // off each end, but because the chroma channels of YUV420 images
-            // are subsampled we may need to shrink the crop region by a whole
-            // texel on each side.
-            switch (buf->getPixelFormat()) {
-                case PIXEL_FORMAT_RGBA_8888:
-                case PIXEL_FORMAT_RGBX_8888:
-                case PIXEL_FORMAT_RGB_888:
-                case PIXEL_FORMAT_RGB_565:
-                case PIXEL_FORMAT_BGRA_8888:
-                    // We know there's no subsampling of any channels, so we
-                    // only need to shrink by a half a pixel.
-                    shrinkAmount = 0.5;
-                    break;
+    float mtxBeforeFlipV[16];
+    if (!isEglImageCroppable(mCurrentCrop)) {
+        Rect cropRect = mCurrentCrop;
+        float tx = 0.0f, ty = 0.0f, sx = 1.0f, sy = 1.0f;
+        float bufferWidth = buf->getWidth();
+        float bufferHeight = buf->getHeight();
+        if (!cropRect.isEmpty()) {
+            float shrinkAmount = 0.0f;
+            if (mFilteringEnabled) {
+                // In order to prevent bilinear sampling beyond the edge of the
+                // crop rectangle we may need to shrink it by 2 texels in each
+                // dimension.  Normally this would just need to take 1/2 a texel
+                // off each end, but because the chroma channels of YUV420 images
+                // are subsampled we may need to shrink the crop region by a whole
+                // texel on each side.
+                switch (buf->getPixelFormat()) {
+                    case PIXEL_FORMAT_RGBA_8888:
+                    case PIXEL_FORMAT_RGBX_8888:
+                    case PIXEL_FORMAT_RGB_888:
+                    case PIXEL_FORMAT_RGB_565:
+                    case PIXEL_FORMAT_BGRA_8888:
+                        // We know there's no subsampling of any channels, so we
+                        // only need to shrink by a half a pixel.
+                        shrinkAmount = 0.5;
+                        break;
 
-                default:
-                    // If we don't recognize the format, we must assume the
-                    // worst case (that we care about), which is YUV420.
-                    shrinkAmount = 1.0;
-                    break;
+                    default:
+                        // If we don't recognize the format, we must assume the
+                        // worst case (that we care about), which is YUV420.
+                        shrinkAmount = 1.0;
+                        break;
+                }
+            }
+
+            // Only shrink the dimensions that are not the size of the buffer.
+            if (cropRect.width() < bufferWidth) {
+                tx = (float(cropRect.left) + shrinkAmount) / bufferWidth;
+                sx = (float(cropRect.width()) - (2.0f * shrinkAmount)) /
+                        bufferWidth;
+            }
+            if (cropRect.height() < bufferHeight) {
+                ty = (float(bufferHeight - cropRect.bottom) + shrinkAmount) /
+                        bufferHeight;
+                sy = (float(cropRect.height()) - (2.0f * shrinkAmount)) /
+                        bufferHeight;
             }
         }
+        float crop[16] = {
+            sx, 0, 0, 0,
+            0, sy, 0, 0,
+            0, 0, 1, 0,
+            tx, ty, 0, 1,
+        };
 
-        // Only shrink the dimensions that are not the size of the buffer.
-        if (cropRect.width() < bufferWidth) {
-            tx = (float(cropRect.left) + shrinkAmount) / bufferWidth;
-            sx = (float(cropRect.width()) - (2.0f * shrinkAmount)) /
-                    bufferWidth;
-        }
-        if (cropRect.height() < bufferHeight) {
-            ty = (float(bufferHeight - cropRect.bottom) + shrinkAmount) /
-                    bufferHeight;
-            sy = (float(cropRect.height()) - (2.0f * shrinkAmount)) /
-                    bufferHeight;
+        mtxMul(mtxBeforeFlipV, crop, xform);
+    } else {
+        for (int i = 0; i < 16; i++) {
+            mtxBeforeFlipV[i] = xform[i];
         }
     }
-    float crop[16] = {
-        sx, 0, 0, 0,
-        0, sy, 0, 0,
-        0, 0, 1, 0,
-        tx, ty, 0, 1,
-    };
-
-    float mtxBeforeFlipV[16];
-    mtxMul(mtxBeforeFlipV, crop, xform);
 
     // SurfaceFlinger expects the top of its window textures to be at a Y
     // coordinate of 0, so GLConsumer must behave the same way.  We don't
@@ -828,12 +875,26 @@
 }
 
 EGLImageKHR GLConsumer::createImage(EGLDisplay dpy,
-        const sp<GraphicBuffer>& graphicBuffer) {
+        const sp<GraphicBuffer>& graphicBuffer, const Rect& crop) {
     EGLClientBuffer cbuf = (EGLClientBuffer)graphicBuffer->getNativeBuffer();
     EGLint attrs[] = {
-        EGL_IMAGE_PRESERVED_KHR,    EGL_TRUE,
+        EGL_IMAGE_PRESERVED_KHR,        EGL_TRUE,
+        EGL_IMAGE_CROP_LEFT_ANDROID,    crop.left,
+        EGL_IMAGE_CROP_TOP_ANDROID,     crop.top,
+        EGL_IMAGE_CROP_RIGHT_ANDROID,   crop.right,
+        EGL_IMAGE_CROP_BOTTOM_ANDROID,  crop.bottom,
         EGL_NONE,
     };
+    if (!crop.isValid()) {
+        // No crop rect to set, so terminate the attrib array before the crop.
+        attrs[2] = EGL_NONE;
+    } else if (!isEglImageCroppable(crop)) {
+        // The crop rect is not at the origin, so we can't set the crop on the
+        // EGLImage because that's not allowed by the EGL_ANDROID_image_crop
+        // extension.  In the future we can add a layered extension that
+        // removes this restriction if there is hardware that can support it.
+        attrs[2] = EGL_NONE;
+    }
     EGLImageKHR image = eglCreateImageKHR(dpy, EGL_NO_CONTEXT,
             EGL_NATIVE_BUFFER_ANDROID, cbuf, attrs);
     if (image == EGL_NO_IMAGE_KHR) {
diff --git a/opengl/include/EGL/eglext.h b/opengl/include/EGL/eglext.h
index 6c505ed..3b2984a 100644
--- a/opengl/include/EGL/eglext.h
+++ b/opengl/include/EGL/eglext.h
@@ -494,6 +494,14 @@
 #define EGL_FRAMEBUFFER_TARGET_ANDROID		0x3147
 #endif
 
+#ifndef EGL_ANDROID_image_crop
+#define EGL_ANDROID_image_crop 1
+#define EGL_IMAGE_CROP_LEFT_ANDROID   0x3148
+#define EGL_IMAGE_CROP_TOP_ANDROID    0x3149
+#define EGL_IMAGE_CROP_RIGHT_ANDROID  0x314A
+#define EGL_IMAGE_CROP_BOTTOM_ANDROID 0x314B
+#endif
+
 #ifndef EGL_ANDROID_blob_cache
 #define EGL_ANDROID_blob_cache 1
 typedef khronos_ssize_t EGLsizeiANDROID;
diff --git a/opengl/libs/EGL/eglApi.cpp b/opengl/libs/EGL/eglApi.cpp
index 04d5f45..0cc5265 100644
--- a/opengl/libs/EGL/eglApi.cpp
+++ b/opengl/libs/EGL/eglApi.cpp
@@ -99,6 +99,7 @@
         "EGL_NV_system_time "
         "EGL_ANDROID_image_native_buffer "      // mandatory
         "EGL_KHR_wait_sync "                    // strongly recommended
+        "EGL_ANDROID_recordable "               // mandatory
         ;
 
 // extensions not exposed to applications but used by the ANDROID system
@@ -106,8 +107,7 @@
 //      "EGL_IMG_hibernate_process "            // optional
 //      "EGL_ANDROID_native_fence_sync "        // strongly recommended
 //      "EGL_ANDROID_framebuffer_target "       // mandatory for HWC 1.1
-//      "EGL_ANDROID_recordable "               // mandatory
-
+//      "EGL_ANDROID_image_crop "               // optional
 
 /*
  * EGL Extensions entry-points exposed to 3rd party applications
diff --git a/opengl/specs/README b/opengl/specs/README
index eb86869..f4de1b3 100644
--- a/opengl/specs/README
+++ b/opengl/specs/README
@@ -14,4 +14,8 @@
 0x3145               EGL_SYNC_NATIVE_FENCE_FD_ANDROID (EGL_ANDROID_native_fence_sync)
 0x3146               EGL_SYNC_NATIVE_FENCE_SIGNALED_ANDROID (EGL_ANDROID_native_fence_sync)
 0x3147               EGL_FRAMEBUFFER_TARGET_ANDROID (EGL_ANDROID_framebuffer_target)
-0x3148 - 0x314F      (unused)
+0x3148               EGL_IMAGE_CROP_LEFT_ANDROID (EGL_ANDROID_image_crop)
+0x3149               EGL_IMAGE_CROP_TOP_ANDROID (EGL_ANDROID_image_crop)
+0x314A               EGL_IMAGE_CROP_RIGHT_ANDROID (EGL_ANDROID_image_crop)
+0x314B               EGL_IMAGE_CROP_BOTTOM_ANDROID (EGL_ANDROID_image_crop)
+0x314C - 0x314F      (unused)
diff --git a/services/surfaceflinger/DisplayHardware/HWComposer.cpp b/services/surfaceflinger/DisplayHardware/HWComposer.cpp
index c851a2c..7132b2f 100644
--- a/services/surfaceflinger/DisplayHardware/HWComposer.cpp
+++ b/services/surfaceflinger/DisplayHardware/HWComposer.cpp
@@ -611,6 +611,10 @@
         // here we're just making sure that "skip" layers are set
         // to HWC_FRAMEBUFFER and we're also counting how many layers
         // we have of each type.
+        //
+        // If there are no window layers, we treat the display has having FB
+        // composition, because SurfaceFlinger will use GLES to draw the
+        // wormhole region.
         for (size_t i=0 ; i<mNumDisplays ; i++) {
             DisplayData& disp(mDisplayData[i]);
             disp.hasFbComp = false;
@@ -632,6 +636,11 @@
                         disp.hasOvComp = true;
                     }
                 }
+                if (disp.list->numHwLayers == (disp.framebufferTarget ? 1 : 0)) {
+                    disp.hasFbComp = true;
+                }
+            } else {
+                disp.hasFbComp = true;
             }
         }
     }
diff --git a/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.cpp b/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.cpp
index 88ef392..c5a14b0 100644
--- a/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.cpp
+++ b/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.cpp
@@ -147,6 +147,10 @@
             mFbProducerSlot, fbBuffer.get(),
             mOutputProducerSlot, outBuffer.get());
 
+    // At this point we know the output buffer acquire fence,
+    // so update HWC state with it.
+    mHwc.setOutputBuffer(mDisplayId, mOutputFence, outBuffer);
+
     return mHwc.fbPost(mDisplayId, mFbFence, fbBuffer);
 }
 
@@ -415,7 +419,11 @@
         return result;
     mOutputProducerSlot = mapSource2ProducerSlot(SOURCE_SINK, sslot);
 
-    result = mHwc.setOutputBuffer(mDisplayId, mOutputFence,
+    // On GLES-only frames, we don't have the right output buffer acquire fence
+    // until after GLES calls queueBuffer(). So here we just set the buffer
+    // (for use in HWC prepare) but not the fence; we'll call this again with
+    // the proper fence once we have it.
+    result = mHwc.setOutputBuffer(mDisplayId, Fence::NO_FENCE,
             mProducerBuffers[mOutputProducerSlot]);
 
     return result;
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index f83cc06..e374548 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -366,12 +366,10 @@
     operator EGLint const* () const { return &mList.keyAt(0).v; }
 };
 
-EGLConfig SurfaceFlinger::selectEGLConfig(EGLDisplay display, EGLint nativeVisualId,
-    EGLint renderableType) {
+status_t SurfaceFlinger::selectEGLConfig(EGLDisplay display, EGLint nativeVisualId,
+    EGLint renderableType, EGLConfig* config) {
     // select our EGLConfig. It must support EGL_RECORDABLE_ANDROID if
     // it is to be used with WIFI displays
-    EGLConfig config;
-    EGLint dummy;
     status_t err;
     EGLint wantedAttribute;
     EGLint wantedAttributeValue;
@@ -390,22 +388,18 @@
 
     } else {
         // if no renderable type specified, fallback to a simplified query
-        attribs[EGL_RECORDABLE_ANDROID]         = EGL_TRUE;
         wantedAttribute                         = EGL_NATIVE_VISUAL_ID;
         wantedAttributeValue                    = nativeVisualId;
     }
 
     err = selectConfigForAttribute(display, attribs, wantedAttribute,
-        wantedAttributeValue, &config);
-    if (!err)
-        goto success;
-
-    return 0;
-
-success:
-    if (eglGetConfigAttrib(display, config, EGL_CONFIG_CAVEAT, &dummy))
-        ALOGW_IF(dummy == EGL_SLOW_CONFIG, "EGL_SLOW_CONFIG selected!");
-    return config;
+        wantedAttributeValue, config);
+    if (err == NO_ERROR) {
+        EGLint caveat;
+        if (eglGetConfigAttrib(display, *config, EGL_CONFIG_CAVEAT, &caveat))
+            ALOGW_IF(caveat == EGL_SLOW_CONFIG, "EGL_SLOW_CONFIG selected!");
+    }
+    return err;
 }
 
 void SurfaceFlinger::init() {
@@ -413,6 +407,7 @@
     ALOGI(  "SurfaceFlinger's main thread ready to run. "
             "Initializing graphics H/W...");
 
+    status_t err;
     Mutex::Autolock _l(mStateLock);
 
     // initialize EGL for the default display
@@ -425,21 +420,23 @@
             *static_cast<HWComposer::EventHandler *>(this));
 
     // First try to get an ES2 config
-    mEGLConfig = selectEGLConfig(mEGLDisplay, mHwc->getVisualID(), EGL_OPENGL_ES2_BIT);
+    err = selectEGLConfig(mEGLDisplay, mHwc->getVisualID(), EGL_OPENGL_ES2_BIT,
+            &mEGLConfig);
 
-    if (!mEGLConfig) {
+    if (err != NO_ERROR) {
         // If ES2 fails, try ES1
-        mEGLConfig = selectEGLConfig(mEGLDisplay, mHwc->getVisualID(), EGL_OPENGL_ES_BIT);
+        err = selectEGLConfig(mEGLDisplay, mHwc->getVisualID(),
+                EGL_OPENGL_ES_BIT, &mEGLConfig);
     }
 
-    if (!mEGLConfig) {
+    if (err != NO_ERROR) {
         // still didn't work, probably because we're on the emulator...
         // try a simplified query
         ALOGW("no suitable EGLConfig found, trying a simpler query");
-        mEGLConfig = selectEGLConfig(mEGLDisplay, mHwc->getVisualID(), 0);
+        err = selectEGLConfig(mEGLDisplay, mHwc->getVisualID(), 0, &mEGLConfig);
     }
 
-    if (!mEGLConfig) {
+    if (err != NO_ERROR) {
         // this EGL is too lame for android
         LOG_ALWAYS_FATAL("no suitable EGLConfig found, giving up");
     }
@@ -1527,7 +1524,7 @@
     HWComposer::LayerListIterator cur = hwc.begin(id);
     const HWComposer::LayerListIterator end = hwc.end(id);
 
-    const bool hasGlesComposition = hwc.hasGlesComposition(id) || (cur==end);
+    bool hasGlesComposition = hwc.hasGlesComposition(id);
     if (hasGlesComposition) {
         if (!hw->makeCurrent(mEGLDisplay, mEGLContext)) {
             ALOGW("DisplayDevice::makeCurrent failed. Aborting surface composition for display %s",
@@ -1600,9 +1597,10 @@
             if (!clip.isEmpty()) {
                 switch (cur->getCompositionType()) {
                     case HWC_OVERLAY: {
+                        const Layer::State& state(layer->getDrawingState());
                         if ((cur->getHints() & HWC_HINT_CLEAR_FB)
                                 && i
-                                && layer->isOpaque()
+                                && layer->isOpaque() && (state.alpha == 0xFF)
                                 && hasGlesComposition) {
                             // never clear the very first layer since we're
                             // guaranteed the FB is already cleared
diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h
index 989e439..0e9955c 100644
--- a/services/surfaceflinger/SurfaceFlinger.h
+++ b/services/surfaceflinger/SurfaceFlinger.h
@@ -317,8 +317,8 @@
      */
     static status_t selectConfigForAttribute(EGLDisplay dpy,
         EGLint const* attrs, EGLint attribute, EGLint value, EGLConfig* outConfig);
-    static EGLConfig selectEGLConfig(EGLDisplay disp, EGLint visualId,
-		EGLint renderableType);
+    static status_t selectEGLConfig(EGLDisplay disp, EGLint visualId,
+        EGLint renderableType, EGLConfig* config);
     size_t getMaxTextureSize() const;
     size_t getMaxViewportDims() const;