Refactor SF. Move all GL operations in their own class.

this is the first step to add support for GLES 2.x, this
change breaks the dependency of SF on GLES 1.x by moving
all operation into their own class.

Bug: 8679321

Change-Id: I0d2741eca2cefe67dfd9cf837cac10c4d126928b
diff --git a/services/surfaceflinger/Android.mk b/services/surfaceflinger/Android.mk
index f2051dd..2ec575e 100644
--- a/services/surfaceflinger/Android.mk
+++ b/services/surfaceflinger/Android.mk
@@ -6,7 +6,6 @@
     DisplayDevice.cpp \
     EventThread.cpp \
     FrameTracker.cpp \
-    GLExtensions.cpp \
     Layer.cpp \
     LayerDim.cpp \
     MessageQueue.cpp \
@@ -19,7 +18,12 @@
     DisplayHardware/PowerHAL.cpp \
     DisplayHardware/VirtualDisplaySurface.cpp \
     EventLog/EventLogTags.logtags \
-    EventLog/EventLog.cpp
+    EventLog/EventLog.cpp \
+    RenderEngine/GLExtensions.cpp \
+    RenderEngine/RenderEngine.cpp \
+    RenderEngine/GLES10RenderEngine.cpp \
+    RenderEngine/GLES11RenderEngine.cpp
+
 
 LOCAL_CFLAGS:= -DLOG_TAG=\"SurfaceFlinger\"
 LOCAL_CFLAGS += -DGL_GLEXT_PROTOTYPES -DEGL_EGLEXT_PROTOTYPES
diff --git a/services/surfaceflinger/DisplayDevice.cpp b/services/surfaceflinger/DisplayDevice.cpp
index b001bdb..2eae9c2 100644
--- a/services/surfaceflinger/DisplayDevice.cpp
+++ b/services/surfaceflinger/DisplayDevice.cpp
@@ -29,18 +29,14 @@
 
 #include <gui/Surface.h>
 
-#include <GLES/gl.h>
-#include <EGL/egl.h>
-#include <EGL/eglext.h>
-
 #include <hardware/gralloc.h>
 
 #include "DisplayHardware/DisplaySurface.h"
 #include "DisplayHardware/HWComposer.h"
+#include "RenderEngine/RenderEngine.h"
 
 #include "clz.h"
 #include "DisplayDevice.h"
-#include "GLExtensions.h"
 #include "SurfaceFlinger.h"
 #include "Layer.h"
 
@@ -48,20 +44,6 @@
 using namespace android;
 // ----------------------------------------------------------------------------
 
