Revert "Revert "fix [2793164] Spam 2x/second with TOT master in SurfaceFlinger""

This reverts commit 330dd304a471d260a73e342a240921c03c825f99.
diff --git a/libs/surfaceflinger/Android.mk b/libs/surfaceflinger/Android.mk
index 0879a66..b0229c0 100644
--- a/libs/surfaceflinger/Android.mk
+++ b/libs/surfaceflinger/Android.mk
@@ -6,6 +6,7 @@
     DisplayHardware/DisplayHardware.cpp \
     DisplayHardware/DisplayHardwareBase.cpp \
     BlurFilter.cpp.arm \
+    GLExtensions.cpp \
     Layer.cpp \
     LayerBase.cpp \
     LayerBuffer.cpp \
diff --git a/libs/surfaceflinger/DisplayHardware/DisplayHardware.cpp b/libs/surfaceflinger/DisplayHardware/DisplayHardware.cpp
index 51de1da..2eac0a8 100644
--- a/libs/surfaceflinger/DisplayHardware/DisplayHardware.cpp
+++ b/libs/surfaceflinger/DisplayHardware/DisplayHardware.cpp
@@ -40,6 +40,8 @@
 #include <hardware/overlay.h>
 #include <hardware/gralloc.h>
 
+#include "GLExtensions.h"
+
 using namespace android;
 
 
@@ -73,7 +75,8 @@
 DisplayHardware::DisplayHardware(
         const sp<SurfaceFlinger>& flinger,
         uint32_t dpy)
-    : DisplayHardwareBase(flinger, dpy), mFlags(0)
+    : DisplayHardwareBase(flinger, dpy),
+      mFlags(0)
 {
     init(dpy);
 }
@@ -97,6 +100,9 @@
 {
     mNativeWindow = new FramebufferNativeWindow();
     framebuffer_device_t const * fbDev = mNativeWindow->getDevice();
+    mDpiX = mNativeWindow->xdpi;
+    mDpiY = mNativeWindow->ydpi;
+    mRefreshRate = fbDev->fps;
 
     mOverlayEngine = NULL;
     hw_module_t const* module;
@@ -104,6 +110,11 @@
         overlay_control_open(module, &mOverlayEngine);
     }
 
+    EGLint w, h, dummy;
+    EGLint numConfigs=0;
+    EGLSurface surface;
+    EGLContext context;
+
     // initialize EGL
     EGLint attribs[] = {
             EGL_SURFACE_TYPE,   EGL_WINDOW_BIT,
@@ -121,11 +132,6 @@
         }
     }
 
-    EGLint w, h, dummy;
-    EGLint numConfigs=0;
-    EGLSurface surface;
-    EGLContext context;
-
     // TODO: all the extensions below should be queried through
     // eglGetProcAddress().
 
@@ -144,22 +150,6 @@
     eglGetConfigAttrib(display, config, EGL_BLUE_SIZE,  &b);
     eglGetConfigAttrib(display, config, EGL_ALPHA_SIZE, &a);
 
-    /*
-     * Gather EGL extensions
-     */
-
-    const char* const egl_extensions = eglQueryString(
-            display, EGL_EXTENSIONS);
-    
-    LOGI("EGL informations:");
-    LOGI("# of configs : %d", numConfigs);
-    LOGI("vendor    : %s", eglQueryString(display, EGL_VENDOR));
-    LOGI("version   : %s", eglQueryString(display, EGL_VERSION));
-    LOGI("extensions: %s", egl_extensions);
-    LOGI("Client API: %s", eglQueryString(display, EGL_CLIENT_APIS)?:"Not Supported");
-    LOGI("EGLSurface: %d-%d-%d-%d, config=%p", r, g, b, a, config);
-    
-
     if (mNativeWindow->isUpdateOnDemand()) {
         mFlags |= PARTIAL_UPDATES;
     }
@@ -174,6 +164,8 @@
      */
 
     surface = eglCreateWindowSurface(display, config, mNativeWindow.get(), NULL);
+    eglQuerySurface(display, surface, EGL_WIDTH,  &mWidth);
+    eglQuerySurface(display, surface, EGL_HEIGHT, &mHeight);
 
     if (mFlags & PARTIAL_UPDATES) {
         // if we have partial updates, we definitely don't need to
@@ -187,31 +179,6 @@
             mFlags |= BUFFER_PRESERVED;
         }
     }
