Migrate most GL from context to driver.

Change-Id: I5cba3a6e879d2e9332fc667a1061a5312fcf14ba
diff --git a/libs/rs/Android.mk b/libs/rs/Android.mk
index 3362c7d..ea7f477 100644
--- a/libs/rs/Android.mk
+++ b/libs/rs/Android.mk
@@ -117,6 +117,7 @@
 	rsVertexArray.cpp \
 	driver/rsdBcc.cpp \
 	driver/rsdCore.cpp \
+	driver/rsdGL.cpp \
 	driver/rsdProgramRaster.cpp \
 	driver/rsdProgramStore.cpp
 
diff --git a/libs/rs/driver/rsdCore.cpp b/libs/rs/driver/rsdCore.cpp
index 00d62ba..75f4d6b 100644
--- a/libs/rs/driver/rsdCore.cpp
+++ b/libs/rs/driver/rsdCore.cpp
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2009 The Android Open Source Project
+ * Copyright (C) 2011 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.
@@ -16,6 +16,7 @@
 
 #include "rsdCore.h"
 #include "rsdBcc.h"
+#include "rsdGL.h"
 #include "rsdProgramStore.h"
 #include "rsdProgramRaster.h"
 
@@ -37,6 +38,11 @@
 static void SetPriority(const Context *rsc, int32_t priority);
 
 static RsdHalFunctions FunctionTable = {
+    rsdGLInit,
+    rsdGLShutdown,
+    rsdGLSetSurface,
+    rsdGLSwap,
+
     Shutdown,
     NULL,
     SetPriority,
diff --git a/libs/rs/driver/rsdCore.h b/libs/rs/driver/rsdCore.h
index 02b2fbc..e37698b 100644
--- a/libs/rs/driver/rsdCore.h
+++ b/libs/rs/driver/rsdCore.h
@@ -23,6 +23,7 @@
 #include "rsMutex.h"
 #include "rsSignal.h"
 
+#include "rsdGL.h"
 
 typedef void (* InvokeFunc_t)(void);
 typedef void (*WorkerCallback_t)(void *usr, uint32_t idx);
@@ -45,6 +46,8 @@
     };
     Workers mWorkers;
     bool mExit;
+
+    RsdGL gl;
 } RsHal;
 
 