-static __attribute__((noinline))
-void checkGLErrors()
-{
-    do {
-        // there could be more than one error flag
-        GLenum error = glGetError();
-        if (error == GL_NO_ERROR)
-            break;
-        ALOGE("GL error 0x%04x", int(error));
-    } while(true);
-}
-
-// ----------------------------------------------------------------------------
-
 /*
  * Initialize the display to the specified values.
  *
@@ -189,7 +171,7 @@
 
 void DisplayDevice::flip(const Region& dirty) const
 {
-    checkGLErrors();
+    mFlinger->getRenderEngine().checkErrors();
 
     EGLDisplay dpy = mDisplay;
     EGLSurface surface = mSurface;
@@ -246,28 +228,22 @@
     return mFlags;
 }
 
-EGLBoolean DisplayDevice::makeCurrent(EGLDisplay dpy,
-        const sp<const DisplayDevice>& hw, EGLContext ctx) {
+EGLBoolean DisplayDevice::makeCurrent(EGLDisplay dpy, EGLContext ctx) const {
     EGLBoolean result = EGL_TRUE;
     EGLSurface sur = eglGetCurrentSurface(EGL_DRAW);
-    if (sur != hw->mSurface) {
-        result = eglMakeCurrent(dpy, hw->mSurface, hw->mSurface, ctx);
+    if (sur != mSurface) {
+        result = eglMakeCurrent(dpy, mSurface, mSurface, ctx);
         if (result == EGL_TRUE) {
-            setViewportAndProjection(hw);
+            setViewportAndProjection();
         }
     }
     return result;
 }
 
-void DisplayDevice::setViewportAndProjection(const sp<const DisplayDevice>& hw) {
-    GLsizei w = hw->mDisplayWidth;
-    GLsizei h = hw->mDisplayHeight;
-    glViewport(0, 0, w, h);
-    glMatrixMode(GL_PROJECTION);
-    glLoadIdentity();
-    // put the origin in the left-bottom corner
-    glOrthof(0, w, 0, h, 0, 1); // l=0, r=w ; b=0, t=h
-    glMatrixMode(GL_MODELVIEW);
+void DisplayDevice::setViewportAndProjection() const {
+    size_t w = mDisplayWidth;
+    size_t h = mDisplayHeight;
+    mFlinger->getRenderEngine().setViewportAndProjection(w, h);
 }
 
 // ----------------------------------------------------------------------------
diff --git a/services/surfaceflinger/DisplayDevice.h b/services/surfaceflinger/DisplayDevice.h
index 047eecd..eefc107 100644
--- a/services/surfaceflinger/DisplayDevice.h
+++ b/services/surfaceflinger/DisplayDevice.h
@@ -133,10 +133,8 @@
     void setDisplayName(const String8& displayName);
     const String8& getDisplayName() const { return mDisplayName; }
 
-    static EGLBoolean makeCurrent(EGLDisplay dpy,
-            const sp<const DisplayDevice>& hw, EGLContext ctx);
-
-    static void setViewportAndProjection(const sp<const DisplayDevice>& hw);
+    EGLBoolean makeCurrent(EGLDisplay dpy, EGLContext ctx) const;
+    void setViewportAndProjection() const;
 
     /* ------------------------------------------------------------------------
      * blank / unblank management
diff --git a/services/surfaceflinger/GLExtensions.cpp b/services/surfaceflinger/GLExtensions.cpp
deleted file mode 100644
index e5fb083..0000000
--- a/services/surfaceflinger/GLExtensions.cpp
+++ /dev/null
@@ -1,138 +0,0 @@
-/*
- * 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),
-      mHaveFramebufferObject(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
-#error "EGL_ANDROID_image_native_buffer not supported"
-#endif
-
-    if (hasExtension("GL_ARB_texture_non_power_of_two")) {
-        mHaveNpot = true;
-    }
-
-    if (hasExtension("GL_OES_EGL_image_external")) {
-        mHaveTextureExternal = true;
-    } else if (strstr(mRenderer.string(), "Adreno")) {
-        // hack for Adreno 200
-        mHaveTextureExternal = true;
-    }
-
-    if (hasExtension("GL_OES_framebuffer_object")) {
-        mHaveFramebufferObject = 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/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp
index b08b8d1..3605dd4 100644
--- a/services/surfaceflinger/Layer.cpp
+++ b/services/surfaceflinger/Layer.cpp
@@ -38,13 +38,14 @@
 #include "clz.h"
 #include "Colorizer.h"
 #include "DisplayDevice.h"
-#include "GLExtensions.h"
 #include "Layer.h"
 #include "SurfaceFlinger.h"
 #include "SurfaceTextureLayer.h"
 
 #include "DisplayHardware/HWComposer.h"
 
+#include "RenderEngine/RenderEngine.h"
+
 #define DEBUG_RESIZE    0
 
 namespace android {
@@ -63,7 +64,6 @@
         mName("unnamed"),
         mDebug(false),
         mFormat(PIXEL_FORMAT_NONE),
-        mGLExtensions(GLExtensions::getInstance()),
         mOpaqueLayer(true),
         mTransactionFlags(0),
         mQueuedFrames(0),
@@ -236,15 +236,6 @@
     return mSurfaceFlingerConsumer->getBufferQueue();
 }
 
-//virtual sp<IGraphicBufferProducer> getSurfaceTexture() const {
-//    sp<IGraphicBufferProducer> res;
-//    sp<const Layer> that( mOwner.promote() );
-//    if (that != NULL) {
-//        res = that->mSurfaceFlingerConsumer->getBufferQueue();
-//    }
-//    return res;
-//}
-
 // ---------------------------------------------------------------------------
 // h/w composer set-up
 // ---------------------------------------------------------------------------
@@ -499,6 +490,8 @@
 
     bool blackOutLayer = isProtected() || (isSecure() && !hw->isSecure());
 
+    RenderEngine& engine(mFlinger->getRenderEngine());
+
     if (!blackOutLayer) {
         // TODO: we could be more subtle with isFixedSize()
         const bool useFiltering = getFiltering() || needsFiltering(hw) || isFixedSize();
@@ -509,49 +502,24 @@
         mSurfaceFlingerConsumer->getTransformMatrix(textureMatrix);
 
         // Set things up for texturing.
-        glBindTexture(GL_TEXTURE_EXTERNAL_OES, mTextureName);
-        GLenum filter = GL_NEAREST;
-        if (useFiltering) {
-            filter = GL_LINEAR;
-        }
-        glTexParameterx(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_MAG_FILTER, filter);
-        glTexParameterx(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_MIN_FILTER, filter);
-        glMatrixMode(GL_TEXTURE);
-        glLoadMatrixf(textureMatrix);
-        glMatrixMode(GL_MODELVIEW);
-        glDisable(GL_TEXTURE_2D);
-        glEnable(GL_TEXTURE_EXTERNAL_OES);
+        engine.setupLayerTexturing(mTextureName, useFiltering, textureMatrix);
     } else {
-        glBindTexture(GL_TEXTURE_2D, mFlinger->getProtectedTexName());
-        glMatrixMode(GL_TEXTURE);
-        glLoadIdentity();
-        glMatrixMode(GL_MODELVIEW);
-        glDisable(GL_TEXTURE_EXTERNAL_OES);
-        glEnable(GL_TEXTURE_2D);
+        engine.setupLayerBlackedOut();
     }
-
     drawWithOpenGL(hw, clip);
-
-    glDisable(GL_TEXTURE_EXTERNAL_OES);
-    glDisable(GL_TEXTURE_2D);
+    engine.disableTexturing();
 }
 
 
 void Layer::clearWithOpenGL(const sp<const DisplayDevice>& hw, const Region& clip,
         GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha) const
 {
-    const uint32_t fbHeight = hw->getHeight();
-    glColor4f(red,green,blue,alpha);
-
-    glDisable(GL_TEXTURE_EXTERNAL_OES);
-    glDisable(GL_TEXTURE_2D);
-    glDisable(GL_BLEND);
-
     LayerMesh mesh;
     computeGeometry(hw, &mesh);
 
-    glVertexPointer(2, GL_FLOAT, 0, mesh.getVertices());
-    glDrawArrays(GL_TRIANGLE_FAN, 0, mesh.getVertexCount());
+    mFlinger->getRenderEngine().clearWithColor(
+        mesh.getVertices(), mesh.getVertexCount(),
+        red, green, blue, alpha);
 }
 
 void Layer::clearWithOpenGL(
@@ -559,102 +527,14 @@
     clearWithOpenGL(hw, clip, 0,0,0,0);
 }
 
-static void setupOpenGL10(bool premultipliedAlpha, bool opaque, int alpha) {
-    // OpenGL ES 1.0 doesn't support texture combiners.
-    // This path doesn't properly handle opaque layers that have non-opaque
-    // alpha values. The alpha channel will be copied into the framebuffer or
-    // screenshot, so if the framebuffer or screenshot is blended on top of
-    // something else,  whatever is below the window will incorrectly show
-    // through.
-    if (CC_UNLIKELY(alpha < 0xFF)) {
-        GLfloat floatAlpha = alpha * (1.0f / 255.0f);
-        if (premultipliedAlpha) {
-            glColor4f(floatAlpha, floatAlpha, floatAlpha, floatAlpha);
-        } else {
-            glColor4f(1.0f, 1.0f, 1.0f, floatAlpha);
-        }
-        glTexEnvx(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
-    } else {
-        glTexEnvx(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
-    }
-}
-
-static void setupOpenGL11(bool premultipliedAlpha, bool opaque, int alpha) {
-    GLenum combineRGB;
-    GLenum combineAlpha;
-    GLenum src0Alpha;
-    GLfloat envColor[4];
-
-    if (CC_UNLIKELY(alpha < 0xFF)) {
-        // Cv = premultiplied ? Cs*alpha : Cs
-        // Av = !opaque       ? alpha*As : 1.0
-        combineRGB   = premultipliedAlpha ? GL_MODULATE : GL_REPLACE;
-        combineAlpha = !opaque            ? GL_MODULATE : GL_REPLACE;
-        src0Alpha    = GL_CONSTANT;
-        envColor[0]  = alpha * (1.0f / 255.0f);
-    } else {
-        // Cv = Cs
-        // Av = opaque ? 1.0 : As
-        combineRGB   = GL_REPLACE;
-        combineAlpha = GL_REPLACE;
-        src0Alpha    = opaque ? GL_CONSTANT : GL_TEXTURE;
-        envColor[0]  = 1.0f;
-    }
-
-    glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE);
-    glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB, combineRGB);
-    glTexEnvi(GL_TEXTURE_ENV, GL_SRC0_RGB, GL_TEXTURE);
-    glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_RGB, GL_SRC_COLOR);
-    if (combineRGB == GL_MODULATE) {
-        glTexEnvi(GL_TEXTURE_ENV, GL_SRC1_RGB, GL_CONSTANT);
-        glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND1_RGB, GL_SRC_COLOR);
-    }
-    glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA, combineAlpha);
-    glTexEnvi(GL_TEXTURE_ENV, GL_SRC0_ALPHA, src0Alpha);
-    glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_ALPHA, GL_SRC_ALPHA);
-    if (combineAlpha == GL_MODULATE) {
-        glTexEnvi(GL_TEXTURE_ENV, GL_SRC1_ALPHA, GL_TEXTURE);
-        glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND1_ALPHA, GL_SRC_ALPHA);
-    }
-    if (combineRGB == GL_MODULATE || src0Alpha == GL_CONSTANT) {
-        envColor[1] = envColor[0];
-        envColor[2] = envColor[0];
-        envColor[3] = envColor[0];
-        glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, envColor);
-    }
-}
-
 void Layer::drawWithOpenGL(
         const sp<const DisplayDevice>& hw, const Region& clip) const {
     const uint32_t fbHeight = hw->getHeight();
     const State& s(getDrawingState());
 
-    if (mFlinger->getGlesVersion() == GLES_VERSION_1_0) {
-        setupOpenGL10(mPremultipliedAlpha, isOpaque(), s.alpha);
-    } else {
-        setupOpenGL11(mPremultipliedAlpha, isOpaque(), s.alpha);
-    }
-
-    if (s.alpha < 0xFF || !isOpaque()) {
-        glEnable(GL_BLEND);
-        glBlendFunc(mPremultipliedAlpha ? GL_ONE : GL_SRC_ALPHA,
-                    GL_ONE_MINUS_SRC_ALPHA);
-    } else {
-        glDisable(GL_BLEND);
-    }
-
     LayerMesh mesh;
     computeGeometry(hw, &mesh);
 
-    // TODO: we probably want to generate the texture coords with the mesh
-    // here we assume that we only have 4 vertices
-
-    struct TexCoords {
-        GLfloat u;
-        GLfloat v;
-    };
-
-
     /*
      * NOTE: the way we compute the texture coordinates here produces
      * different results than when we take the HWC path -- in the later case
@@ -676,26 +556,25 @@
     GLfloat right  = GLfloat(win.right)  / GLfloat(s.active.w);
     GLfloat bottom = GLfloat(win.bottom) / GLfloat(s.active.h);
 
-    TexCoords texCoords[4];
-    texCoords[0].u = left;
-    texCoords[0].v = top;
-    texCoords[1].u = left;
-    texCoords[1].v = bottom;
-    texCoords[2].u = right;
-    texCoords[2].v = bottom;
-    texCoords[3].u = right;
-    texCoords[3].v = top;
+    // TODO: we probably want to generate the texture coords with the mesh
+    // here we assume that we only have 4 vertices
+    float texCoords[4][2];
+    texCoords[0][0] = left;
+    texCoords[0][1] = top;
+    texCoords[1][0] = left;
+    texCoords[1][1] = bottom;
+    texCoords[2][0] = right;
+    texCoords[2][1] = bottom;
+    texCoords[3][0] = right;
+    texCoords[3][1] = top;
     for (int i = 0; i < 4; i++) {
-        texCoords[i].v = 1.0f - texCoords[i].v;
+        texCoords[i][1] = 1.0f - texCoords[i][1];
     }
 
-    glEnableClientState(GL_TEXTURE_COORD_ARRAY);
-    glTexCoordPointer(2, GL_FLOAT, 0, texCoords);
-    glVertexPointer(2, GL_FLOAT, 0, mesh.getVertices());
-    glDrawArrays(GL_TRIANGLE_FAN, 0, mesh.getVertexCount());
-
-    glDisableClientState(GL_TEXTURE_COORD_ARRAY);
-    glDisable(GL_BLEND);
+    RenderEngine& engine(mFlinger->getRenderEngine());
+    engine.setupLayerBlending(mPremultipliedAlpha, isOpaque(), s.alpha);
+    engine.drawMesh2D(mesh.getVertices(), texCoords, mesh.getVertexCount());
+    engine.disableBlending();
 }
 
 void Layer::setFiltering(bool filtering) {
@@ -1209,9 +1088,6 @@
             recomputeVisibleRegions = true;
         }
 
-        glTexParameterx(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
-        glTexParameterx(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
-
         // FIXME: postedRegion should be dirty & bounds
         const Layer::State& s(getDrawingState());
         Region dirtyRegion(Rect(s.active.w, s.active.h));
diff --git a/services/surfaceflinger/Layer.h b/services/surfaceflinger/Layer.h
index f79bf2d..e7e9585 100644
--- a/services/surfaceflinger/Layer.h
+++ b/services/surfaceflinger/Layer.h
@@ -22,8 +22,6 @@
 
 #include <EGL/egl.h>
 #include <EGL/eglext.h>
-#include <GLES/gl.h>
-#include <GLES/glext.h>
 
 #include <utils/RefBase.h>
 #include <utils/String8.h>
@@ -55,7 +53,6 @@
 class DisplayDevice;
 class GraphicBuffer;
 class SurfaceFlinger;
-class GLExtensions;
 
 // ---------------------------------------------------------------------------
 
@@ -113,14 +110,15 @@
 
     class LayerMesh {
         friend class Layer;
-        GLfloat mVertices[4][2];
+        typedef GLfloat float2[2];
+        float2 mVertices[4];
         size_t mNumVertices;
     public:
         LayerMesh() :
                 mNumVertices(4) {
         }
-        GLfloat const* getVertices() const {
-            return &mVertices[0][0];
+        float2 const* getVertices() const {
+            return mVertices;
         }
         size_t getVertexCount() const {
             return mNumVertices;
@@ -355,7 +353,6 @@
     String8 mName;
     mutable bool mDebug;
     PixelFormat mFormat;
-    const GLExtensions& mGLExtensions;
     bool mOpaqueLayer;
 
     // these are protected by an external lock
diff --git a/services/surfaceflinger/LayerDim.cpp b/services/surfaceflinger/LayerDim.cpp
index f4adeeb..062ad46 100644
--- a/services/surfaceflinger/LayerDim.cpp
+++ b/services/surfaceflinger/LayerDim.cpp
@@ -18,9 +18,6 @@
 #include <stdint.h>
 #include <sys/types.h>
 
-#include <GLES/gl.h>
-#include <GLES/glext.h>
-
 #include <utils/Errors.h>
 #include <utils/Log.h>
 
@@ -29,6 +26,7 @@
 #include "LayerDim.h"
 #include "SurfaceFlinger.h"
 #include "DisplayDevice.h"
+#include "RenderEngine/RenderEngine.h"
 
 namespace android {
 // ---------------------------------------------------------------------------
@@ -45,28 +43,12 @@
 {
     const State& s(getDrawingState());
     if (s.alpha>0) {
-        const GLfloat alpha = s.alpha/255.0f;
-        const uint32_t fbHeight = hw->getHeight();
-        glDisable(GL_TEXTURE_EXTERNAL_OES);
-        glDisable(GL_TEXTURE_2D);
-
-        if (s.alpha == 0xFF) {
-            glDisable(GL_BLEND);
-        } else {
-            glEnable(GL_BLEND);
-            glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
-        }
-
-        glColor4f(0, 0, 0, alpha);
-
         LayerMesh mesh;
         computeGeometry(hw, &mesh);
-
-        glVertexPointer(2, GL_FLOAT, 0, mesh.getVertices());
-        glDrawArrays(GL_TRIANGLE_FAN, 0, mesh.getVertexCount());
-
-        glDisable(GL_BLEND);
-        glDisableClientState(GL_TEXTURE_COORD_ARRAY);
+        RenderEngine& engine(mFlinger->getRenderEngine());
+        engine.setupDimLayerBlending(s.alpha);
+        engine.drawMesh2D(mesh.getVertices(), NULL, mesh.getVertexCount());
+        engine.disableBlending();
     }
 }
 
diff --git a/services/surfaceflinger/LayerDim.h b/services/surfaceflinger/LayerDim.h
index 2a96149..6561d7f 100644
--- a/services/surfaceflinger/LayerDim.h
+++ b/services/surfaceflinger/LayerDim.h
@@ -20,9 +20,6 @@
 #include <stdint.h>
 #include <sys/types.h>
 
-#include <EGL/egl.h>
-#include <EGL/eglext.h>
-
 #include "Layer.h"
 
 // ---------------------------------------------------------------------------
diff --git a/services/surfaceflinger/RenderEngine/GLES10RenderEngine.cpp b/services/surfaceflinger/RenderEngine/GLES10RenderEngine.cpp
new file mode 100644
index 0000000..9a47568
--- /dev/null
+++ b/services/surfaceflinger/RenderEngine/GLES10RenderEngine.cpp
@@ -0,0 +1,61 @@
+/*
+ * Copyright 2013 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 <GLES/gl.h>
+
+#include <cutils/compiler.h>
+
+#include "GLES10RenderEngine.h"
+
+// ---------------------------------------------------------------------------
+namespace android {
+// ---------------------------------------------------------------------------
+
+GLES10RenderEngine::~GLES10RenderEngine() {
+}
+
+void GLES10RenderEngine::setupLayerBlending(
+    bool premultipliedAlpha, bool opaque, int alpha) {
+    // OpenGL ES 1.0 doesn't support texture combiners.
+    // This path doesn't properly handle opaque layers that have non-opaque
+    // alpha values. The alpha channel will be copied into the framebuffer or
+    // screenshot, so if the framebuffer or screenshot is blended on top of
+    // something else,  whatever is below the window will incorrectly show
+    // through.
+    if (CC_UNLIKELY(alpha < 0xFF)) {
+        GLfloat floatAlpha = alpha * (1.0f / 255.0f);
+        if (premultipliedAlpha) {
+            glColor4f(floatAlpha, floatAlpha, floatAlpha, floatAlpha);
+        } else {
+            glColor4f(1.0f, 1.0f, 1.0f, floatAlpha);
+        }
+        glTexEnvx(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
+    } else {
+        glTexEnvx(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
+    }
+
+    if (alpha < 0xFF || !opaque) {
+        glEnable(GL_BLEND);
+        glBlendFunc(premultipliedAlpha ? GL_ONE : GL_SRC_ALPHA,
+                    GL_ONE_MINUS_SRC_ALPHA);
+    } else {
+        glDisable(GL_BLEND);
+    }
+}
+
+// ---------------------------------------------------------------------------
+}; // namespace android
+// ---------------------------------------------------------------------------
diff --git a/services/surfaceflinger/RenderEngine/GLES10RenderEngine.h b/services/surfaceflinger/RenderEngine/GLES10RenderEngine.h
new file mode 100644
index 0000000..f9c7c04
--- /dev/null
+++ b/services/surfaceflinger/RenderEngine/GLES10RenderEngine.h
@@ -0,0 +1,40 @@
+/*
+ * Copyright 2013 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 SF_GLES10RENDERENGINE_H_
+#define SF_GLES10RENDERENGINE_H_
+
+#include <stdint.h>
+#include <sys/types.h>
+
+#include "GLES11RenderEngine.h"
+
+// ---------------------------------------------------------------------------
+namespace android {
+// ---------------------------------------------------------------------------
+
+class GLES10RenderEngine : public GLES11RenderEngine {
+    virtual ~GLES10RenderEngine();
+protected:
+    virtual void setupLayerBlending(bool premultipliedAlpha, bool opaque, int alpha);
+};
+
+// ---------------------------------------------------------------------------
+}; // namespace android
+// ---------------------------------------------------------------------------
+
+#endif /* SF_GLES10RENDERENGINE_H_ */
diff --git a/services/surfaceflinger/RenderEngine/GLES11RenderEngine.cpp b/services/surfaceflinger/RenderEngine/GLES11RenderEngine.cpp
new file mode 100644
index 0000000..19499c9
--- /dev/null
+++ b/services/surfaceflinger/RenderEngine/GLES11RenderEngine.cpp
@@ -0,0 +1,217 @@
+/*
+ * Copyright 2013 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 <GLES/gl.h>
+
+#include <utils/String8.h>
+#include <cutils/compiler.h>
+
+#include "GLES11RenderEngine.h"
+#include "GLExtensions.h"
+
+// ---------------------------------------------------------------------------
+namespace android {
+// ---------------------------------------------------------------------------
+
+GLES11RenderEngine::GLES11RenderEngine() {
+
+    glGetIntegerv(GL_MAX_TEXTURE_SIZE, &mMaxTextureSize);
+    glGetIntegerv(GL_MAX_VIEWPORT_DIMS, mMaxViewportDims);
+
+    glPixelStorei(GL_UNPACK_ALIGNMENT, 4);
+    glPixelStorei(GL_PACK_ALIGNMENT, 4);
+    glEnableClientState(GL_VERTEX_ARRAY);
+    glShadeModel(GL_FLAT);
+    glDisable(GL_DITHER);
+    glDisable(GL_CULL_FACE);
+
+    struct pack565 {
+        inline uint16_t operator() (int r, int g, int b) const {
+            return (r<<11)|(g<<5)|b;
+        }
+    } pack565;
+
+    const uint16_t protTexData[] = { pack565(0x03, 0x03, 0x03) };
+    glGenTextures(1, &mProtectedTexName);
+    glBindTexture(GL_TEXTURE_2D, mProtectedTexName);
+    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_REPEAT);
+    glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
+    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, 1, 1, 0,
+            GL_RGB, GL_UNSIGNED_SHORT_5_6_5, protTexData);
+}
+
+GLES11RenderEngine::~GLES11RenderEngine() {
+}
+
+
+size_t GLES11RenderEngine::getMaxTextureSize() const {
+    return mMaxTextureSize;
+}
+
+size_t GLES11RenderEngine::getMaxViewportDims() const {
+    return
+        mMaxViewportDims[0] < mMaxViewportDims[1] ?
+            mMaxViewportDims[0] : mMaxViewportDims[1];
+}
+
+void GLES11RenderEngine::setViewportAndProjection(size_t w, size_t h) {
+    glViewport(0, 0, w, h);
+    glMatrixMode(GL_PROJECTION);
+    glLoadIdentity();
+    // put the origin in the left-bottom corner
+    glOrthof(0, w, 0, h, 0, 1); // l=0, r=w ; b=0, t=h
+    glMatrixMode(GL_MODELVIEW);
+}
+
+void GLES11RenderEngine::setupLayerBlending(
+    bool premultipliedAlpha, bool opaque, int alpha) {
+    GLenum combineRGB;
+    GLenum combineAlpha;
+    GLenum src0Alpha;
+    GLfloat envColor[4];
+
+    if (CC_UNLIKELY(alpha < 0xFF)) {
+        // Cv = premultiplied ? Cs*alpha : Cs
+        // Av = !opaque       ? alpha*As : 1.0
+        combineRGB   = premultipliedAlpha ? GL_MODULATE : GL_REPLACE;
+        combineAlpha = !opaque            ? GL_MODULATE : GL_REPLACE;
+        src0Alpha    = GL_CONSTANT;
+        envColor[0]  = alpha * (1.0f / 255.0f);
+    } else {
+        // Cv = Cs
+        // Av = opaque ? 1.0 : As
+        combineRGB   = GL_REPLACE;
+        combineAlpha = GL_REPLACE;
+        src0Alpha    = opaque ? GL_CONSTANT : GL_TEXTURE;
+        envColor[0]  = 1.0f;
+    }
+
+    glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE);
+    glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB, combineRGB);
+    glTexEnvi(GL_TEXTURE_ENV, GL_SRC0_RGB, GL_TEXTURE);
+    glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_RGB, GL_SRC_COLOR);
+    if (combineRGB == GL_MODULATE) {
+        glTexEnvi(GL_TEXTURE_ENV, GL_SRC1_RGB, GL_CONSTANT);
+        glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND1_RGB, GL_SRC_COLOR);
+    }
+    glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA, combineAlpha);
+    glTexEnvi(GL_TEXTURE_ENV, GL_SRC0_ALPHA, src0Alpha);
+    glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_ALPHA, GL_SRC_ALPHA);
+    if (combineAlpha == GL_MODULATE) {
+        glTexEnvi(GL_TEXTURE_ENV, GL_SRC1_ALPHA, GL_TEXTURE);
+        glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND1_ALPHA, GL_SRC_ALPHA);
+    }
+    if (combineRGB == GL_MODULATE || src0Alpha == GL_CONSTANT) {
+        envColor[1] = envColor[0];
+        envColor[2] = envColor[0];
+        envColor[3] = envColor[0];
+        glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, envColor);
+    }
+
+    if (alpha < 0xFF || !opaque) {
+        glEnable(GL_BLEND);
+        glBlendFunc(premultipliedAlpha ? GL_ONE : GL_SRC_ALPHA,
+                    GL_ONE_MINUS_SRC_ALPHA);
+    } else {
+        glDisable(GL_BLEND);
+    }
+}
+
+void GLES11RenderEngine::setupDimLayerBlending(int alpha) {
+    glDisable(GL_TEXTURE_EXTERNAL_OES);
+    glDisable(GL_TEXTURE_2D);
+    if (alpha == 0xFF) {
+        glDisable(GL_BLEND);
+    } else {
+        glEnable(GL_BLEND);
+        glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
+    }
+    glColor4f(0, 0, 0, alpha/255.0f);
+}
+
+void GLES11RenderEngine::setupLayerTexturing(size_t textureName,
+    bool useFiltering, const float* textureMatrix) {
+    glBindTexture(GL_TEXTURE_EXTERNAL_OES, textureName);
+    GLenum filter = GL_NEAREST;
+    if (useFiltering) {
+        filter = GL_LINEAR;
+    }
+    glTexParameterx(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
+    glTexParameterx(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
+    glTexParameterx(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_MAG_FILTER, filter);
+    glTexParameterx(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_MIN_FILTER, filter);
+    glMatrixMode(GL_TEXTURE);
+    glLoadMatrixf(textureMatrix);
+    glMatrixMode(GL_MODELVIEW);
+    glDisable(GL_TEXTURE_2D);
+    glEnable(GL_TEXTURE_EXTERNAL_OES);
+}
+
+void GLES11RenderEngine::setupLayerBlackedOut() {
+    glBindTexture(GL_TEXTURE_2D, mProtectedTexName);
+    glMatrixMode(GL_TEXTURE);
+    glLoadIdentity();
+    glMatrixMode(GL_MODELVIEW);
+    glDisable(GL_TEXTURE_EXTERNAL_OES);
+    glEnable(GL_TEXTURE_2D);
+}
+
+void GLES11RenderEngine::disableTexturing() {
+    glDisable(GL_TEXTURE_EXTERNAL_OES);
+    glDisable(GL_TEXTURE_2D);
+}
+
+void GLES11RenderEngine::disableBlending() {
+    glDisable(GL_BLEND);
+}
+
+void GLES11RenderEngine::clearWithColor(const float vertices[][2] , size_t count,
+    float red, float green, float blue, float alpha) {
+    glColor4f(red, green, blue, alpha);
+    glDisable(GL_TEXTURE_EXTERNAL_OES);
+    glDisable(GL_TEXTURE_2D);
+    glDisable(GL_BLEND);
+    glVertexPointer(2, GL_FLOAT, 0, vertices);
+    glDrawArrays(GL_TRIANGLE_FAN, 0, count);
+}
+
+void GLES11RenderEngine::drawMesh2D(
+    const float vertices[][2], const float texCoords[][2], size_t count) {
+    if (texCoords) {
+        glEnableClientState(GL_TEXTURE_COORD_ARRAY);
+        glTexCoordPointer(2, GL_FLOAT, 0, texCoords);
+    }
+    glVertexPointer(2, GL_FLOAT, 0, vertices);
+    glDrawArrays(GL_TRIANGLE_FAN, 0, count);
+    if (texCoords) {
+        glDisableClientState(GL_TEXTURE_COORD_ARRAY);
+    }
+}
+
+void GLES11RenderEngine::dump(String8& result) {
+    const GLExtensions& extensions(GLExtensions::getInstance());
+    result.appendFormat("GLES: %s, %s, %s\n",
+            extensions.getVendor(),
+            extensions.getRenderer(),
+            extensions.getVersion());
+    result.appendFormat("%s\n", extensions.getExtension());
+}
+
+// ---------------------------------------------------------------------------
+}; // namespace android
+// ---------------------------------------------------------------------------
diff --git a/services/surfaceflinger/RenderEngine/GLES11RenderEngine.h b/services/surfaceflinger/RenderEngine/GLES11RenderEngine.h
new file mode 100644
index 0000000..15054bd
--- /dev/null
+++ b/services/surfaceflinger/RenderEngine/GLES11RenderEngine.h
@@ -0,0 +1,67 @@
+/*
+ * Copyright 2013 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 SF_GLES11RENDERENGINE_H_
+#define SF_GLES11RENDERENGINE_H_
+
+#include <stdint.h>
+#include <sys/types.h>
+
+#include <GLES/gl.h>
+
+#include "RenderEngine.h"
+
+// ---------------------------------------------------------------------------
+namespace android {
+// ---------------------------------------------------------------------------
+
+class String8;
+
+class GLES11RenderEngine : public RenderEngine {
+    GLuint mProtectedTexName;
+    GLint mMaxViewportDims[2];
+    GLint mMaxTextureSize;
+
+public:
+    GLES11RenderEngine();
+
+protected:
+    virtual ~GLES11RenderEngine();
+
+    virtual void dump(String8& result);
+    virtual void setViewportAndProjection(size_t w, size_t h);
+    virtual void setupLayerBlending(bool premultipliedAlpha, bool opaque, int alpha);
+    virtual void setupDimLayerBlending(int alpha);
+    virtual void setupLayerTexturing(size_t textureName, bool useFiltering, const float* textureMatrix);
+    virtual void setupLayerBlackedOut();
+    virtual void disableTexturing();
+    virtual void disableBlending();
+
+    virtual void clearWithColor(const float vertices[][2], size_t count,
+        float red, float green, float blue, float alpha);
+
+    virtual void drawMesh2D(const float vertices[][2], const float texCoords[][2], size_t count);
+
+    virtual size_t getMaxTextureSize() const;
+    virtual size_t getMaxViewportDims() const;
+};
+
+// ---------------------------------------------------------------------------
+}; // namespace android
+// ---------------------------------------------------------------------------
+
+#endif /* SF_GLES11RENDERENGINE_H_ */
diff --git a/services/surfaceflinger/RenderEngine/GLExtensions.cpp b/services/surfaceflinger/RenderEngine/GLExtensions.cpp
new file mode 100644
index 0000000..76bbcc1
--- /dev/null
+++ b/services/surfaceflinger/RenderEngine/GLExtensions.cpp
@@ -0,0 +1,83 @@
+/*
+ * 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()
+    : mHaveFramebufferObject(false)
+{
+}
+
+void GLExtensions::initWithGLStrings(
+        GLubyte const* vendor,
+        GLubyte const* renderer,
+        GLubyte const* version,
+        GLubyte const* extensions)
+{
+    mVendor     = (char const*)vendor;
+    mRenderer   = (char const*)renderer;
+    mVersion    = (char const*)version;
+    mExtensions = (char const*)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);
+
+    if (hasExtension("GL_OES_framebuffer_object")) {
+        mHaveFramebufferObject = 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();
+}
+
+// ---------------------------------------------------------------------------
+}; // namespace android
diff --git a/services/surfaceflinger/GLExtensions.h b/services/surfaceflinger/RenderEngine/GLExtensions.h
similarity index 73%
rename from services/surfaceflinger/GLExtensions.h
rename to services/surfaceflinger/RenderEngine/GLExtensions.h
index c86c66a..d81ed2a 100644
--- a/services/surfaceflinger/GLExtensions.h
+++ b/services/surfaceflinger/RenderEngine/GLExtensions.h
@@ -36,18 +36,12 @@
 {
     friend class Singleton<GLExtensions>;
 
-    bool mHaveTextureExternal   : 1;
-    bool mHaveNpot              : 1;
-    bool mHaveDirectTexture     : 1;
     bool mHaveFramebufferObject : 1;
 
     String8 mVendor;
     String8 mRenderer;
     String8 mVersion;
     String8 mExtensions;
-    String8 mEglVendor;
-    String8 mEglVersion;
-    String8 mEglExtensions;
     SortedVector<String8> mExtensionList;
 
     GLExtensions(const GLExtensions&);
@@ -57,15 +51,6 @@
     GLExtensions();
 
 public:
-    inline bool haveTextureExternal() const {
-        return mHaveTextureExternal;
-    }
-    inline bool haveNpot() const {
-        return mHaveNpot;
-    }
-    inline bool haveDirectTexture() const {
-        return mHaveDirectTexture;
-    }
 
     inline bool haveFramebufferObject() const {
         return mHaveFramebufferObject;
@@ -75,20 +60,13 @@
             GLubyte const* vendor,
             GLubyte const* renderer,
             GLubyte const* version,
-            GLubyte const* extensions,
-            char const* egl_vendor,
-            char const* egl_version,
-            char const* egl_extensions);
+            GLubyte const* 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;
 };
 
diff --git a/services/surfaceflinger/RenderEngine/RenderEngine.cpp b/services/surfaceflinger/RenderEngine/RenderEngine.cpp
new file mode 100644
index 0000000..cb77e38
--- /dev/null
+++ b/services/surfaceflinger/RenderEngine/RenderEngine.cpp
@@ -0,0 +1,145 @@
+/*
+ * Copyright 2013 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 <cutils/log.h>
+
+#include "RenderEngine.h"
+#include "GLES10RenderEngine.h"
+#include "GLES11RenderEngine.h"
+#include "GLExtensions.h"
+
+// ---------------------------------------------------------------------------
+namespace android {
+// ---------------------------------------------------------------------------
+
+RenderEngine* RenderEngine::create(EGLDisplay display, EGLConfig config) {
+    // Also create our EGLContext
+    EGLint contextAttributes[] = {
+//            EGL_CONTEXT_CLIENT_VERSION, 2,
+#ifdef EGL_IMG_context_priority
+#ifdef HAS_CONTEXT_PRIORITY
+#warning "using EGL_IMG_context_priority"
+            EGL_CONTEXT_PRIORITY_LEVEL_IMG, EGL_CONTEXT_PRIORITY_HIGH_IMG,
+#endif
+#endif
+            EGL_NONE, EGL_NONE
+    };
+
+    EGLContext ctxt = eglCreateContext(display, config, NULL, contextAttributes);
+    if (ctxt == EGL_NO_CONTEXT) {
+        // maybe ES 2.x is not supported
+        ALOGW("can't create an ES 2.x context, trying 1.x");
+        ctxt = eglCreateContext(display, config, NULL, contextAttributes + 2);
+    }
+
+    // if can't create a GL context, we can only abort.
+    LOG_ALWAYS_FATAL_IF(ctxt==EGL_NO_CONTEXT, "EGLContext creation failed");
+
+
+    // now figure out what version of GL did we actually get
+    // NOTE: a dummy surface is not needed if KHR_create_context is supported
+
+    EGLint attribs[] = { EGL_WIDTH, 1, EGL_HEIGHT, 1, EGL_NONE, EGL_NONE };
+    EGLSurface dummy = eglCreatePbufferSurface(display, config, attribs);
+    LOG_ALWAYS_FATAL_IF(dummy==EGL_NO_SURFACE, "can't create dummy pbuffer");
+    EGLBoolean success = eglMakeCurrent(display, dummy, dummy, ctxt);
+    LOG_ALWAYS_FATAL_IF(!success, "can't make dummy pbuffer current");
+
+    GLExtensions& extensions(GLExtensions::getInstance());
+    extensions.initWithGLStrings(
+            glGetString(GL_VENDOR),
+            glGetString(GL_RENDERER),
+            glGetString(GL_VERSION),
+            glGetString(GL_EXTENSIONS));
+
+    GlesVersion version = parseGlesVersion( extensions.getVersion() );
+
+    // initialize the renderer while GL is current
+
+    RenderEngine* engine = NULL;
+    switch (version) {
+    case GLES_VERSION_1_0:
+        engine = new GLES10RenderEngine();
+        break;
+    case GLES_VERSION_1_1:
+        engine = new GLES11RenderEngine();
+        break;
+    case GLES_VERSION_2_0:
+    case GLES_VERSION_3_0:
+        //engine = new GLES20RenderEngine();
+        break;
+    }
+    engine->setEGLContext(ctxt);
+
+    ALOGI("OpenGL ES informations:");
+    ALOGI("vendor    : %s", extensions.getVendor());
+    ALOGI("renderer  : %s", extensions.getRenderer());
+    ALOGI("version   : %s", extensions.getVersion());
+    ALOGI("extensions: %s", extensions.getExtension());
+    ALOGI("GL_MAX_TEXTURE_SIZE = %d", engine->getMaxTextureSize());
+    ALOGI("GL_MAX_VIEWPORT_DIMS = %d", engine->getMaxViewportDims());
+
+    eglMakeCurrent(display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
+    eglDestroySurface(display, dummy);
+
+    return engine;
+}
+
+RenderEngine::RenderEngine() : mEGLContext(EGL_NO_CONTEXT) {
+}
+
+RenderEngine::~RenderEngine() {
+}
+
+void RenderEngine::setEGLContext(EGLContext ctxt) {
+    mEGLContext = ctxt;
+}
+
+EGLContext RenderEngine::getEGLContext() const {
+    return mEGLContext;
+}
+
+void RenderEngine::checkErrors() const {
+    do {
+        // there could be more than one error flag
+        GLenum error = glGetError();
+        if (error == GL_NO_ERROR)
+            break;
+        ALOGE("GL error 0x%04x", int(error));
+    } while (true);
+}
+
+RenderEngine::GlesVersion RenderEngine::parseGlesVersion(const char* str) {
+    int major, minor;
+    if (sscanf(str, "OpenGL ES-CM %d.%d", &major, &minor) != 2) {
+        if (sscanf(str, "OpenGL ES %d.%d", &major, &minor) != 2) {
+            ALOGW("Unable to parse GL_VERSION string: \"%s\"", str);
+            return GLES_VERSION_1_0;
+        }
+    }
+
+    if (major == 1 && minor == 0) return GLES_VERSION_1_0;
+    if (major == 1 && minor >= 1) return GLES_VERSION_1_1;
+    if (major == 2 && minor >= 0) return GLES_VERSION_2_0;
+    if (major == 3 && minor >= 0) return GLES_VERSION_3_0;
+
+    ALOGW("Unrecognized OpenGL ES version: %d.%d", major, minor);
+    return GLES_VERSION_1_0;
+}
+
+// ---------------------------------------------------------------------------
+}; // namespace android
+// ---------------------------------------------------------------------------
diff --git a/services/surfaceflinger/RenderEngine/RenderEngine.h b/services/surfaceflinger/RenderEngine/RenderEngine.h
new file mode 100644
index 0000000..e43bfa4
--- /dev/null
+++ b/services/surfaceflinger/RenderEngine/RenderEngine.h
@@ -0,0 +1,78 @@
+/*
+ * Copyright 2013 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 SF_RENDERENGINE_H_
+#define SF_RENDERENGINE_H_
+
+#include <stdint.h>
+#include <sys/types.h>
+
+#include <EGL/egl.h>
+
+// ---------------------------------------------------------------------------
+namespace android {
+// ---------------------------------------------------------------------------
+
+class String8;
+
+class RenderEngine {
+    enum GlesVersion {
+        GLES_VERSION_1_0    = 0x10000,
+        GLES_VERSION_1_1    = 0x10001,
+        GLES_VERSION_2_0    = 0x20000,
+        GLES_VERSION_3_0    = 0x30000,
+    };
+    static GlesVersion parseGlesVersion(const char* str);
+
+    EGLContext mEGLContext;
+    void setEGLContext(EGLContext ctxt);
+
+protected:
+    RenderEngine();
+    virtual ~RenderEngine() = 0;
+
+public:
+    static RenderEngine* create(EGLDisplay display, EGLConfig config);
+
+    virtual void checkErrors() const;
+
+    virtual void dump(String8& result) = 0;
+    virtual void setViewportAndProjection(size_t w, size_t h) = 0;
+    virtual void setupLayerBlending(bool premultipliedAlpha, bool opaque, int alpha) = 0;
+    virtual void setupDimLayerBlending(int alpha) = 0;
+    virtual void setupLayerTexturing(size_t textureName, bool useFiltering, const float* textureMatrix) = 0;
+    virtual void setupLayerBlackedOut() = 0;
+
+    virtual void disableTexturing() = 0;
+    virtual void disableBlending() = 0;
+
+    virtual void clearWithColor(const float vertices[][2], size_t count,
+        float red, float green, float blue, float alpha) = 0;
+
+    virtual void drawMesh2D(const float vertices[][2], const float texCoords[][2], size_t count) = 0;
+
+    virtual size_t getMaxTextureSize() const = 0;
+    virtual size_t getMaxViewportDims() const = 0;
+
+    EGLContext getEGLContext() const;
+};
+
+// ---------------------------------------------------------------------------
+}; // namespace android
+// ---------------------------------------------------------------------------
+
+#endif /* SF_RENDERENGINE_H_ */
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index fc193e5..5d138d1 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -24,6 +24,7 @@
 
 #include <EGL/egl.h>
 #include <GLES/gl.h>