-
-    eglQuerySurface(display, surface, EGL_WIDTH,  &mWidth);
-    eglQuerySurface(display, surface, EGL_HEIGHT, &mHeight);
-
-#ifdef EGL_ANDROID_swap_rectangle    
-    if (strstr(egl_extensions, "EGL_ANDROID_swap_rectangle")) {
-        if (eglSetSwapRectangleANDROID(display, surface,
-                0, 0, mWidth, mHeight) == EGL_TRUE) {
-            // This could fail if this extension is not supported by this
-            // specific surface (of config)
-            mFlags |= SWAP_RECTANGLE;
-        }
-    }
-    // when we have the choice between PARTIAL_UPDATES and SWAP_RECTANGLE
-    // choose PARTIAL_UPDATES, which should be more efficient
-    if (mFlags & PARTIAL_UPDATES)
-        mFlags &= ~SWAP_RECTANGLE;
-#endif
-    
-
-    LOGI("flags     : %08x", mFlags);
-    
-    mDpiX = mNativeWindow->xdpi;
-    mDpiY = mNativeWindow->ydpi;
-    mRefreshRate = fbDev->fps; 
     
     /* Read density from build-specific ro.sf.lcd_density property
      * except if it is overridden by qemu.sf.lcd_density.
@@ -234,49 +201,67 @@
     
     context = eglCreateContext(display, config, NULL, NULL);
     
-    /*
-     * Gather OpenGL ES extensions
-     */
-
-    eglMakeCurrent(display, surface, surface, context);
-    const char* const  gl_extensions = (const char*)glGetString(GL_EXTENSIONS);
-    const char* const  gl_renderer = (const char*)glGetString(GL_RENDERER);
-    LOGI("OpenGL informations:");
-    LOGI("vendor    : %s", glGetString(GL_VENDOR));
-    LOGI("renderer  : %s", gl_renderer);
-    LOGI("version   : %s", glGetString(GL_VERSION));
-    LOGI("extensions: %s", gl_extensions);
-
-    glGetIntegerv(GL_MAX_TEXTURE_SIZE, &mMaxTextureSize);
-    glGetIntegerv(GL_MAX_VIEWPORT_DIMS, &mMaxViewportDims);
-    LOGI("GL_MAX_TEXTURE_SIZE = %d", mMaxTextureSize);
-    LOGI("GL_MAX_VIEWPORT_DIMS = %d", mMaxViewportDims);
-
-
-    if (strstr(gl_extensions, "GL_ARB_texture_non_power_of_two")) {
-        mFlags |= NPOT_EXTENSION;
-    }
-#ifdef EGL_ANDROID_image_native_buffer
-    if (strstr( gl_extensions, "GL_OES_EGL_image") &&
-        (strstr(egl_extensions, "EGL_KHR_image_base") || 
-                strstr(egl_extensions, "EGL_KHR_image")) &&
-        strstr(egl_extensions, "EGL_ANDROID_image_native_buffer")) {
-        mFlags |= DIRECT_TEXTURE;
-    }
-#else
-#warning "EGL_ANDROID_image_native_buffer not supported"
-#endif
-
-
-    // Unbind the context from this thread
-    eglMakeCurrent(display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
-
     mDisplay = display;
     mConfig  = config;
     mSurface = surface;
     mContext = context;
     mFormat  = fbDev->format;
     mPageFlipCount = 0;
+
+    /*
+     * Gather OpenGL ES extensions
+     */
+
+    eglMakeCurrent(display, surface, surface, context);
+
+    GLExtensions& extensions(GLExtensions::getInstance());
+    extensions.initWithGLStrings(
+            glGetString(GL_VENDOR),
+            glGetString(GL_RENDERER),
+            glGetString(GL_VERSION),
+            glGetString(GL_EXTENSIONS),
+            eglQueryString(display, EGL_VENDOR),
+            eglQueryString(display, EGL_VERSION),
+            eglQueryString(display, EGL_EXTENSIONS));
+
+    glGetIntegerv(GL_MAX_TEXTURE_SIZE, &mMaxTextureSize);
+    glGetIntegerv(GL_MAX_VIEWPORT_DIMS, &mMaxViewportDims);
+
+
+#ifdef EGL_ANDROID_swap_rectangle
+    if (extensions.hasExtension("EGL_ANDROID_swap_rectangle")) {
+        if (eglSetSwapRectangleANDROID(display, surface,
+                0, 0, mWidth, mHeight) == EGL_TRUE) {
+            // This could fail if this extension is not supported by this
+            // specific surface (of config)
+            mFlags |= SWAP_RECTANGLE;
+        }
+    }
+    // when we have the choice between PARTIAL_UPDATES and SWAP_RECTANGLE
+    // choose PARTIAL_UPDATES, which should be more efficient
+    if (mFlags & PARTIAL_UPDATES)
+        mFlags &= ~SWAP_RECTANGLE;
+#endif
+
+    LOGI("EGL informations:");
+    LOGI("# of configs : %d", numConfigs);
+    LOGI("vendor    : %s", extensions.getEglVendor());
+    LOGI("version   : %s", extensions.getEglVersion());
+    LOGI("extensions: %s", extensions.getEglExtension());
+    LOGI("Client API: %s", eglQueryString(display, EGL_CLIENT_APIS)?:"Not Supported");
+    LOGI("EGLSurface: %d-%d-%d-%d, config=%p", r, g, b, a, config);
+
+    LOGI("OpenGL informations:");
+    LOGI("vendor    : %s", extensions.getVendor());
+    LOGI("renderer  : %s", extensions.getRenderer());
+    LOGI("version   : %s", extensions.getVersion());
+    LOGI("extensions: %s", extensions.getExtension());
+    LOGI("GL_MAX_TEXTURE_SIZE = %d", mMaxTextureSize);
+    LOGI("GL_MAX_VIEWPORT_DIMS = %d", mMaxViewportDims);
+    LOGI("flags = %08x", mFlags);
+
+    // Unbind the context from this thread
+    eglMakeCurrent(display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
 }
 
 /*
diff --git a/libs/surfaceflinger/DisplayHardware/DisplayHardware.h b/libs/surfaceflinger/DisplayHardware/DisplayHardware.h
index ebd7c42..66bf521 100644
--- a/libs/surfaceflinger/DisplayHardware/DisplayHardware.h
+++ b/libs/surfaceflinger/DisplayHardware/DisplayHardware.h
@@ -29,6 +29,8 @@
 
 #include <pixelflinger/pixelflinger.h>
 
+#include "GLExtensions.h"
+
 #include "DisplayHardware/DisplayHardwareBase.h"
 
 struct overlay_control_device_t;
@@ -43,13 +45,11 @@
 {
 public:
     enum {
-        DIRECT_TEXTURE          = 0x00000002,
-        COPY_BITS_EXTENSION     = 0x00000008,
-        NPOT_EXTENSION          = 0x00000100,
-        BUFFER_PRESERVED        = 0x00010000,
-        PARTIAL_UPDATES         = 0x00020000,   // video driver feature
-        SLOW_CONFIG             = 0x00040000,   // software
-        SWAP_RECTANGLE          = 0x00080000,
+        COPY_BITS_EXTENSION         = 0x00000008,
+        BUFFER_PRESERVED            = 0x00010000,
+        PARTIAL_UPDATES             = 0x00020000,   // video driver feature
+        SLOW_CONFIG                 = 0x00040000,   // software
+        SWAP_RECTANGLE              = 0x00080000,
     };
 
     DisplayHardware(
diff --git a/libs/surfaceflinger/GLExtensions.cpp b/libs/surfaceflinger/GLExtensions.cpp
new file mode 100644
index 0000000..7f4f9fc
--- /dev/null
+++ b/libs/surfaceflinger/GLExtensions.cpp
@@ -0,0 +1,133 @@
+/*
+ * Copyright (C) 2010 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.
+ */
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <stdint.h>
+
+#include "GLExtensions.h"
+
+namespace android {
+// ---------------------------------------------------------------------------
+
+ANDROID_SINGLETON_STATIC_INSTANCE( GLExtensions )
+
+GLExtensions::GLExtensions()
+    : mHaveTextureExternal(false),
+      mHaveNpot(false),
+      mHaveDirectTexture(false)
+{
+}
+
+void GLExtensions::initWithGLStrings(
+        GLubyte const* vendor,
+        GLubyte const* renderer,
+        GLubyte const* version,
+        GLubyte const* extensions,
+        char const* egl_vendor,
+        char const* egl_version,
+        char const* egl_extensions)
+{
+    mVendor     = (char const*)vendor;
+    mRenderer   = (char const*)renderer;
+    mVersion    = (char const*)version;
+    mExtensions = (char const*)extensions;
+    mEglVendor     = egl_vendor;
+    mEglVersion    = egl_version;
+    mEglExtensions = egl_extensions;
+
+    char const* curr = (char const*)extensions;
+    char const* head = curr;
+    do {
+        head = strchr(curr, ' ');
+        String8 s(curr, head ? head-curr : strlen(curr));
+        if (s.length()) {
+            mExtensionList.add(s);
+        }
+        curr = head+1;
+    } while (head);
+
+    curr = egl_extensions;
+    head = curr;
+    do {
+        head = strchr(curr, ' ');
+        String8 s(curr, head ? head-curr : strlen(curr));
+        if (s.length()) {
+            mExtensionList.add(s);
+        }
+        curr = head+1;
+    } while (head);
+
+#ifdef EGL_ANDROID_image_native_buffer
+    if (hasExtension("GL_OES_EGL_image") &&
+        (hasExtension("EGL_KHR_image_base") || hasExtension("EGL_KHR_image")) &&
+        hasExtension("EGL_ANDROID_image_native_buffer"))
+    {
+        mHaveDirectTexture = true;
+    }
+#else
+#warning "EGL_ANDROID_image_native_buffer not supported"
+#endif
+
+    if (hasExtension("GL_ARB_texture_non_power_of_two")) {
+        mHaveNpot = true;
+    }
+
+    if (hasExtension("GL_OES_texture_external")) {
+        mHaveTextureExternal = true;
+    } else if (strstr(mRenderer.string(), "Adreno")) {
+        // hack for Adreno 200
+        mHaveTextureExternal = true;
+    }
+}
+
+bool GLExtensions::hasExtension(char const* extension) const
+{
+    const String8 s(extension);
+    return mExtensionList.indexOf(s) >= 0;
+}
+
+char const* GLExtensions::getVendor() const {
+    return mVendor.string();
+}
+
+char const* GLExtensions::getRenderer() const {
+    return mRenderer.string();
+}
+
+char const* GLExtensions::getVersion() const {
+    return mVersion.string();
+}
+
+char const* GLExtensions::getExtension() const {
+    return mExtensions.string();
+}
+
+char const* GLExtensions::getEglVendor() const {
+    return mEglVendor.string();
+}
+
+char const* GLExtensions::getEglVersion() const {
+    return mEglVersion.string();
+}
+
+char const* GLExtensions::getEglExtension() const {
+    return mEglExtensions.string();
+}
+
+
+// ---------------------------------------------------------------------------
+}; // namespace android
diff --git a/libs/surfaceflinger/GLExtensions.h b/libs/surfaceflinger/GLExtensions.h
new file mode 100644
index 0000000..bbb284e
--- /dev/null
+++ b/libs/surfaceflinger/GLExtensions.h
@@ -0,0 +1,94 @@
+/*
+ * Copyright (C) 2010 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.
+ */
+
+#ifndef ANDROID_SF_GLEXTENSION_H
+#define ANDROID_SF_GLEXTENSION_H
+
+#include <stdint.h>
+#include <sys/types.h>
+
+#include <utils/String8.h>
+#include <utils/SortedVector.h>
+#include <utils/Singleton.h>
+
+#include <EGL/egl.h>
+#include <EGL/eglext.h>
+#include <GLES/gl.h>
+#include <GLES/glext.h>
+
+namespace android {
+// ---------------------------------------------------------------------------
+
+class GLExtensions : public Singleton<GLExtensions>
+{
+    friend class Singleton<GLExtensions>;
+
+    bool mHaveTextureExternal   : 1;
+    bool mHaveNpot              : 1;
+    bool mHaveDirectTexture     : 1;
+
+    String8 mVendor;
+    String8 mRenderer;
+    String8 mVersion;
+    String8 mExtensions;
+    String8 mEglVendor;
+    String8 mEglVersion;
+    String8 mEglExtensions;
+    SortedVector<String8> mExtensionList;
+
+    GLExtensions(const GLExtensions&);
+    GLExtensions& operator = (const GLExtensions&);
+
+protected:
+    GLExtensions();
+
+public:
+    inline bool haveTextureExternal() const {
+        return mHaveTextureExternal;
+    }
+    inline bool haveNpot() const {
+        return mHaveNpot;
+    }
+    inline bool haveDirectTexture() const {
+        return mHaveDirectTexture;
+    }
+
+    void initWithGLStrings(
+            GLubyte const* vendor,
+            GLubyte const* renderer,
+            GLubyte const* version,
+            GLubyte const* extensions,
+            char const* egl_vendor,
+            char const* egl_version,
+            char const* egl_extensions);
+
+    char const* getVendor() const;
+    char const* getRenderer() const;
+    char const* getVersion() const;
+    char const* getExtension() const;
+
+    char const* getEglVendor() const;
+    char const* getEglVersion() const;
+    char const* getEglExtension() const;
+
+    bool hasExtension(char const* extension) const;
+};
+
+
+// ---------------------------------------------------------------------------
+}; // namespace android
+
+#endif // ANDROID_SF_GLEXTENSION_H
diff --git a/libs/surfaceflinger/Layer.cpp b/libs/surfaceflinger/Layer.cpp
index e606f71..758da4e 100644
--- a/libs/surfaceflinger/Layer.cpp
+++ b/libs/surfaceflinger/Layer.cpp
@@ -31,6 +31,7 @@
 #include <surfaceflinger/Surface.h>
 
 #include "clz.h"
+#include "GLExtensions.h"
 #include "Layer.h"
 #include "SurfaceFlinger.h"
 #include "DisplayHardware/DisplayHardware.h"
@@ -50,10 +51,11 @@
 Layer::Layer(SurfaceFlinger* flinger,
         DisplayID display, const sp<Client>& client)
     :   LayerBaseClient(flinger, display, client),
+        mGLExtensions(GLExtensions::getInstance()),
         mNeedsBlending(true),
         mNeedsDithering(false),
         mSecure(false),
-        mTextureManager(mFlags),
+        mTextureManager(),
         mBufferManager(mTextureManager),
         mWidth(0), mHeight(0), mFixedSize(false)
 {
@@ -185,17 +187,13 @@
         return;
     }
 
-#ifdef EGL_ANDROID_image_native_buffer
-    if (mFlags & DisplayHardware::DIRECT_TEXTURE) {
+    if (mGLExtensions.haveDirectTexture()) {
         EGLDisplay dpy(mFlinger->graphicPlane(0).getEGLDisplay());
         if (mBufferManager.initEglImage(dpy, buffer) != NO_ERROR) {
             // not sure what we can do here...
-            mFlags &= ~DisplayHardware::DIRECT_TEXTURE;
             goto slowpath;
         }
-    } else
-#endif
-    {
+    } else {
 slowpath:
         GGLSurface t;
         status_t res = buffer->lock(&t, GRALLOC_USAGE_SW_READ_OFTEN);
@@ -786,19 +784,24 @@
     status_t err = NO_INIT;
     ssize_t index = mActiveBuffer;
     if (index >= 0) {
-        Image& texture(mBufferData[index].texture);
-        err = mTextureManager.initEglImage(&texture, dpy, buffer);
-        // if EGLImage fails, we switch to regular texture mode, and we
-        // free all resources associated with using EGLImages.
-        if (err == NO_ERROR) {
-            mFailover = false;
-            destroyTexture(&mFailoverTexture, dpy);
-        } else {
-            mFailover = true;
-            const size_t num = mNumBuffers;
-            for (size_t i=0 ; i<num ; i++) {
-                destroyTexture(&mBufferData[i].texture, dpy);
+        if (!mFailover) {
+            Image& texture(mBufferData[index].texture);
+            err = mTextureManager.initEglImage(&texture, dpy, buffer);
+            // if EGLImage fails, we switch to regular texture mode, and we
+            // free all resources associated with using EGLImages.
+            if (err == NO_ERROR) {
+                mFailover = false;
+                destroyTexture(&mFailoverTexture, dpy);
+            } else {
+                mFailover = true;
+                const size_t num = mNumBuffers;
+                for (size_t i=0 ; i<num ; i++) {
+                    destroyTexture(&mBufferData[i].texture, dpy);
+                }
             }
+        } else {
+            // we failed once, don't try again
+            err = BAD_VALUE;
         }
     }
     return err;
diff --git a/libs/surfaceflinger/Layer.h b/libs/surfaceflinger/Layer.h
index dcb27a0..e1d283b 100644
--- a/libs/surfaceflinger/Layer.h
+++ b/libs/surfaceflinger/Layer.h
@@ -37,9 +37,10 @@
 
 // ---------------------------------------------------------------------------
 
-class Client;
-class UserClient;
 class FreezeLock;
+class Client;
+class GLExtensions;
+class UserClient;
 
 // ---------------------------------------------------------------------------
 
@@ -206,6 +207,7 @@
     // constants
     sp<Surface> mSurface;
     PixelFormat mFormat;
+    const GLExtensions& mGLExtensions;
     bool mNeedsBlending;
     bool mNeedsDithering;
 
diff --git a/libs/surfaceflinger/LayerBlur.cpp b/libs/surfaceflinger/LayerBlur.cpp
index c1c440b..64a43c7 100644
--- a/libs/surfaceflinger/LayerBlur.cpp
+++ b/libs/surfaceflinger/LayerBlur.cpp
@@ -147,7 +147,9 @@
     Region::const_iterator const end = clip.end();
     if (it != end) {
 #if defined(GL_OES_texture_external)
-        glDisable(GL_TEXTURE_EXTERNAL_OES);
+        if (GLExtensions::getInstance().haveTextureExternal()) {
+            glDisable(GL_TEXTURE_EXTERNAL_OES);
+        }
 #endif
         glEnable(GL_TEXTURE_2D);
         glBindTexture(GL_TEXTURE_2D, mTextureName);
@@ -181,7 +183,7 @@
             bl.data = (GGLubyte*)pixels;            
             blurFilter(&bl, 8, 2);
 
-            if (mFlags & (DisplayHardware::NPOT_EXTENSION)) {
+            if (GLExtensions::getInstance().haveNpot()) {
                 glTexImage2D(GL_TEXTURE_2D, 0, mReadFormat, w, h, 0,
                         mReadFormat, mReadType, pixels);
                 mWidthScale  = 1.0f / w;
diff --git a/libs/surfaceflinger/LayerBuffer.cpp b/libs/surfaceflinger/LayerBuffer.cpp
index 732a4ec..5f836366 100644
--- a/libs/surfaceflinger/LayerBuffer.cpp
+++ b/libs/surfaceflinger/LayerBuffer.cpp
@@ -315,8 +315,7 @@
 
 LayerBuffer::BufferSource::BufferSource(LayerBuffer& layer,
         const ISurface::BufferHeap& buffers)
-    : Source(layer), mStatus(NO_ERROR), mBufferSize(0),
-      mTextureManager(layer.mFlags)
+    : Source(layer), mStatus(NO_ERROR), mBufferSize(0)
 {
     if (buffers.heap == NULL) {
         // this is allowed, but in this case, it is illegal to receive
@@ -374,11 +373,11 @@
 
     if (mTexture.name != -1U) {
         // GL textures can only be destroyed from the GL thread
-        mLayer.mFlinger->mEventQueue.postMessage(
-                new MessageDestroyTexture(mLayer.mFlinger.get(), mTexture.name) );
+        getFlinger()->mEventQueue.postMessage(
+                new MessageDestroyTexture(getFlinger(), mTexture.name) );
     }
     if (mTexture.image != EGL_NO_IMAGE_KHR) {
-        EGLDisplay dpy(mLayer.mFlinger->graphicPlane(0).getEGLDisplay());
+        EGLDisplay dpy(getFlinger()->graphicPlane(0).getEGLDisplay());
         eglDestroyImageKHR(dpy, mTexture.image);
     }
 }
@@ -444,7 +443,7 @@
     const Rect transformedBounds(mLayer.getTransformedBounds());
 
 #if defined(EGL_ANDROID_image_native_buffer)
-    if (mLayer.mFlags & DisplayHardware::DIRECT_TEXTURE) {
+    if (GLExtensions::getInstance().haveDirectTexture()) {
         err = INVALID_OPERATION;
         if (ourBuffer->supportsCopybit()) {
             copybit_device_t* copybit = mLayer.mBlitEngine;
@@ -549,7 +548,7 @@
         dst.crop.r = w;
         dst.crop.b = h;
 
-        EGLDisplay dpy(mLayer.mFlinger->graphicPlane(0).getEGLDisplay());
+        EGLDisplay dpy(getFlinger()->graphicPlane(0).getEGLDisplay());
         err = mTextureManager.initEglImage(&mTexture, dpy, buffer);
     }
 
@@ -559,7 +558,7 @@
 void LayerBuffer::BufferSource::clearTempBufferImage() const
 {
     // delete the image
-    EGLDisplay dpy(mLayer.mFlinger->graphicPlane(0).getEGLDisplay());
+    EGLDisplay dpy(getFlinger()->graphicPlane(0).getEGLDisplay());
     eglDestroyImageKHR(dpy, mTexture.image);
 
     // and the associated texture (recreate a name)
@@ -576,7 +575,7 @@
     : Source(layer), mVisibilityChanged(false),
     mOverlay(0), mOverlayHandle(0), mOverlayDevice(0), mOrientation(orientation)
 {
-    overlay_control_device_t* overlay_dev = mLayer.mFlinger->getOverlayEngine();
+    overlay_control_device_t* overlay_dev = getFlinger()->getOverlayEngine();
     if (overlay_dev == NULL) {
         // overlays not supported
         return;
@@ -607,7 +606,7 @@
 
     *overlayRef = new OverlayRef(mOverlayHandle, channel,
             mWidth, mHeight, mFormat, mWidthStride, mHeightStride);
-    mLayer.mFlinger->signalEvent();
+    getFlinger()->signalEvent();
 }
 
 LayerBuffer::OverlaySource::~OverlaySource()
diff --git a/libs/surfaceflinger/LayerBuffer.h b/libs/surfaceflinger/LayerBuffer.h
index 413b8a4..1c0bf83 100644
--- a/libs/surfaceflinger/LayerBuffer.h
+++ b/libs/surfaceflinger/LayerBuffer.h
@@ -47,6 +47,7 @@
         virtual void postBuffer(ssize_t offset);
         virtual void unregisterBuffers();
         virtual void destroy() { }
+        SurfaceFlinger* getFlinger() const { return mLayer.mFlinger.get(); }
     protected:
         LayerBuffer& mLayer;
     };
diff --git a/libs/surfaceflinger/LayerDim.cpp b/libs/surfaceflinger/LayerDim.cpp
index 906a583..c13b4b3 100644
--- a/libs/surfaceflinger/LayerDim.cpp
+++ b/libs/surfaceflinger/LayerDim.cpp
@@ -112,15 +112,17 @@
     Region::const_iterator const end = clip.end();
     if (s.alpha>0 && (it != end)) {
         const DisplayHardware& hw(graphicPlane(0).displayHardware());
-        const GGLfixed alpha = (s.alpha << 16)/255;
+        const GLfloat alpha = s.alpha/255.0f;
         const uint32_t fbHeight = hw.getHeight();
         glDisable(GL_DITHER);
         glEnable(GL_BLEND);
         glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
-        glColor4x(0, 0, 0, alpha);
-        
+        glColor4f(0, 0, 0, alpha);
+
 #if defined(GL_OES_texture_external)
-        glDisable(GL_TEXTURE_EXTERNAL_OES);
+        if (GLExtensions::getInstance().haveTextureExternal()) {
+            glDisable(GL_TEXTURE_EXTERNAL_OES);
+        }
 #endif
 #if defined(DIM_WITH_TEXTURE) && defined(EGL_ANDROID_image_native_buffer)
         if (sUseTexture) {
diff --git a/libs/surfaceflinger/SurfaceFlinger.cpp b/libs/surfaceflinger/SurfaceFlinger.cpp
index 96a5411..23efd16 100644
--- a/libs/surfaceflinger/SurfaceFlinger.cpp
+++ b/libs/surfaceflinger/SurfaceFlinger.cpp
@@ -44,6 +44,7 @@
 #include <GLES/gl.h>
 
 #include "clz.h"
+#include "GLExtensions.h"
 #include "Layer.h"
 #include "LayerBlur.h"
 #include "LayerBuffer.h"
@@ -993,7 +994,9 @@
         glTexCoordPointer(2, GL_SHORT, 0, tcoords);
         glEnableClientState(GL_TEXTURE_COORD_ARRAY);
 #if defined(GL_OES_texture_external)
-        glDisable(GL_TEXTURE_EXTERNAL_OES);
+        if (GLExtensions::getInstance().haveTextureExternal()) {
+            glDisable(GL_TEXTURE_EXTERNAL_OES);
+        }
 #endif
         glEnable(GL_TEXTURE_2D);
         glBindTexture(GL_TEXTURE_2D, mWormholeTexName);
diff --git a/libs/surfaceflinger/TextureManager.cpp b/libs/surfaceflinger/TextureManager.cpp
index d9bdc6a..e4dd42f 100644
--- a/libs/surfaceflinger/TextureManager.cpp
+++ b/libs/surfaceflinger/TextureManager.cpp
@@ -30,14 +30,15 @@
 
 #include "clz.h"
 #include "DisplayHardware/DisplayHardware.h"
+#include "GLExtensions.h"
 #include "TextureManager.h"
 
 namespace android {
 
 // ---------------------------------------------------------------------------
 
-TextureManager::TextureManager(uint32_t flags)
-    : mFlags(flags)
+TextureManager::TextureManager()
+    : mGLExtensions(GLExtensions::getInstance())
 {
 }
 
@@ -85,9 +86,11 @@
 
     GLenum target = GL_TEXTURE_2D;
 #if defined(GL_OES_texture_external)
-    if (format && isSupportedYuvFormat(format)) {
-        target = GL_TEXTURE_EXTERNAL_OES;
-        pImage->target = Texture::TEXTURE_EXTERNAL;
+    if (GLExtensions::getInstance().haveTextureExternal()) {
+        if (format && isSupportedYuvFormat(format)) {
+            target = GL_TEXTURE_EXTERNAL_OES;
+            pImage->target = Texture::TEXTURE_EXTERNAL;
+        }
     }
 #endif
 
@@ -208,7 +211,7 @@
     /*
      * round to POT if needed
      */
-    if (!(mFlags & DisplayHardware::NPOT_EXTENSION)) {
+    if (!mGLExtensions.haveNpot()) {
         texture->NPOTAdjust = true;
     }
 
@@ -294,14 +297,19 @@
 void TextureManager::activateTexture(const Texture& texture, bool filter)
 {
     const GLenum target = getTextureTarget(&texture);
-
-    glBindTexture(target, texture.name);
-    glEnable(target);
-
+    if (target == Texture::TEXTURE_2D) {
+        glBindTexture(GL_TEXTURE_2D, texture.name);
+        glEnable(GL_TEXTURE_2D);
 #if defined(GL_OES_texture_external)
-    if (texture.target == Texture::TEXTURE_2D) {
-        glDisable(GL_TEXTURE_EXTERNAL_OES);
-    } else {
+        if (GLExtensions::getInstance().haveTextureExternal()) {
+            glDisable(GL_TEXTURE_EXTERNAL_OES);
+        }
+#endif
+    }
+#if defined(GL_OES_texture_external)
+    else {
+        glBindTexture(GL_TEXTURE_EXTERNAL_OES, texture.name);
+        glEnable(GL_TEXTURE_EXTERNAL_OES);
         glDisable(GL_TEXTURE_2D);
     }
 #endif
@@ -319,7 +327,9 @@
 {
     glDisable(GL_TEXTURE_2D);
 #if defined(GL_OES_texture_external)
-    glDisable(GL_TEXTURE_EXTERNAL_OES);
+    if (GLExtensions::getInstance().haveTextureExternal()) {
+        glDisable(GL_TEXTURE_EXTERNAL_OES);
+    }
 #endif
 }
 
diff --git a/libs/surfaceflinger/TextureManager.h b/libs/surfaceflinger/TextureManager.h
index 1f7fe3f..c7c14e7 100644
--- a/libs/surfaceflinger/TextureManager.h
+++ b/libs/surfaceflinger/TextureManager.h
@@ -32,6 +32,7 @@
 
 // ---------------------------------------------------------------------------
 
+class GLExtensions;
 class GraphicBuffer;
 
 // ---------------------------------------------------------------------------
@@ -61,7 +62,7 @@
 // ---------------------------------------------------------------------------
 
 class TextureManager {
-    uint32_t mFlags;
+    const GLExtensions& mGLExtensions;
     static status_t initTexture(Image* texture, int32_t format);
     static status_t initTexture(Texture* texture);
     static bool isSupportedYuvFormat(int format);
@@ -69,7 +70,7 @@
     static GLenum getTextureTarget(const Image* pImage);
 public:
 
-    TextureManager(uint32_t flags);
+    TextureManager();
 
     // load bitmap data into the active buffer
     status_t loadTexture(Texture* texture,