diff --git a/libs/rs/driver/rsdGL.cpp b/libs/rs/driver/rsdGL.cpp
new file mode 100644
index 0000000..86dfa0f
--- /dev/null
+++ b/libs/rs/driver/rsdGL.cpp
@@ -0,0 +1,333 @@
+/*
+ * Copyright (C) 2011 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 <ui/FramebufferNativeWindow.h>
+#include <ui/PixelFormat.h>
+#include <ui/EGLUtils.h>
+#include <ui/egl/android_natives.h>
+
+#include <sys/types.h>
+#include <sys/resource.h>
+#include <sched.h>
+
+#include <cutils/properties.h>
+
+#include <GLES/gl.h>
+#include <GLES/glext.h>
+#include <GLES2/gl2.h>
+#include <GLES2/gl2ext.h>
+
+//#include <cutils/sched_policy.h>
+//#include <sys/syscall.h>
+#include <string.h>
+
+
+#include "rsdCore.h"
+#include "rsdGL.h"
+
+#include <malloc.h>
+#include "rsContext.h"
+
+using namespace android;
+using namespace android::renderscript;
+
+static int32_t gGLContextCount = 0;
+
+static void checkEglError(const char* op, EGLBoolean returnVal = EGL_TRUE) {
+    if (returnVal != EGL_TRUE) {
+        fprintf(stderr, "%s() returned %d\n", op, returnVal);
+    }
+
+    for (EGLint error = eglGetError(); error != EGL_SUCCESS; error
+            = eglGetError()) {
+        fprintf(stderr, "after %s() eglError %s (0x%x)\n", op, EGLUtils::strerror(error),
+                error);
+    }
+}
+
+static void printEGLConfiguration(EGLDisplay dpy, EGLConfig config) {
+
+#define X(VAL) {VAL, #VAL}
+    struct {EGLint attribute; const char* name;} names[] = {
+    X(EGL_BUFFER_SIZE),
+    X(EGL_ALPHA_SIZE),
+    X(EGL_BLUE_SIZE),
+    X(EGL_GREEN_SIZE),
+    X(EGL_RED_SIZE),
+    X(EGL_DEPTH_SIZE),
+    X(EGL_STENCIL_SIZE),
+    X(EGL_CONFIG_CAVEAT),
+    X(EGL_CONFIG_ID),
+    X(EGL_LEVEL),
+    X(EGL_MAX_PBUFFER_HEIGHT),
+    X(EGL_MAX_PBUFFER_PIXELS),
+    X(EGL_MAX_PBUFFER_WIDTH),
+    X(EGL_NATIVE_RENDERABLE),
+    X(EGL_NATIVE_VISUAL_ID),
+    X(EGL_NATIVE_VISUAL_TYPE),
+    X(EGL_SAMPLES),
+    X(EGL_SAMPLE_BUFFERS),
+    X(EGL_SURFACE_TYPE),
+    X(EGL_TRANSPARENT_TYPE),
+    X(EGL_TRANSPARENT_RED_VALUE),
+    X(EGL_TRANSPARENT_GREEN_VALUE),
+    X(EGL_TRANSPARENT_BLUE_VALUE),
+    X(EGL_BIND_TO_TEXTURE_RGB),
+    X(EGL_BIND_TO_TEXTURE_RGBA),
+    X(EGL_MIN_SWAP_INTERVAL),
+    X(EGL_MAX_SWAP_INTERVAL),
+    X(EGL_LUMINANCE_SIZE),
+    X(EGL_ALPHA_MASK_SIZE),
+    X(EGL_COLOR_BUFFER_TYPE),
+    X(EGL_RENDERABLE_TYPE),
+    X(EGL_CONFORMANT),
+   };
+#undef X
+
+    for (size_t j = 0; j < sizeof(names) / sizeof(names[0]); j++) {
+        EGLint value = -1;
+        EGLint returnVal = eglGetConfigAttrib(dpy, config, names[j].attribute, &value);
+        EGLint error = eglGetError();
+        if (returnVal && error == EGL_SUCCESS) {
+            LOGV(" %s: %d (0x%x)", names[j].name, value, value);
+        }
+    }
+}
+
+static void DumpDebug(RsHal *dc) {
+    LOGE(" EGL ver %i %i", dc->gl.egl.majorVersion, dc->gl.egl.minorVersion);
+    LOGE(" EGL context %p  surface %p,  Display=%p", dc->gl.egl.context, dc->gl.egl.surface,
+         dc->gl.egl.display);
+    LOGE(" GL vendor: %s", dc->gl.gl.vendor);
+    LOGE(" GL renderer: %s", dc->gl.gl.renderer);
+    LOGE(" GL Version: %s", dc->gl.gl.version);
+    LOGE(" GL Extensions: %s", dc->gl.gl.extensions);
+    LOGE(" GL int Versions %i %i", dc->gl.gl.majorVersion, dc->gl.gl.minorVersion);
+
+    LOGV("MAX Textures %i, %i  %i", dc->gl.gl.maxVertexTextureUnits,
+         dc->gl.gl.maxFragmentTextureImageUnits, dc->gl.gl.maxTextureImageUnits);
+    LOGV("MAX Attribs %i", dc->gl.gl.maxVertexAttribs);
+    LOGV("MAX Uniforms %i, %i", dc->gl.gl.maxVertexUniformVectors,
+         dc->gl.gl.maxFragmentUniformVectors);
+    LOGV("MAX Varyings %i", dc->gl.gl.maxVaryingVectors);
+}
+
+void rsdGLShutdown(const Context *rsc) {
+    RsHal *dc = (RsHal *)rsc->mHal.drv;
+
+    LOGV("%p, deinitEGL", rsc);
+
+    if (dc->gl.egl.context != EGL_NO_CONTEXT) {
+        eglMakeCurrent(dc->gl.egl.display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
+        eglDestroySurface(dc->gl.egl.display, dc->gl.egl.surfaceDefault);
+        if (dc->gl.egl.surface != EGL_NO_SURFACE) {
+            eglDestroySurface(dc->gl.egl.display, dc->gl.egl.surface);
+        }
+        eglDestroyContext(dc->gl.egl.display, dc->gl.egl.context);
+        checkEglError("eglDestroyContext");
+    }
+
+    gGLContextCount--;
+    if (!gGLContextCount) {
+        eglTerminate(dc->gl.egl.display);
+    }
+}
+
+bool rsdGLInit(const Context *rsc) {
+    RsHal *dc = (RsHal *)rsc->mHal.drv;
+
+    dc->gl.egl.numConfigs = -1;
+    EGLint configAttribs[128];
+    EGLint *configAttribsPtr = configAttribs;
+    EGLint context_attribs2[] = { EGL_CONTEXT_CLIENT_VERSION, 2, EGL_NONE };
+
+    memset(configAttribs, 0, sizeof(configAttribs));
+
+    configAttribsPtr[0] = EGL_SURFACE_TYPE;
+    configAttribsPtr[1] = EGL_WINDOW_BIT;
+    configAttribsPtr += 2;
+
+    configAttribsPtr[0] = EGL_RENDERABLE_TYPE;
+    configAttribsPtr[1] = EGL_OPENGL_ES2_BIT;
+    configAttribsPtr += 2;
+
+    if (rsc->mUserSurfaceConfig.depthMin > 0) {
+        configAttribsPtr[0] = EGL_DEPTH_SIZE;
+        configAttribsPtr[1] = rsc->mUserSurfaceConfig.depthMin;
+        configAttribsPtr += 2;
+    }
+
+    if (rsc->mDev->mForceSW) {
+        configAttribsPtr[0] = EGL_CONFIG_CAVEAT;
+        configAttribsPtr[1] = EGL_SLOW_CONFIG;
+        configAttribsPtr += 2;
+    }
+
+    configAttribsPtr[0] = EGL_NONE;
+    rsAssert(configAttribsPtr < (configAttribs + (sizeof(configAttribs) / sizeof(EGLint))));
+
+    LOGV("%p initEGL start", rsc);
+    dc->gl.egl.display = eglGetDisplay(EGL_DEFAULT_DISPLAY);
+    checkEglError("eglGetDisplay");
+
+    eglInitialize(dc->gl.egl.display, &dc->gl.egl.majorVersion, &dc->gl.egl.minorVersion);
+    checkEglError("eglInitialize");
+
+    PixelFormat pf = PIXEL_FORMAT_RGBA_8888;
+    if (rsc->mUserSurfaceConfig.alphaMin == 0) {
+        pf = PIXEL_FORMAT_RGBX_8888;
+    }
+
+    status_t err = EGLUtils::selectConfigForPixelFormat(dc->gl.egl.display, configAttribs,
+                                                        pf, &dc->gl.egl.config);
+    if (err) {
+       LOGE("%p, couldn't find an EGLConfig matching the screen format\n", rsc);
+    }
+    //if (props.mLogVisual) {
+        printEGLConfiguration(dc->gl.egl.display, dc->gl.egl.config);
+    //}
+
+    dc->gl.egl.context = eglCreateContext(dc->gl.egl.display, dc->gl.egl.config,
+                                          EGL_NO_CONTEXT, context_attribs2);
+    checkEglError("eglCreateContext");
+    if (dc->gl.egl.context == EGL_NO_CONTEXT) {
+        LOGE("%p, eglCreateContext returned EGL_NO_CONTEXT", rsc);
+        return false;
+    }
+    gGLContextCount++;
+
+
+    EGLint pbuffer_attribs[] = { EGL_WIDTH, 1, EGL_HEIGHT, 1, EGL_NONE };
+    dc->gl.egl.surfaceDefault = eglCreatePbufferSurface(dc->gl.egl.display, dc->gl.egl.config,
+                                                        pbuffer_attribs);
+    checkEglError("eglCreatePbufferSurface");
+    if (dc->gl.egl.surfaceDefault == EGL_NO_SURFACE) {
+        LOGE("eglCreatePbufferSurface returned EGL_NO_SURFACE");
+        rsdGLShutdown(rsc);
+        return false;
+    }
+
+    EGLBoolean ret = eglMakeCurrent(dc->gl.egl.display, dc->gl.egl.surfaceDefault,
+                                    dc->gl.egl.surfaceDefault, dc->gl.egl.context);
+    if (ret == EGL_FALSE) {
+        LOGE("eglMakeCurrent returned EGL_FALSE");
+        checkEglError("eglMakeCurrent", ret);
+        rsdGLShutdown(rsc);
+        return false;
+    }
+
+    dc->gl.gl.version = glGetString(GL_VERSION);
+    dc->gl.gl.vendor = glGetString(GL_VENDOR);
+    dc->gl.gl.renderer = glGetString(GL_RENDERER);
+    dc->gl.gl.extensions = glGetString(GL_EXTENSIONS);
+
+    //LOGV("EGL Version %i %i", mEGL.mMajorVersion, mEGL.mMinorVersion);
+    //LOGV("GL Version %s", mGL.mVersion);
+    //LOGV("GL Vendor %s", mGL.mVendor);
+    //LOGV("GL Renderer %s", mGL.mRenderer);
+    //LOGV("GL Extensions %s", mGL.mExtensions);
+
+    const char *verptr = NULL;
+    if (strlen((const char *)dc->gl.gl.version) > 9) {
+        if (!memcmp(dc->gl.gl.version, "OpenGL ES-CM", 12)) {
+            verptr = (const char *)dc->gl.gl.version + 12;
+        }
+        if (!memcmp(dc->gl.gl.version, "OpenGL ES ", 10)) {
+            verptr = (const char *)dc->gl.gl.version + 9;
+        }
+    }
+
+    if (!verptr) {
+        LOGE("Error, OpenGL ES Lite not supported");
+        rsdGLShutdown(rsc);
+        return false;
+    } else {
+        sscanf(verptr, " %i.%i", &dc->gl.gl.majorVersion, &dc->gl.gl.minorVersion);
+    }
+
+    glGetIntegerv(GL_MAX_VERTEX_ATTRIBS, &dc->gl.gl.maxVertexAttribs);
+    glGetIntegerv(GL_MAX_VERTEX_UNIFORM_VECTORS, &dc->gl.gl.maxVertexUniformVectors);
+    glGetIntegerv(GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS, &dc->gl.gl.maxVertexTextureUnits);
+
+    glGetIntegerv(GL_MAX_VARYING_VECTORS, &dc->gl.gl.maxVaryingVectors);
+    glGetIntegerv(GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS, &dc->gl.gl.maxTextureImageUnits);
+
+    glGetIntegerv(GL_MAX_TEXTURE_IMAGE_UNITS, &dc->gl.gl.maxFragmentTextureImageUnits);
+    glGetIntegerv(GL_MAX_FRAGMENT_UNIFORM_VECTORS, &dc->gl.gl.maxFragmentUniformVectors);
+
+    dc->gl.gl.OES_texture_npot = NULL != strstr((const char *)dc->gl.gl.extensions,
+                                                "GL_OES_texture_npot");
+    dc->gl.gl.GL_IMG_texture_npot = NULL != strstr((const char *)dc->gl.gl.extensions,
+                                                   "GL_IMG_texture_npot");
+    dc->gl.gl.GL_NV_texture_npot_2D_mipmap = NULL != strstr((const char *)dc->gl.gl.extensions,
+                                                            "GL_NV_texture_npot_2D_mipmap");
+    dc->gl.gl.EXT_texture_max_aniso = 1.0f;
+    bool hasAniso = NULL != strstr((const char *)dc->gl.gl.extensions,
+                                   "GL_EXT_texture_filter_anisotropic");
+    if (hasAniso) {
+        glGetFloatv(GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT, &dc->gl.gl.EXT_texture_max_aniso);
+    }
+
+    DumpDebug(dc);
+
+    LOGV("initGLThread end %p", rsc);
+    return true;
+}
+
+
+bool rsdGLSetSurface(const Context *rsc, uint32_t w, uint32_t h, ANativeWindow *sur) {
+    RsHal *dc = (RsHal *)rsc->mHal.drv;
+
+    EGLBoolean ret;
+    // WAR: Some drivers fail to handle 0 size surfaces correcntly.
+    // Use the pbuffer to avoid this pitfall.
+    if ((dc->gl.egl.surface != NULL) || (w == 0) || (h == 0)) {
+        ret = eglMakeCurrent(dc->gl.egl.display, dc->gl.egl.surfaceDefault,
+                             dc->gl.egl.surfaceDefault, dc->gl.egl.context);
+        checkEglError("eglMakeCurrent", ret);
+
+        ret = eglDestroySurface(dc->gl.egl.display, dc->gl.egl.surface);
+        checkEglError("eglDestroySurface", ret);
+
+        dc->gl.egl.surface = NULL;
+        dc->gl.width = 1;
+        dc->gl.height = 1;
+    }
+
+    dc->gl.wndSurface = sur;
+    if (dc->gl.wndSurface != NULL) {
+        dc->gl.width = w;
+        dc->gl.height = h;
+
+        dc->gl.egl.surface = eglCreateWindowSurface(dc->gl.egl.display, dc->gl.egl.config,
+                                                    dc->gl.wndSurface, NULL);
+        checkEglError("eglCreateWindowSurface");
+        if (dc->gl.egl.surface == EGL_NO_SURFACE) {
+            LOGE("eglCreateWindowSurface returned EGL_NO_SURFACE");
+        }
+
+        ret = eglMakeCurrent(dc->gl.egl.display, dc->gl.egl.surface,
+                             dc->gl.egl.surface, dc->gl.egl.context);
+        checkEglError("eglMakeCurrent", ret);
+    }
+    return true;
+}
+
+void rsdGLSwap(const android::renderscript::Context *rsc) {
+    RsHal *dc = (RsHal *)rsc->mHal.drv;
+    eglSwapBuffers(dc->gl.egl.display, dc->gl.egl.surface);
+}
+
diff --git a/libs/rs/driver/rsdGL.h b/libs/rs/driver/rsdGL.h
new file mode 100644
index 0000000..246931f
--- /dev/null
+++ b/libs/rs/driver/rsdGL.h
@@ -0,0 +1,78 @@
+/*
+ * Copyright (C) 2011 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 RSD_GL_H
+#define RSD_GL_H
+
+#include <rs_hal.h>
+
+
+
+typedef void (* InvokeFunc_t)(void);
+typedef void (*WorkerCallback_t)(void *usr, uint32_t idx);
+
+typedef struct RsdGLRec {
+    struct {
+        EGLint numConfigs;
+        EGLint majorVersion;
+        EGLint minorVersion;
+        EGLConfig config;
+        EGLContext context;
+        EGLSurface surface;
+        EGLSurface surfaceDefault;
+        EGLDisplay display;
+    } egl;
+
+    struct {
+        const uint8_t * vendor;
+        const uint8_t * renderer;
+        const uint8_t * version;
+        const uint8_t * extensions;
+
+        uint32_t majorVersion;
+        uint32_t minorVersion;
+
+        int32_t maxVaryingVectors;
+        int32_t maxTextureImageUnits;
+
+        int32_t maxFragmentTextureImageUnits;
+        int32_t maxFragmentUniformVectors;
+
+        int32_t maxVertexAttribs;
+        int32_t maxVertexUniformVectors;
+        int32_t maxVertexTextureUnits;
+
+        bool OES_texture_npot;
+        bool GL_IMG_texture_npot;
+        bool GL_NV_texture_npot_2D_mipmap;
+        float EXT_texture_max_aniso;
+    } gl;
+
+    ANativeWindow *wndSurface;
+    uint32_t width;
+    uint32_t height;
+} RsdGL;
+
+
+
+bool rsdGLInit(const android::renderscript::Context *rsc);
+void rsdGLShutdown(const android::renderscript::Context *rsc);
+bool rsdGLSetSurface(const android::renderscript::Context *rsc,
+                     uint32_t w, uint32_t h, ANativeWindow *sur);
+void rsdGLSwap(const android::renderscript::Context *rsc);
+
+#endif
+
diff --git a/libs/rs/rsContext.cpp b/libs/rs/rsContext.cpp
index c9a7060..0f61789 100644
--- a/libs/rs/rsContext.cpp
+++ b/libs/rs/rsContext.cpp
@@ -19,7 +19,6 @@
 #include "rsThreadIO.h"
 #include <ui/FramebufferNativeWindow.h>
 #include <ui/PixelFormat.h>
-#include <ui/EGLUtils.h>
 #include <ui/egl/android_natives.h>
 
 #include <sys/types.h>
@@ -42,188 +41,22 @@
 
 pthread_key_t Context::gThreadTLSKey = 0;
 uint32_t Context::gThreadTLSKeyCount = 0;
-uint32_t Context::gGLContextCount = 0;
 pthread_mutex_t Context::gInitMutex = PTHREAD_MUTEX_INITIALIZER;
 pthread_mutex_t Context::gLibMutex = PTHREAD_MUTEX_INITIALIZER;
 
-static void checkEglError(const char* op, EGLBoolean returnVal = EGL_TRUE) {
-    if (returnVal != EGL_TRUE) {
-        fprintf(stderr, "%s() returned %d\n", op, returnVal);
-    }
-
-    for (EGLint error = eglGetError(); error != EGL_SUCCESS; error
-            = eglGetError()) {
-        fprintf(stderr, "after %s() eglError %s (0x%x)\n", op, EGLUtils::strerror(error),
-                error);
-    }
-}
-
-void printEGLConfiguration(EGLDisplay dpy, EGLConfig config) {
-
-#define X(VAL) {VAL, #VAL}
-    struct {EGLint attribute; const char* name;} names[] = {
-    X(EGL_BUFFER_SIZE),
-    X(EGL_ALPHA_SIZE),
-    X(EGL_BLUE_SIZE),
-    X(EGL_GREEN_SIZE),
-    X(EGL_RED_SIZE),
-    X(EGL_DEPTH_SIZE),
-    X(EGL_STENCIL_SIZE),
-    X(EGL_CONFIG_CAVEAT),
-    X(EGL_CONFIG_ID),
-    X(EGL_LEVEL),
-    X(EGL_MAX_PBUFFER_HEIGHT),
-    X(EGL_MAX_PBUFFER_PIXELS),
-    X(EGL_MAX_PBUFFER_WIDTH),
-    X(EGL_NATIVE_RENDERABLE),
-    X(EGL_NATIVE_VISUAL_ID),
-    X(EGL_NATIVE_VISUAL_TYPE),
-    X(EGL_SAMPLES),
-    X(EGL_SAMPLE_BUFFERS),
-    X(EGL_SURFACE_TYPE),
-    X(EGL_TRANSPARENT_TYPE),
-    X(EGL_TRANSPARENT_RED_VALUE),
-    X(EGL_TRANSPARENT_GREEN_VALUE),
-    X(EGL_TRANSPARENT_BLUE_VALUE),
-    X(EGL_BIND_TO_TEXTURE_RGB),
-    X(EGL_BIND_TO_TEXTURE_RGBA),
-    X(EGL_MIN_SWAP_INTERVAL),
-    X(EGL_MAX_SWAP_INTERVAL),
-    X(EGL_LUMINANCE_SIZE),
-    X(EGL_ALPHA_MASK_SIZE),
-    X(EGL_COLOR_BUFFER_TYPE),
-    X(EGL_RENDERABLE_TYPE),
-    X(EGL_CONFORMANT),
-   };
-#undef X
-
-    for (size_t j = 0; j < sizeof(names) / sizeof(names[0]); j++) {
-        EGLint value = -1;
-        EGLint returnVal = eglGetConfigAttrib(dpy, config, names[j].attribute, &value);
-        EGLint error = eglGetError();
-        if (returnVal && error == EGL_SUCCESS) {
-            LOGV(" %s: %d (0x%x)", names[j].name, value, value);
-        }
-    }
-}
 
 
 bool Context::initGLThread() {
     pthread_mutex_lock(&gInitMutex);
     LOGV("initGLThread start %p", this);
 
-    mEGL.mNumConfigs = -1;
-    EGLint configAttribs[128];
-    EGLint *configAttribsPtr = configAttribs;
-    EGLint context_attribs2[] = { EGL_CONTEXT_CLIENT_VERSION, 2, EGL_NONE };
-
-    memset(configAttribs, 0, sizeof(configAttribs));
-
-    configAttribsPtr[0] = EGL_SURFACE_TYPE;
-    configAttribsPtr[1] = EGL_WINDOW_BIT;
-    configAttribsPtr += 2;
-
-    configAttribsPtr[0] = EGL_RENDERABLE_TYPE;
-    configAttribsPtr[1] = EGL_OPENGL_ES2_BIT;
-    configAttribsPtr += 2;
-
-    if (mUserSurfaceConfig.depthMin > 0) {
-        configAttribsPtr[0] = EGL_DEPTH_SIZE;
-        configAttribsPtr[1] = mUserSurfaceConfig.depthMin;
-        configAttribsPtr += 2;
-    }
-
-    if (mDev->mForceSW) {
-        configAttribsPtr[0] = EGL_CONFIG_CAVEAT;
-        configAttribsPtr[1] = EGL_SLOW_CONFIG;
-        configAttribsPtr += 2;
-    }
-
-    configAttribsPtr[0] = EGL_NONE;
-    rsAssert(configAttribsPtr < (configAttribs + (sizeof(configAttribs) / sizeof(EGLint))));
-
-    LOGV("%p initEGL start", this);
-    mEGL.mDisplay = eglGetDisplay(EGL_DEFAULT_DISPLAY);
-    checkEglError("eglGetDisplay");
-
-    eglInitialize(mEGL.mDisplay, &mEGL.mMajorVersion, &mEGL.mMinorVersion);
-    checkEglError("eglInitialize");
-
-#if 1
-    PixelFormat pf = PIXEL_FORMAT_RGBA_8888;
-    if (mUserSurfaceConfig.alphaMin == 0) {
-        pf = PIXEL_FORMAT_RGBX_8888;
-    }
-
-    status_t err = EGLUtils::selectConfigForPixelFormat(mEGL.mDisplay, configAttribs, pf, &mEGL.mConfig);
-    if (err) {
-       LOGE("%p, couldn't find an EGLConfig matching the screen format\n", this);
-    }
-    if (props.mLogVisual) {
-        printEGLConfiguration(mEGL.mDisplay, mEGL.mConfig);
-    }
-#else
-    eglChooseConfig(mEGL.mDisplay, configAttribs, &mEGL.mConfig, 1, &mEGL.mNumConfigs);
-#endif
-
-    mEGL.mContext = eglCreateContext(mEGL.mDisplay, mEGL.mConfig, EGL_NO_CONTEXT, context_attribs2);
-    checkEglError("eglCreateContext");
-    if (mEGL.mContext == EGL_NO_CONTEXT) {
+    if (!mHal.funcs.initGraphics(this)) {
         pthread_mutex_unlock(&gInitMutex);
-        LOGE("%p, eglCreateContext returned EGL_NO_CONTEXT", this);
-        return false;
-    }
-    gGLContextCount++;
-
-
-    EGLint pbuffer_attribs[] = { EGL_WIDTH, 1, EGL_HEIGHT, 1, EGL_NONE };
-    mEGL.mSurfaceDefault = eglCreatePbufferSurface(mEGL.mDisplay, mEGL.mConfig, pbuffer_attribs);
-    checkEglError("eglCreatePbufferSurface");
-    if (mEGL.mSurfaceDefault == EGL_NO_SURFACE) {
-        LOGE("eglCreatePbufferSurface returned EGL_NO_SURFACE");
-        pthread_mutex_unlock(&gInitMutex);
-        deinitEGL();
+        LOGE("%p, initGraphics failed", this);
         return false;
     }
 
-    EGLBoolean ret = eglMakeCurrent(mEGL.mDisplay, mEGL.mSurfaceDefault, mEGL.mSurfaceDefault, mEGL.mContext);
-    if (ret == EGL_FALSE) {
-        LOGE("eglMakeCurrent returned EGL_FALSE");
-        checkEglError("eglMakeCurrent", ret);
-        pthread_mutex_unlock(&gInitMutex);
-        deinitEGL();
-        return false;
-    }
-
-    mGL.mVersion = glGetString(GL_VERSION);
-    mGL.mVendor = glGetString(GL_VENDOR);
-    mGL.mRenderer = glGetString(GL_RENDERER);
-    mGL.mExtensions = glGetString(GL_EXTENSIONS);
-
-    //LOGV("EGL Version %i %i", mEGL.mMajorVersion, mEGL.mMinorVersion);
-    //LOGV("GL Version %s", mGL.mVersion);
-    //LOGV("GL Vendor %s", mGL.mVendor);
-    //LOGV("GL Renderer %s", mGL.mRenderer);
-    //LOGV("GL Extensions %s", mGL.mExtensions);
-
-    const char *verptr = NULL;
-    if (strlen((const char *)mGL.mVersion) > 9) {
-        if (!memcmp(mGL.mVersion, "OpenGL ES-CM", 12)) {
-            verptr = (const char *)mGL.mVersion + 12;
-        }
-        if (!memcmp(mGL.mVersion, "OpenGL ES ", 10)) {
-            verptr = (const char *)mGL.mVersion + 9;
-        }
-    }
-
-    if (!verptr) {
-        LOGE("Error, OpenGL ES Lite not supported");
-        pthread_mutex_unlock(&gInitMutex);
-        deinitEGL();
-        return false;
-    } else {
-        sscanf(verptr, " %i.%i", &mGL.mMajorVersion, &mGL.mMinorVersion);
-    }
+    const char * ext = (const char *)glGetString(GL_EXTENSIONS);
 
     glGetIntegerv(GL_MAX_VERTEX_ATTRIBS, &mGL.mMaxVertexAttribs);
     glGetIntegerv(GL_MAX_VERTEX_UNIFORM_VECTORS, &mGL.mMaxVertexUniformVectors);
@@ -235,11 +68,11 @@
     glGetIntegerv(GL_MAX_TEXTURE_IMAGE_UNITS, &mGL.mMaxFragmentTextureImageUnits);
     glGetIntegerv(GL_MAX_FRAGMENT_UNIFORM_VECTORS, &mGL.mMaxFragmentUniformVectors);
 
-    mGL.OES_texture_npot = NULL != strstr((const char *)mGL.mExtensions, "GL_OES_texture_npot");
-    mGL.GL_IMG_texture_npot = NULL != strstr((const char *)mGL.mExtensions, "GL_IMG_texture_npot");
-    mGL.GL_NV_texture_npot_2D_mipmap = NULL != strstr((const char *)mGL.mExtensions, "GL_NV_texture_npot_2D_mipmap");
+    mGL.OES_texture_npot = NULL != strstr(ext, "GL_OES_texture_npot");
+    mGL.GL_IMG_texture_npot = NULL != strstr(ext, "GL_IMG_texture_npot");
+    mGL.GL_NV_texture_npot_2D_mipmap = NULL != strstr(ext, "GL_NV_texture_npot_2D_mipmap");
     mGL.EXT_texture_max_aniso = 1.0f;
-    bool hasAniso = NULL != strstr((const char *)mGL.mExtensions, "GL_EXT_texture_filter_anisotropic");
+    bool hasAniso = NULL != strstr(ext, "GL_EXT_texture_filter_anisotropic");
     if (hasAniso) {
         glGetFloatv(GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT, &mGL.EXT_texture_max_aniso);
     }
@@ -251,21 +84,7 @@
 
 void Context::deinitEGL() {
     LOGV("%p, deinitEGL", this);
-
-    if (mEGL.mContext != EGL_NO_CONTEXT) {
-        eglMakeCurrent(mEGL.mDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
-        eglDestroySurface(mEGL.mDisplay, mEGL.mSurfaceDefault);
-        if (mEGL.mSurface != EGL_NO_SURFACE) {
-            eglDestroySurface(mEGL.mDisplay, mEGL.mSurface);
-        }
-        eglDestroyContext(mEGL.mDisplay, mEGL.mContext);
-        checkEglError("eglDestroyContext");
-    }
-
-    gGLContextCount--;
-    if (!gGLContextCount) {
-        eglTerminate(mEGL.mDisplay);
-    }
+    mHal.funcs.shutdownGraphics(this);
 }
 
 Context::PushState::PushState(Context *con) {
@@ -507,7 +326,7 @@
 
              mDraw = targetTime && !rsc->mPaused;
              rsc->timerSet(RS_TIMER_CLEAR_SWAP);
-             eglSwapBuffers(rsc->mEGL.mDisplay, rsc->mEGL.mSurface);
+             rsc->mHal.funcs.swap(rsc);
              rsc->timerFrame();
              rsc->timerSet(RS_TIMER_INTERNAL);
              rsc->timerPrint();
@@ -604,7 +423,6 @@
         memset(&mUserSurfaceConfig, 0, sizeof(mUserSurfaceConfig));
     }
 
-    memset(&mEGL, 0, sizeof(mEGL));
     memset(&mGL, 0, sizeof(mGL));
     mIsGraphicsContext = sc != NULL;
 
@@ -693,36 +511,13 @@
 
 void Context::setSurface(uint32_t w, uint32_t h, ANativeWindow *sur) {
     rsAssert(mIsGraphicsContext);
-
-    EGLBoolean ret;
-    // WAR: Some drivers fail to handle 0 size surfaces correcntly.
-    // Use the pbuffer to avoid this pitfall.
-    if ((mEGL.mSurface != NULL) || (w == 0) || (h == 0)) {
-        ret = eglMakeCurrent(mEGL.mDisplay, mEGL.mSurfaceDefault, mEGL.mSurfaceDefault, mEGL.mContext);
-        checkEglError("eglMakeCurrent", ret);
-
-        ret = eglDestroySurface(mEGL.mDisplay, mEGL.mSurface);
-        checkEglError("eglDestroySurface", ret);
-
-        mEGL.mSurface = NULL;
-        mWidth = 1;
-        mHeight = 1;
-    }
+    mHal.funcs.setSurface(this, w, h, sur);
 
     mWndSurface = sur;
-    if (mWndSurface != NULL) {
-        mWidth = w;
-        mHeight = h;
+    mWidth = w;
+    mHeight = h;
 
-        mEGL.mSurface = eglCreateWindowSurface(mEGL.mDisplay, mEGL.mConfig, mWndSurface, NULL);
-        checkEglError("eglCreateWindowSurface");
-        if (mEGL.mSurface == EGL_NO_SURFACE) {
-            LOGE("eglCreateWindowSurface returned EGL_NO_SURFACE");
-        }
-
-        ret = eglMakeCurrent(mEGL.mDisplay, mEGL.mSurface, mEGL.mSurface, mEGL.mContext);
-        checkEglError("eglMakeCurrent", ret);
-
+    if (mWidth && mHeight) {
         mStateVertex.updateSize(this);
     }
 }
@@ -887,21 +682,9 @@
     LOGE("RS Context debug %p", this);
     LOGE("RS Context debug");
 
-    LOGE(" EGL ver %i %i", mEGL.mMajorVersion, mEGL.mMinorVersion);
-    LOGE(" EGL context %p  surface %p,  Display=%p", mEGL.mContext, mEGL.mSurface, mEGL.mDisplay);
-    LOGE(" GL vendor: %s", mGL.mVendor);
-    LOGE(" GL renderer: %s", mGL.mRenderer);
-    LOGE(" GL Version: %s", mGL.mVersion);
-    LOGE(" GL Extensions: %s", mGL.mExtensions);
-    LOGE(" GL int Versions %i %i", mGL.mMajorVersion, mGL.mMinorVersion);
     LOGE(" RS width %i, height %i", mWidth, mHeight);
     LOGE(" RS running %i, exit %i, paused %i", mRunning, mExit, mPaused);
     LOGE(" RS pThreadID %li, nativeThreadID %i", mThreadId, mNativeThreadId);
-
-    LOGV("MAX Textures %i, %i  %i", mGL.mMaxVertexTextureUnits, mGL.mMaxFragmentTextureImageUnits, mGL.mMaxTextureImageUnits);
-    LOGV("MAX Attribs %i", mGL.mMaxVertexAttribs);
-    LOGV("MAX Uniforms %i, %i", mGL.mMaxVertexUniformVectors, mGL.mMaxFragmentUniformVectors);
-    LOGV("MAX Varyings %i", mGL.mMaxVaryingVectors);
 }
 
 ///////////////////////////////////////////////////////////////////////////////////////////
diff --git a/libs/rs/rsContext.h b/libs/rs/rsContext.h
index eacfdf7..4dd186c 100644
--- a/libs/rs/rsContext.h
+++ b/libs/rs/rsContext.h
@@ -222,29 +222,10 @@
     uint32_t getDPI() const {return mDPI;}
     void setDPI(uint32_t dpi) {mDPI = dpi;}
 
-protected:
     Device *mDev;
+protected:
 
     struct {
-        EGLint mNumConfigs;
-        EGLint mMajorVersion;
-        EGLint mMinorVersion;
-        EGLConfig mConfig;
-        EGLContext mContext;
-        EGLSurface mSurface;
-        EGLSurface mSurfaceDefault;
-        EGLDisplay mDisplay;
-    } mEGL;
-
-    struct {
-        const uint8_t * mVendor;
-        const uint8_t * mRenderer;
-        const uint8_t * mVersion;
-        const uint8_t * mExtensions;
-
-        uint32_t mMajorVersion;
-        uint32_t mMinorVersion;
-
         int32_t mMaxVaryingVectors;
         int32_t mMaxTextureImageUnits;
 
diff --git a/libs/rs/rs_hal.h b/libs/rs/rs_hal.h
index 93d7476..a4ca936 100644
--- a/libs/rs/rs_hal.h
+++ b/libs/rs/rs_hal.h
@@ -18,6 +18,7 @@
 #define RS_HAL_H
 
 #include <RenderScriptDefines.h>
+#include <ui/egl/android_natives.h>
 
 namespace android {
 namespace renderscript {
@@ -44,6 +45,11 @@
  * Script management functions
  */
 typedef struct {
+    bool (*initGraphics)(const Context *);
+    void (*shutdownGraphics)(const Context *);
+    bool (*setSurface)(const Context *, uint32_t w, uint32_t h, ANativeWindow *);
+    void (*swap)(const Context *);
+
     void (*shutdownDriver)(Context *);
     void (*getVersion)(unsigned int *major, unsigned int *minor);
     void (*setPriority)(const Context *, int32_t priority);
@@ -87,7 +93,6 @@
         void (*destroy)(const Context *rsc, Script *s);
     } script;
 
-
     struct {
         bool (*init)(const Context *rsc, const ProgramStore *ps);
         void (*setActive)(const Context *rsc, const ProgramStore *ps);