+#include <GLES/glext.h>
 
 #include <cutils/log.h>
 #include <cutils/properties.h>
@@ -61,7 +62,6 @@
 #include "DdmConnection.h"
 #include "DisplayDevice.h"
 #include "EventThread.h"
-#include "GLExtensions.h"
 #include "Layer.h"
 #include "LayerDim.h"
 #include "SurfaceFlinger.h"
@@ -70,6 +70,8 @@
 #include "DisplayHardware/HWComposer.h"
 #include "DisplayHardware/VirtualDisplaySurface.h"
 
+#include "RenderEngine/RenderEngine.h"
+
 #define DISPLAY_COUNT       1
 
 EGLAPI const char* eglQueryStringImplementationANDROID(EGLDisplay dpy, EGLint name);
@@ -91,6 +93,7 @@
         mAnimTransactionPending(false),
         mLayersRemoved(false),
         mRepaintEverything(0),
+        mRenderEngine(NULL),
         mBootTime(systemTime()),
         mVisibleRegionsDirty(false),
         mHwWorkListDirty(false),
@@ -349,7 +352,9 @@
     status_t err;
 
     EGLAttributeVector attribs;
-    attribs[EGL_SURFACE_TYPE]               = EGL_WINDOW_BIT;
+    // TODO: enable ES2
+    //attribs[EGL_RENDERABLE_TYPE]            = EGL_OPENGL_ES_BIT | EGL_OPENGL_ES2_BIT;
+    attribs[EGL_SURFACE_TYPE]               = EGL_WINDOW_BIT | EGL_PBUFFER_BIT;
     attribs[EGL_RECORDABLE_ANDROID]         = EGL_TRUE;
     attribs[EGL_FRAMEBUFFER_TARGET_ANDROID] = EGL_TRUE;
     attribs[EGL_RED_SIZE]                   = 8;
@@ -360,25 +365,12 @@
     if (!err)
         goto success;
 
-    // maybe we failed because of EGL_FRAMEBUFFER_TARGET_ANDROID
-    ALOGW("no suitable EGLConfig found, trying without EGL_FRAMEBUFFER_TARGET_ANDROID");
+    // this didn't work, probably because we're on the emulator...
+    // try a simplified query
+    ALOGW("no suitable EGLConfig found, trying a simpler query");
+    attribs.remove(EGL_RENDERABLE_TYPE);
     attribs.remove(EGL_FRAMEBUFFER_TARGET_ANDROID);
-    err = selectConfigForAttribute(display, attribs,
-            EGL_NATIVE_VISUAL_ID, nativeVisualId, &config);
-    if (!err)
-        goto success;
-
-    // maybe we failed because of EGL_RECORDABLE_ANDROID
-    ALOGW("no suitable EGLConfig found, trying without EGL_RECORDABLE_ANDROID");
     attribs.remove(EGL_RECORDABLE_ANDROID);
-    err = selectConfigForAttribute(display, attribs,
-            EGL_NATIVE_VISUAL_ID, nativeVisualId, &config);
-    if (!err)
-        goto success;
-
-    // allow less than 24-bit color; the non-gpu-accelerated emulator only
-    // supports 16-bit color
-    ALOGW("no suitable EGLConfig found, trying with 16-bit color allowed");
     attribs.remove(EGL_RED_SIZE);
     attribs.remove(EGL_GREEN_SIZE);
     attribs.remove(EGL_BLUE_SIZE);
@@ -388,8 +380,7 @@
         goto success;
 
     // this EGL is too lame for Android
-    ALOGE("no suitable EGLConfig found, giving up");
-
+    LOG_ALWAYS_FATAL("no suitable EGLConfig found, giving up");
     return 0;
 
 success:
@@ -398,97 +389,6 @@
     return config;
 }
 
-EGLContext SurfaceFlinger::createGLContext(EGLDisplay display, EGLConfig config) {
-    // Also create our EGLContext
-    EGLint contextAttributes[] = {
-#ifdef EGL_IMG_context_priority
-#ifdef HAS_CONTEXT_PRIORITY
-#warning "using EGL_IMG_context_priority"
-            EGL_CONTEXT_PRIORITY_LEVEL_IMG, EGL_CONTEXT_PRIORITY_HIGH_IMG,
-#endif
-#endif
-            EGL_NONE, EGL_NONE
-    };
-    EGLContext ctxt = eglCreateContext(display, config, NULL, contextAttributes);
-    ALOGE_IF(ctxt==EGL_NO_CONTEXT, "EGLContext creation failed");
-    return ctxt;
-}
-
-static GlesVersion parseGlesVersion(const char* str) {
-    int major, minor;
-    if (sscanf(str, "OpenGL ES-CM %d.%d", &major, &minor) != 2) {
-        ALOGW("Unable to parse GL_VERSION string: \"%s\"", str);
-        return GLES_VERSION_1_0;
-    }
-
-    if (major == 1 && minor == 0) return GLES_VERSION_1_0;
-    if (major == 1 && minor >= 1) return GLES_VERSION_1_1;
-    if (major == 2 && minor >= 0) return GLES_VERSION_2_0;
-    if (major == 3 && minor >= 0) return GLES_VERSION_3_0;
-
-    ALOGW("Unrecognized OpenGL ES version: %d.%d", major, minor);
-    return GLES_VERSION_1_0;
-}
-
-void SurfaceFlinger::initializeGL(EGLDisplay display) {
-    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));
-
-    mGlesVersion = parseGlesVersion(extensions.getVersion());
-
-    glGetIntegerv(GL_MAX_TEXTURE_SIZE, &mMaxTextureSize);
-    glGetIntegerv(GL_MAX_VIEWPORT_DIMS, mMaxViewportDims);
-
-    glPixelStorei(GL_UNPACK_ALIGNMENT, 4);
-    glPixelStorei(GL_PACK_ALIGNMENT, 4);
-    glEnableClientState(GL_VERTEX_ARRAY);
-    glShadeModel(GL_FLAT);
-    glDisable(GL_DITHER);
-    glDisable(GL_CULL_FACE);
-
-    struct pack565 {
-        inline uint16_t operator() (int r, int g, int b) const {
-            return (r<<11)|(g<<5)|b;
-        }
-    } pack565;
-
-    const uint16_t protTexData[] = { pack565(0x03, 0x03, 0x03) };
-    glGenTextures(1, &mProtectedTexName);
-    glBindTexture(GL_TEXTURE_2D, mProtectedTexName);
-    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_REPEAT);
-    glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
-    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, 1, 1, 0,
-            GL_RGB, GL_UNSIGNED_SHORT_5_6_5, protTexData);
-
-    // print some debugging info
-    EGLint r,g,b,a;
-    eglGetConfigAttrib(display, mEGLConfig, EGL_RED_SIZE,   &r);
-    eglGetConfigAttrib(display, mEGLConfig, EGL_GREEN_SIZE, &g);
-    eglGetConfigAttrib(display, mEGLConfig, EGL_BLUE_SIZE,  &b);
-    eglGetConfigAttrib(display, mEGLConfig, EGL_ALPHA_SIZE, &a);
-    ALOGI("EGL informations:");
-    ALOGI("vendor    : %s", extensions.getEglVendor());
-    ALOGI("version   : %s", extensions.getEglVersion());
-    ALOGI("extensions: %s", extensions.getEglExtension());
-    ALOGI("Client API: %s", eglQueryString(display, EGL_CLIENT_APIS)?:"Not Supported");
-    ALOGI("EGLSurface: %d-%d-%d-%d, config=%p", r, g, b, a, mEGLConfig);
-    ALOGI("OpenGL ES informations:");
-    ALOGI("vendor    : %s", extensions.getVendor());
-    ALOGI("renderer  : %s", extensions.getRenderer());
-    ALOGI("version   : %s", extensions.getVersion());
-    ALOGI("extensions: %s", extensions.getExtension());
-    ALOGI("GL_MAX_TEXTURE_SIZE = %d", mMaxTextureSize);
-    ALOGI("GL_MAX_VIEWPORT_DIMS = %d x %d", mMaxViewportDims[0], mMaxViewportDims[1]);
-}
 
 status_t SurfaceFlinger::readyToRun()
 {
@@ -506,10 +406,27 @@
     mHwc = new HWComposer(this,
             *static_cast<HWComposer::EventHandler *>(this));
 
-    // initialize the config and context
-    EGLint format = mHwc->getVisualID();
-    mEGLConfig  = selectEGLConfig(mEGLDisplay, format);
-    mEGLContext = createGLContext(mEGLDisplay, mEGLConfig);
+    // initialize the config and context (can't fail)
+    mEGLConfig = selectEGLConfig(mEGLDisplay, mHwc->getVisualID());
+
+    // print some debugging info
+    EGLint r,g,b,a;
+    eglGetConfigAttrib(mEGLDisplay, mEGLConfig, EGL_RED_SIZE,   &r);
+    eglGetConfigAttrib(mEGLDisplay, mEGLConfig, EGL_GREEN_SIZE, &g);
+    eglGetConfigAttrib(mEGLDisplay, mEGLConfig, EGL_BLUE_SIZE,  &b);
+    eglGetConfigAttrib(mEGLDisplay, mEGLConfig, EGL_ALPHA_SIZE, &a);
+    ALOGI("EGL informations:");
+    ALOGI("vendor    : %s", eglQueryString(mEGLDisplay, EGL_VENDOR));
+    ALOGI("version   : %s", eglQueryString(mEGLDisplay, EGL_VERSION));
+    ALOGI("extensions: %s", eglQueryString(mEGLDisplay, EGL_EXTENSIONS));
+    ALOGI("Client API: %s", eglQueryString(mEGLDisplay, EGL_CLIENT_APIS)?:"Not Supported");
+    ALOGI("EGLSurface: %d-%d-%d-%d, config=%p", r, g, b, a, mEGLConfig);
+
+    // get a RenderEngine for the given display / config (can't fail)
+    mRenderEngine = RenderEngine::create(mEGLDisplay, mEGLConfig);
+
+    // retrieve the EGL context that was selected/created
+    mEGLContext = mRenderEngine->getEGLContext();
 
     // figure out which format we got
     eglGetConfigAttrib(mEGLDisplay, mEGLConfig,
@@ -543,17 +460,6 @@
         }
     }
 
-    //  we need a GL context current in a few places, when initializing
-    //  OpenGL ES (see below), or creating a layer,
-    //  or when a texture is (asynchronously) destroyed, and for that
-    //  we need a valid surface, so it's convenient to use the main display
-    //  for that.
-    sp<const DisplayDevice> hw(getDefaultDisplayDevice());
-
-    //  initialize OpenGL ES
-    DisplayDevice::makeCurrent(mEGLDisplay, hw, mEGLContext);
-    initializeGL(mEGLDisplay);
-
     // start the EventThread
     mEventThread = new EventThread(this);
     mEventQueue.setEventThread(mEventThread);
@@ -561,7 +467,6 @@
     // initialize our drawing state
     mDrawingState = mCurrentState;
 
-
     // We're now ready to accept clients...
     mReadyToRunBarrier.open();
 
@@ -585,13 +490,12 @@
     property_set("ctl.start", "bootanim");
 }
 
-uint32_t SurfaceFlinger::getMaxTextureSize() const {
-    return mMaxTextureSize;
+size_t SurfaceFlinger::getMaxTextureSize() const {
+    return mRenderEngine->getMaxTextureSize();
 }
 
-uint32_t SurfaceFlinger::getMaxViewportDims() const {
-    return mMaxViewportDims[0] < mMaxViewportDims[1] ?
-            mMaxViewportDims[0] : mMaxViewportDims[1];
+size_t SurfaceFlinger::getMaxViewportDims() const {
+    return mRenderEngine->getMaxViewportDims();
 }
 
 // ----------------------------------------------------------------------------
@@ -1023,8 +927,7 @@
             // EGL spec says:
             //   "surface must be bound to the calling thread's current context,
             //    for the current rendering API."
-            DisplayDevice::makeCurrent(mEGLDisplay,
-                    getDefaultDisplayDevice(), mEGLContext);
+            getDefaultDisplayDevice()->makeCurrent(mEGLDisplay, mEGLContext);
         }
         hwc.commit();
     }
@@ -1131,7 +1034,7 @@
                         // be sure that nothing associated with this display
                         // is current.
                         const sp<const DisplayDevice> defaultDisplay(getDefaultDisplayDevice());
-                        DisplayDevice::makeCurrent(mEGLDisplay, defaultDisplay, mEGLContext);
+                        defaultDisplay->makeCurrent(mEGLDisplay, mEGLContext);
                         sp<DisplayDevice> hw(getDisplayDevice(draw.keyAt(i)));
                         if (hw != NULL)
                             hw->disconnect(getHwComposer());
@@ -1562,7 +1465,7 @@
 
     const bool hasGlesComposition = hwc.hasGlesComposition(id) || (cur==end);
     if (hasGlesComposition) {
-        if (!DisplayDevice::makeCurrent(mEGLDisplay, hw, mEGLContext)) {
+        if (!hw->makeCurrent(mEGLDisplay, mEGLContext)) {
             ALOGW("DisplayDevice::makeCurrent failed. Aborting surface composition for display %s",
                   hw->getDisplayName().string());
             return;
@@ -2383,7 +2286,6 @@
 
     HWComposer& hwc(getHwComposer());
     sp<const DisplayDevice> hw(getDefaultDisplayDevice());
-    const GLExtensions& extensions(GLExtensions::getInstance());
 
     colorizer.bold(result);
     result.appendFormat("EGL implementation : %s\n",
@@ -2392,13 +2294,7 @@
     result.appendFormat("%s\n",
             eglQueryStringImplementationANDROID(mEGLDisplay, EGL_EXTENSIONS));
 
-    colorizer.bold(result);
-    result.appendFormat("GLES: %s, %s, %s\n",
-            extensions.getVendor(),
-            extensions.getRenderer(),
-            extensions.getVersion());
-    colorizer.reset(result);
-    result.appendFormat("%s\n", extensions.getExtension());
+    mRenderEngine->dump(result);
 
     hw->undefinedRegion.dump(result, "undefinedRegion");
     result.appendFormat("  orientation=%d, canDraw=%d\n",
@@ -2731,10 +2627,6 @@
 {
     ATRACE_CALL();
 
-    if (!GLExtensions::getInstance().haveFramebufferObject()) {
-        return INVALID_OPERATION;
-    }
-
     // get screen geometry
     const uint32_t hw_w = hw->getWidth();
     const uint32_t hw_h = hw->getHeight();
@@ -2793,7 +2685,7 @@
                         glGenFramebuffersOES(1, &name);
                         glBindFramebufferOES(GL_FRAMEBUFFER_OES, name);
                         glFramebufferTexture2DOES(GL_FRAMEBUFFER_OES,
-                                GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, tname, 0);
+                                GL_COLOR_ATTACHMENT0_OES, GL_TEXTURE_2D, tname, 0);
                     } else {
                         // since we're going to use glReadPixels() anyways,
                         // use an intermediate renderbuffer instead
@@ -2851,7 +2743,7 @@
         native_window_api_disconnect(window, NATIVE_WINDOW_API_EGL);
     }
 
-    DisplayDevice::setViewportAndProjection(hw);
+    hw->setViewportAndProjection();
 
     return result;
 }
diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h
index 089c265..c0815f8 100644
--- a/services/surfaceflinger/SurfaceFlinger.h
+++ b/services/surfaceflinger/SurfaceFlinger.h
@@ -21,7 +21,7 @@
 #include <sys/types.h>
 
 #include <EGL/egl.h>
-#include <GLES/gl.h>
+#include <GLES/gl.h>        // needed for GLuint
 
 #include <cutils/compiler.h>
 
@@ -62,6 +62,7 @@
 class Layer;
 class LayerDim;
 class Surface;
+class RenderEngine;
 
 // ---------------------------------------------------------------------------
 
@@ -72,13 +73,6 @@
     eTransactionMask          = 0x07
 };
 
-enum GlesVersion {
-    GLES_VERSION_1_0    = 0x10000,
-    GLES_VERSION_1_1    = 0x10001,
-    GLES_VERSION_2_0    = 0x20000,
-    GLES_VERSION_3_0    = 0x30000,
-};
-
 class SurfaceFlinger : public BinderService<SurfaceFlinger>,
                        public BnSurfaceComposer,
                        private IBinder::DeathRecipient,
@@ -128,9 +122,8 @@
     // TODO: this should be made accessible only to HWComposer
     const Vector< sp<Layer> >& getLayerSortedByZForHwcDisplay(int id);
 
-    // return the version of the OpenGL ES composition context
-    GlesVersion getGlesVersion() const {
-        return mGlesVersion;
+    RenderEngine& getRenderEngine() const {
+        return *mRenderEngine;
     }
 
 private:
@@ -319,10 +312,8 @@
     static status_t selectConfigForAttribute(EGLDisplay dpy,
         EGLint const* attrs, EGLint attribute, EGLint value, EGLConfig* outConfig);
     static EGLConfig selectEGLConfig(EGLDisplay disp, EGLint visualId);
-    static EGLContext createGLContext(EGLDisplay disp, EGLConfig config);
-    void initializeGL(EGLDisplay display);
-    uint32_t getMaxTextureSize() const;
-    uint32_t getMaxViewportDims() const;
+    size_t getMaxTextureSize() const;
+    size_t getMaxViewportDims() const;
 
     /* ------------------------------------------------------------------------
      * Display and layer stack management
@@ -378,9 +369,6 @@
     void postFramebuffer();
     void drawWormhole(const sp<const DisplayDevice>& hw,
             const Region& region) const;
-    GLuint getProtectedTexName() const {
-        return mProtectedTexName;
-    }
 
     /* ------------------------------------------------------------------------
      * Display management
@@ -423,17 +411,14 @@
 
     // constant members (no synchronization needed for access)
     HWComposer* mHwc;
-    GLuint mProtectedTexName;
+    RenderEngine* mRenderEngine;
     nsecs_t mBootTime;
     bool mGpuToCpuSupported;
     sp<EventThread> mEventThread;
-    GLint mMaxViewportDims[2];
-    GLint mMaxTextureSize;
     EGLContext mEGLContext;
     EGLConfig mEGLConfig;
     EGLDisplay mEGLDisplay;
     EGLint mEGLNativeVisualId;
-    GlesVersion mGlesVersion;
     sp<IBinder> mBuiltinDisplays[DisplayDevice::NUM_DISPLAY_TYPES];
 
     // Can only accessed from the main thread, these members