Merge change 22399 into eclair

* changes:
  Refactor VCard handling code, phase 2, 3, 4, 5
diff --git a/include/private/opengles/gl_context.h b/include/private/opengles/gl_context.h
index 523aed0..67c2dd8 100644
--- a/include/private/opengles/gl_context.h
+++ b/include/private/opengles/gl_context.h
@@ -287,6 +287,7 @@
     vec4_t      normalizedObjPosition;
     vec4_t      spotDir;
     vec4_t      normalizedSpotDir;
+    vec4_t      objViewer;
     GLfixed     spotExp;
     GLfixed     spotCutoff;
     GLfixed     spotCutoffCosine;
diff --git a/opengl/libagl/light.cpp b/opengl/libagl/light.cpp
index 8ae32cc..f211bca 100644
--- a/opengl/libagl/light.cpp
+++ b/opengl/libagl/light.cpp
@@ -216,6 +216,8 @@
 static inline void validate_light_mvi(ogles_context_t* c)
 {
     uint32_t en = c->lighting.enabledLights;
+    // Vector from object to viewer, in eye coordinates
+    const vec4_t eyeViewer = { 0, 0, 0x1000, 0 };
     while (en) {
         const int i = 31 - gglClz(en);
         en &= ~(1<<i);
@@ -223,6 +225,9 @@
         c->transforms.mvui.point4(&c->transforms.mvui,
                 &l.objPosition, &l.position);
         vnorm3(l.normalizedObjPosition.v, l.objPosition.v);
+        c->transforms.mvui.point4(&c->transforms.mvui,
+                &l.objViewer, &eyeViewer);
+        vnorm3(l.objViewer.v, l.objViewer.v);
     }
 }
 
@@ -379,9 +384,9 @@
             // specular
             if (ggl_unlikely(s && l.implicitSpecular.v[3])) {
                 vec4_t h;
-                h.x = d.x;
-                h.y = d.y;
-                h.z = d.z + 0x10000;
+                h.x = d.x + l.objViewer.x;
+                h.y = d.y + l.objViewer.y;
+                h.z = d.z + l.objViewer.z;
                 vnorm3(h.v, h.v);
                 s = dot3(n.v, h.v);
                 s = (s<0) ? (twoSide?(-s):0) : s;
diff --git a/opengl/libagl/matrix.cpp b/opengl/libagl/matrix.cpp
index 0b68dc0..21ef50e 100644
--- a/opengl/libagl/matrix.cpp
+++ b/opengl/libagl/matrix.cpp
@@ -696,6 +696,8 @@
     f[2] = 0;   f[6] = 0;   f[10] = A;  f[14] = B;
     f[3] = 0;   f[7] = 0;   f[11] = 0;  f[15] = 1;
     c->transforms.dirty |= transform_state_t::VIEWPORT;
+    if (c->transforms.mvp4.flags & transform_t::FLAGS_2D_PROJECTION)
+        c->transforms.dirty |= transform_state_t::MVP;
 }
 
 // ----------------------------------------------------------------------------
diff --git a/opengl/libs/Android.mk b/opengl/libs/Android.mk
index e1fd48b..9578452 100644
--- a/opengl/libs/Android.mk
+++ b/opengl/libs/Android.mk
@@ -28,6 +28,10 @@
 LOCAL_CFLAGS += -DGL_GLEXT_PROTOTYPES -DEGL_EGLEXT_PROTOTYPES
 LOCAL_CFLAGS += -fvisibility=hidden
 
+ifeq ($(TARGET_BOARD_PLATFORM),msm7k)
+LOCAL_CFLAGS += -DADRENO130=1
+endif
+
 include $(BUILD_SHARED_LIBRARY)
 installed_libEGL := $(LOCAL_INSTALLED_MODULE)
 
diff --git a/opengl/libs/EGL/egl.cpp b/opengl/libs/EGL/egl.cpp
index 03e764c..d1ddcd3 100644
--- a/opengl/libs/EGL/egl.cpp
+++ b/opengl/libs/EGL/egl.cpp
@@ -36,6 +36,8 @@
 #include <cutils/properties.h>
 #include <cutils/memory.h>
 
+#include <utils/SortedVector.h>
+
 #include "hooks.h"
 #include "egl_impl.h"
 #include "Loader.h"
@@ -63,40 +65,122 @@
 
 // ----------------------------------------------------------------------------
 
-template <int MAGIC>
-struct egl_object_t
-{
-    egl_object_t() : magic(MAGIC) { }
-    ~egl_object_t() { magic = 0; }
-    bool isValid() const { return magic == MAGIC; }
+class egl_object_t {
+    static SortedVector<egl_object_t*> sObjects;
+    static Mutex sLock;
+
+            volatile int32_t  terminated;
+    mutable volatile int32_t  count;
+
+public:
+    egl_object_t() : terminated(0), count(1) { 
+        Mutex::Autolock _l(sLock);
+        sObjects.add(this);
+    }
+
+    inline bool isAlive() const { return !terminated; }
+
 private:
-    uint32_t    magic;
+    bool get() {
+        Mutex::Autolock _l(sLock);
+        if (egl_object_t::sObjects.indexOf(this) >= 0) {
+            android_atomic_inc(&count);
+            return true;
+        }
+        return false;
+    }
+
+    bool put() {
+        Mutex::Autolock _l(sLock);
+        if (android_atomic_dec(&count) == 1) {
+            sObjects.remove(this);
+            return true;
+        }
+        return false;
+    }    
+
+public:
+    template <typename N, typename T>
+    struct LocalRef {
+        N* ref;
+        LocalRef(T o) : ref(0) {
+            N* native = reinterpret_cast<N*>(o);
+            if (o && native->get()) {
+                ref = native;
+            }
+        }
+        ~LocalRef() { 
+            if (ref && ref->put()) {
+                delete ref;
+            }
+        }
+        inline N* get() {
+            return ref;
+        }
+        void acquire() const {
+            if (ref) {
+                android_atomic_inc(&ref->count);
+            }
+        }
+        void release() const {
+            if (ref) {
+                int32_t c = android_atomic_dec(&ref->count);
+                // ref->count cannot be 1 prior atomic_dec because we have
+                // a reference, and if we have one, it means there was
+                // already one before us.
+                LOGE_IF(c==1, "refcount is now 0 in release()");
+            }
+        }
+        void terminate() {
+            if (ref) {
+                ref->terminated = 1;
+                release();
+            }
+        }
+    };
 };
 
-struct egl_display_t : public egl_object_t<'_dpy'>
-{
-    EGLDisplay  dpys[IMPL_NUM_DRIVERS_IMPLEMENTATIONS];
-    EGLConfig*  configs[IMPL_NUM_DRIVERS_IMPLEMENTATIONS];
-    EGLint      numConfigs[IMPL_NUM_DRIVERS_IMPLEMENTATIONS];
-    EGLint      numTotalConfigs;
-    char const* extensionsString;
-    volatile int32_t refs;
+SortedVector<egl_object_t*> egl_object_t::sObjects;
+Mutex egl_object_t::sLock;
+
+struct egl_display_t {
+    enum { NOT_INITIALIZED, INITIALIZED, TERMINATED };
+    
     struct strings_t {
         char const * vendor;
         char const * version;
         char const * clientApi;
         char const * extensions;
     };
-    strings_t   queryString[IMPL_NUM_DRIVERS_IMPLEMENTATIONS];
+
+    struct DisplayImpl {
+        DisplayImpl() : dpy(EGL_NO_DISPLAY), config(0),
+                        state(NOT_INITIALIZED), numConfigs(0) { }
+        EGLDisplay  dpy;
+        EGLConfig*  config;
+        EGLint      state;
+        EGLint      numConfigs;
+        strings_t   queryString;
+    };
+
+    uint32_t    magic;
+    DisplayImpl disp[IMPL_NUM_DRIVERS_IMPLEMENTATIONS];
+    EGLint      numTotalConfigs;
+    volatile int32_t refs;
+    
+    egl_display_t() : magic('_dpy'), numTotalConfigs(0) { }
+    ~egl_display_t() { magic = 0; }
+    inline bool isValid() const { return magic == '_dpy'; }
+    inline bool isAlive() const { return isValid(); }
 };
 
-struct egl_surface_t : public egl_object_t<'_srf'>
+struct egl_surface_t : public egl_object_t
 {
+    typedef egl_object_t::LocalRef<egl_surface_t, EGLSurface> Ref;
+
     egl_surface_t(EGLDisplay dpy, EGLSurface surface,
             int impl, egl_connection_t const* cnx) 
-    : dpy(dpy), surface(surface), impl(impl), cnx(cnx)
-    {
-        // NOTE: window must be incRef'ed and connected already
+    : dpy(dpy), surface(surface), impl(impl), cnx(cnx) {
     }
     ~egl_surface_t() {
     }
@@ -106,8 +190,10 @@
     egl_connection_t const*     cnx;
 };
 
-struct egl_context_t : public egl_object_t<'_ctx'>
+struct egl_context_t : public egl_object_t
 {
+    typedef egl_object_t::LocalRef<egl_context_t, EGLContext> Ref;
+    
     egl_context_t(EGLDisplay dpy, EGLContext context,
             int impl, egl_connection_t const* cnx) 
     : dpy(dpy), context(context), read(0), draw(0), impl(impl), cnx(cnx)
@@ -121,8 +207,10 @@
     egl_connection_t const*     cnx;
 };
 
-struct egl_image_t : public egl_object_t<'_img'>
+struct egl_image_t : public egl_object_t
 {
+    typedef egl_object_t::LocalRef<egl_image_t, EGLImageKHR> Ref;
+
     egl_image_t(EGLDisplay dpy, EGLContext context)
         : dpy(dpy), context(context)
     {
@@ -133,6 +221,10 @@
     EGLImageKHR images[IMPL_NUM_DRIVERS_IMPLEMENTATIONS];
 };
 
+typedef egl_surface_t::Ref  SurfaceRef;
+typedef egl_context_t::Ref  ContextRef;
+typedef egl_image_t::Ref    ImageRef;
+
 struct tls_t
 {
     tls_t() : error(EGL_SUCCESS), ctx(0), logCallWithNoContext(EGL_TRUE) { }
@@ -272,14 +364,14 @@
 static EGLint configToUniqueId(egl_display_t const* dp, int i, int index) 
 {
     // NOTE: this mapping works only if we have no more than two EGLimpl
-    return (i>0 ? dp->numConfigs[0] : 0) + index;
+    return (i>0 ? dp->disp[0].numConfigs : 0) + index;
 }
 
 static void uniqueIdToConfig(egl_display_t const* dp, EGLint configId,
         int& i, int& index) 
 {
     // NOTE: this mapping works only if we have no more than two EGLimpl
-    size_t numConfigs = dp->numConfigs[0];
+    size_t numConfigs = dp->disp[0].numConfigs;
     i = configId / numConfigs;
     index = configId % numConfigs;
 }
@@ -391,7 +483,7 @@
         return setError(EGL_BAD_CONFIG, (egl_connection_t*)NULL);
     } 
     index = uintptr_t(config) & 0xFFFFFF;
-    if (index >= dp->numConfigs[impl]) {
+    if (index >= dp->disp[impl].numConfigs) {
         return setError(EGL_BAD_CONFIG, (egl_connection_t*)NULL);
     }
     egl_connection_t* const cnx = &gEGLImpl[impl];
@@ -405,11 +497,9 @@
 {
     if ((uintptr_t(dpy)-1U) >= NUM_DISPLAYS)
         return setError(EGL_BAD_DISPLAY, EGL_FALSE);
-    if (!get_display(dpy)->isValid())
+    if (!get_display(dpy)->isAlive())
         return setError(EGL_BAD_DISPLAY, EGL_FALSE);
-    if (!ctx) // TODO: make sure context is a valid object
-        return setError(EGL_BAD_CONTEXT, EGL_FALSE);
-    if (!get_context(ctx)->isValid())
+    if (!get_context(ctx)->isAlive())
         return setError(EGL_BAD_CONTEXT, EGL_FALSE);
     return EGL_TRUE;
 }
@@ -418,37 +508,34 @@
 {
     if ((uintptr_t(dpy)-1U) >= NUM_DISPLAYS)
         return setError(EGL_BAD_DISPLAY, EGL_FALSE);
-    if (!get_display(dpy)->isValid())
+    if (!get_display(dpy)->isAlive())
         return setError(EGL_BAD_DISPLAY, EGL_FALSE);
-    if (!surface) // TODO: make sure surface is a valid object
-        return setError(EGL_BAD_SURFACE, EGL_FALSE);
-    if (!get_surface(surface)->isValid())
+    if (!get_surface(surface)->isAlive())
         return setError(EGL_BAD_SURFACE, EGL_FALSE);
     return EGL_TRUE;
 }
 
-
 EGLImageKHR egl_get_image_for_current_context(EGLImageKHR image)
 {
+    ImageRef _i(image);
+    if (!_i.get()) return EGL_NO_IMAGE_KHR;
+    
     EGLContext context = getContext();
     if (context == EGL_NO_CONTEXT || image == EGL_NO_IMAGE_KHR)
         return EGL_NO_IMAGE_KHR;
     
     egl_context_t const * const c = get_context(context);
-    if (!c->isValid())
+    if (!c->isAlive())
         return EGL_NO_IMAGE_KHR;
 
     egl_image_t const * const i = get_image(image);
-    if (!i->isValid())
-        return EGL_NO_IMAGE_KHR;
-
     return i->images[c->impl];
 }
 
 // ----------------------------------------------------------------------------
 
 // this mutex protects:
-//    d->dpys[]
+//    d->disp[]
 //    egl_init_drivers_locked()
 //
 static pthread_mutex_t gInitDriverMutex = PTHREAD_MUTEX_INITIALIZER;
@@ -477,7 +564,7 @@
         if (cnx->dso) {
             EGLDisplay dpy = cnx->hooks->egl.eglGetDisplay(EGL_DEFAULT_DISPLAY);
             LOGE_IF(dpy==EGL_NO_DISPLAY, "No EGLDisplay for software EGL!");
-            d->dpys[IMPL_SOFTWARE] = dpy; 
+            d->disp[IMPL_SOFTWARE].dpy = dpy; 
             if (dpy == EGL_NO_DISPLAY) {
                 loader.close(cnx->dso);
                 cnx->dso = NULL;
@@ -495,7 +582,7 @@
             if (cnx->dso) {
                 EGLDisplay dpy = cnx->hooks->egl.eglGetDisplay(EGL_DEFAULT_DISPLAY);
                 LOGE_IF(dpy==EGL_NO_DISPLAY, "No EGLDisplay for hardware EGL!");
-                d->dpys[IMPL_HARDWARE] = dpy; 
+                d->disp[IMPL_HARDWARE].dpy = dpy; 
                 if (dpy == EGL_NO_DISPLAY) {
                     loader.close(cnx->dso);
                     cnx->dso = NULL;
@@ -505,7 +592,7 @@
             LOGD("3D hardware acceleration is disabled");
         }
     }
-    
+
     if (!gEGLImpl[IMPL_SOFTWARE].dso && !gEGLImpl[IMPL_HARDWARE].dso) {
         return EGL_FALSE;
     }
@@ -563,7 +650,6 @@
     // initialize each EGL and
     // build our own extension string first, based on the extension we know
     // and the extension supported by our client implementation
-    dp->extensionsString = strdup(gExtensionString);
     for (int i=0 ; i<IMPL_NUM_DRIVERS_IMPLEMENTATIONS ; i++) {
         egl_connection_t* const cnx = &gEGLImpl[i];
         cnx->major = -1;
@@ -571,25 +657,43 @@
         if (!cnx->dso) 
             continue;
 
-        if (cnx->hooks->egl.eglInitialize(
-                dp->dpys[i], &cnx->major, &cnx->minor)) {
+#if defined(ADRENO130)
+#warning "Adreno-130 eglInitialize() workaround"
+        /*
+         * The ADRENO 130 driver returns a different EGLDisplay each time
+         * eglGetDisplay() is called, but also makes the EGLDisplay invalid
+         * after eglTerminate() has been called, so that eglInitialize() 
+         * cannot be called again. Therefore, we need to make sure to call
+         * eglGetDisplay() before calling eglInitialize();
+         */
+        if (i == IMPL_HARDWARE) {
+            dp->disp[i].dpy =
+                cnx->hooks->egl.eglGetDisplay(EGL_DEFAULT_DISPLAY);
+        }
+#endif
 
+
+        EGLDisplay idpy = dp->disp[i].dpy;
+        if (cnx->hooks->egl.eglInitialize(idpy, &cnx->major, &cnx->minor)) {
             //LOGD("initialized %d dpy=%p, ver=%d.%d, cnx=%p",
-            //        i, dp->dpys[i], cnx->major, cnx->minor, cnx);
+            //        i, idpy, cnx->major, cnx->minor, cnx);
+
+            // display is now initialized
+            dp->disp[i].state = egl_display_t::INITIALIZED;
 
             // get the query-strings for this display for each implementation
-            dp->queryString[i].vendor =
-                cnx->hooks->egl.eglQueryString(dp->dpys[i], EGL_VENDOR);
-            dp->queryString[i].version =
-                cnx->hooks->egl.eglQueryString(dp->dpys[i], EGL_VERSION);
-            dp->queryString[i].extensions = strdup(
-                    cnx->hooks->egl.eglQueryString(dp->dpys[i], EGL_EXTENSIONS));
-            dp->queryString[i].clientApi =
-                cnx->hooks->egl.eglQueryString(dp->dpys[i], EGL_CLIENT_APIS);
+            dp->disp[i].queryString.vendor =
+                cnx->hooks->egl.eglQueryString(idpy, EGL_VENDOR);
+            dp->disp[i].queryString.version =
+                cnx->hooks->egl.eglQueryString(idpy, EGL_VERSION);
+            dp->disp[i].queryString.extensions =
+                    cnx->hooks->egl.eglQueryString(idpy, EGL_EXTENSIONS);
+            dp->disp[i].queryString.clientApi =
+                cnx->hooks->egl.eglQueryString(idpy, EGL_CLIENT_APIS);
 
         } else {
-            LOGD("%d: eglInitialize() failed (%s)", 
-                    i, egl_strerror(cnx->hooks->egl.eglGetError()));
+            LOGW("%d: eglInitialize(%p) failed (%s)", i, idpy,
+                    egl_strerror(cnx->hooks->egl.eglGetError()));
         }
     }
 
@@ -598,15 +702,16 @@
         egl_connection_t* const cnx = &gEGLImpl[i];
         if (cnx->dso && cnx->major>=0 && cnx->minor>=0) {
             EGLint n;
-            if (cnx->hooks->egl.eglGetConfigs(dp->dpys[i], 0, 0, &n)) {
-                dp->configs[i] = (EGLConfig*)malloc(sizeof(EGLConfig)*n);
-                if (dp->configs[i]) {
+            if (cnx->hooks->egl.eglGetConfigs(dp->disp[i].dpy, 0, 0, &n)) {
+                dp->disp[i].config = (EGLConfig*)malloc(sizeof(EGLConfig)*n);
+                if (dp->disp[i].config) {
                     if (cnx->hooks->egl.eglGetConfigs(
-                            dp->dpys[i], dp->configs[i], n, &dp->numConfigs[i]))
+                            dp->disp[i].dpy, dp->disp[i].config, n,
+                            &dp->disp[i].numConfigs))
                     {
                         // sort the configurations so we can do binary searches
-                        qsort(  dp->configs[i],
-                                dp->numConfigs[i],
+                        qsort(  dp->disp[i].config,
+                                dp->disp[i].numConfigs,
                                 sizeof(EGLConfig), cmp_configs);
 
                         dp->numTotalConfigs += n;
@@ -639,18 +744,24 @@
     EGLBoolean res = EGL_FALSE;
     for (int i=0 ; i<IMPL_NUM_DRIVERS_IMPLEMENTATIONS ; i++) {
         egl_connection_t* const cnx = &gEGLImpl[i];
-        if (cnx->dso) {
-            cnx->hooks->egl.eglTerminate(dp->dpys[i]);
+        if (cnx->dso && dp->disp[i].state == egl_display_t::INITIALIZED) {
+            if (cnx->hooks->egl.eglTerminate(dp->disp[i].dpy) == EGL_FALSE) {
+                LOGW("%d: eglTerminate(%p) failed (%s)", i, dp->disp[i].dpy,
+                        egl_strerror(cnx->hooks->egl.eglGetError()));
+            }
             // REVISIT: it's unclear what to do if eglTerminate() fails
-            free(dp->configs[i]);
-            free((void*)dp->queryString[i].extensions);
-            dp->numConfigs[i] = 0;
-            dp->dpys[i] = EGL_NO_DISPLAY;
+            free(dp->disp[i].config);
+
+            dp->disp[i].numConfigs = 0;
+            dp->disp[i].config = 0;
+            dp->disp[i].state = egl_display_t::TERMINATED;
+
             res = EGL_TRUE;
         }
     }
-    free((void*)dp->extensionsString);
-    dp->extensionsString = 0;
+    
+    // TODO: all egl_object_t should be marked for termination
+    
     dp->numTotalConfigs = 0;
     clearTLS();
     return res;
@@ -674,7 +785,7 @@
     }
     GLint n = 0;
     for (int j=0 ; j<IMPL_NUM_DRIVERS_IMPLEMENTATIONS ; j++) {
-        for (int i=0 ; i<dp->numConfigs[j] && config_size ; i++) {
+        for (int i=0 ; i<dp->disp[j].numConfigs && config_size ; i++) {
             *configs++ = MAKE_CONFIG(j, i);
             config_size--;
             n++;
@@ -731,7 +842,7 @@
         egl_connection_t* const cnx = &gEGLImpl[i];
         if (cnx->dso) {
             cnx->hooks->egl.eglGetConfigAttrib(
-                    dp->dpys[i], dp->configs[i][index], 
+                    dp->disp[i].dpy, dp->disp[i].config[index], 
                     EGL_CONFIG_ID, &configId);
 
             // and switch to the new list
@@ -746,7 +857,7 @@
             // which one.
 
             res = cnx->hooks->egl.eglChooseConfig(
-                    dp->dpys[i], attrib_list, configs, config_size, &n);
+                    dp->disp[i].dpy, attrib_list, configs, config_size, &n);
             if (res && n>0) {
                 // n has to be 0 or 1, by construction, and we already know
                 // which config it will return (since there can be only one).
@@ -765,13 +876,14 @@
         egl_connection_t* const cnx = &gEGLImpl[i];
         if (cnx->dso) {
             if (cnx->hooks->egl.eglChooseConfig(
-                    dp->dpys[i], attrib_list, configs, config_size, &n)) {
+                    dp->disp[i].dpy, attrib_list, configs, config_size, &n)) {
                 if (configs) {
                     // now we need to convert these client EGLConfig to our
                     // internal EGLConfig format. This is done in O(n log n).
                     for (int j=0 ; j<n ; j++) {
                         int index = binarySearch<EGLConfig>(
-                                dp->configs[i], 0, dp->numConfigs[i]-1, configs[j]);
+                                dp->disp[i].config, 0,
+                                dp->disp[i].numConfigs-1, configs[j]);
                         if (index >= 0) {
                             if (configs) {
                                 configs[j] = MAKE_CONFIG(i, index);
@@ -806,7 +918,7 @@
         return EGL_TRUE;
     }
     return cnx->hooks->egl.eglGetConfigAttrib(
-            dp->dpys[i], dp->configs[i][index], attribute, value);
+            dp->disp[i].dpy, dp->disp[i].config[index], attribute, value);
 }
 
 // ----------------------------------------------------------------------------
@@ -822,7 +934,7 @@
     egl_connection_t* cnx = validate_display_config(dpy, config, dp, i, index);
     if (cnx) {
         EGLSurface surface = cnx->hooks->egl.eglCreateWindowSurface(
-                dp->dpys[i], dp->configs[i][index], window, attrib_list);       
+                dp->disp[i].dpy, dp->disp[i].config[index], window, attrib_list);       
         if (surface != EGL_NO_SURFACE) {
             egl_surface_t* s = new egl_surface_t(dpy, surface, i, cnx);
             return s;
@@ -840,7 +952,7 @@
     egl_connection_t* cnx = validate_display_config(dpy, config, dp, i, index);
     if (cnx) {
         EGLSurface surface = cnx->hooks->egl.eglCreatePixmapSurface(
-                dp->dpys[i], dp->configs[i][index], pixmap, attrib_list);
+                dp->disp[i].dpy, dp->disp[i].config[index], pixmap, attrib_list);
         if (surface != EGL_NO_SURFACE) {
             egl_surface_t* s = new egl_surface_t(dpy, surface, i, cnx);
             return s;
@@ -857,7 +969,7 @@
     egl_connection_t* cnx = validate_display_config(dpy, config, dp, i, index);
     if (cnx) {
         EGLSurface surface = cnx->hooks->egl.eglCreatePbufferSurface(
-                dp->dpys[i], dp->configs[i][index], attrib_list);
+                dp->disp[i].dpy, dp->disp[i].config[index], attrib_list);
         if (surface != EGL_NO_SURFACE) {
             egl_surface_t* s = new egl_surface_t(dpy, surface, i, cnx);
             return s;
@@ -868,28 +980,35 @@
                                     
 EGLBoolean eglDestroySurface(EGLDisplay dpy, EGLSurface surface)
 {
+    SurfaceRef _s(surface);
+    if (!_s.get()) return setError(EGL_BAD_SURFACE, EGL_FALSE);
+
     if (!validate_display_surface(dpy, surface))
         return EGL_FALSE;    
     egl_display_t const * const dp = get_display(dpy);
-    egl_surface_t const * const s = get_surface(surface);
 
+    egl_surface_t * const s = get_surface(surface);
     EGLBoolean result = s->cnx->hooks->egl.eglDestroySurface(
-            dp->dpys[s->impl], s->surface);
-    
-    delete s;
+            dp->disp[s->impl].dpy, s->surface);
+    if (result == EGL_TRUE) {
+        _s.terminate();
+    }
     return result;
 }
 
 EGLBoolean eglQuerySurface( EGLDisplay dpy, EGLSurface surface,
                             EGLint attribute, EGLint *value)
 {
+    SurfaceRef _s(surface);
+    if (!_s.get()) return setError(EGL_BAD_SURFACE, EGL_FALSE);
+
     if (!validate_display_surface(dpy, surface))
         return EGL_FALSE;    
     egl_display_t const * const dp = get_display(dpy);
     egl_surface_t const * const s = get_surface(surface);
 
     return s->cnx->hooks->egl.eglQuerySurface(
-            dp->dpys[s->impl], s->surface, attribute, value);
+            dp->disp[s->impl].dpy, s->surface, attribute, value);
 }
 
 // ----------------------------------------------------------------------------
@@ -904,7 +1023,8 @@
     egl_connection_t* cnx = validate_display_config(dpy, config, dp, i, index);
     if (cnx) {
         EGLContext context = cnx->hooks->egl.eglCreateContext(
-                dp->dpys[i], dp->configs[i][index], share_list, attrib_list);
+                dp->disp[i].dpy, dp->disp[i].config[index],
+                share_list, attrib_list);
         if (context != EGL_NO_CONTEXT) {
             egl_context_t* c = new egl_context_t(dpy, context, i, cnx);
             return c;
@@ -915,66 +1035,125 @@
 
 EGLBoolean eglDestroyContext(EGLDisplay dpy, EGLContext ctx)
 {
+    ContextRef _c(ctx);
+    if (!_c.get()) return setError(EGL_BAD_CONTEXT, EGL_FALSE);
+    
     if (!validate_display_context(dpy, ctx))
         return EGL_FALSE;
     egl_display_t const * const dp = get_display(dpy);
     egl_context_t * const c = get_context(ctx);
     EGLBoolean result = c->cnx->hooks->egl.eglDestroyContext(
-            dp->dpys[c->impl], c->context);
-    delete c;
+            dp->disp[c->impl].dpy, c->context);
+    if (result == EGL_TRUE) {
+        _c.terminate();
+    }
     return result;
 }
 
 EGLBoolean eglMakeCurrent(  EGLDisplay dpy, EGLSurface draw,
                             EGLSurface read, EGLContext ctx)
 {
+    // get a reference to the object passed in
+    ContextRef _c(ctx);
+    SurfaceRef _d(draw);
+    SurfaceRef _r(read);
+
+    // validate the display and the context (if not EGL_NO_CONTEXT)
     egl_display_t const * const dp = get_display(dpy);
     if (!dp) return setError(EGL_BAD_DISPLAY, EGL_FALSE);
-
-    if (read == EGL_NO_SURFACE && draw  == EGL_NO_SURFACE &&
-            ctx == EGL_NO_CONTEXT) 
-    {
-        EGLBoolean result = EGL_TRUE;
-        ctx = getContext();
-        if (ctx) {
-            egl_context_t * const c = get_context(ctx);
-            result = c->cnx->hooks->egl.eglMakeCurrent(dp->dpys[c->impl], 0, 0, 0);
-            if (result == EGL_TRUE) {
-                setGlThreadSpecific(&gHooks[IMPL_NO_CONTEXT]);
-                setContext(EGL_NO_CONTEXT);
-            }
-        }
-        return result;
+    if ((ctx != EGL_NO_CONTEXT) && (!validate_display_context(dpy, ctx))) {
+        // EGL_NO_CONTEXT is valid
+        return EGL_FALSE;
     }
 
-    if (!validate_display_context(dpy, ctx))
-        return EGL_FALSE;    
-    
+    // these are the underlying implementation's object
+    EGLContext impl_ctx  = EGL_NO_CONTEXT;
     EGLSurface impl_draw = EGL_NO_SURFACE;
     EGLSurface impl_read = EGL_NO_SURFACE;
-    egl_context_t * const c = get_context(ctx);
+
+    // these are our objects structs passed in
+    egl_context_t       * c = NULL;
+    egl_surface_t const * d = NULL;
+    egl_surface_t const * r = NULL;
+
+    // these are the current objects structs
+    egl_context_t * cur_c = get_context(getContext());
+    egl_surface_t * cur_r = NULL;
+    egl_surface_t * cur_d = NULL;
+    
+    if (ctx != EGL_NO_CONTEXT) {
+        c = get_context(ctx);
+        cur_r = get_surface(c->read);
+        cur_d = get_surface(c->draw);
+        impl_ctx = c->context;
+    } else {
+        // no context given, use the implementation of the current context
+        if (cur_c == NULL) {
+            // no current context
+            if (draw != EGL_NO_SURFACE || read != EGL_NO_SURFACE) {
+                // calling eglMakeCurrent( ..., EGL_NO_CONTEXT, !=0, !=0);
+                return setError(EGL_BAD_PARAMETER, EGL_FALSE);
+            }
+            // not an error, there is just not current context.
+            return EGL_TRUE;
+        }
+    }
+
+    // retrieve the underlying implementation's draw EGLSurface
     if (draw != EGL_NO_SURFACE) {
-        egl_surface_t const * d = get_surface(draw);
-        if (!d) return setError(EGL_BAD_SURFACE, EGL_FALSE);
-        if (d->impl != c->impl)
+        d = get_surface(draw);
+        // make sure the EGLContext and EGLSurface passed in are for
+        // the same driver
+        if (c && d->impl != c->impl)
             return setError(EGL_BAD_MATCH, EGL_FALSE);
         impl_draw = d->surface;
     }
+
+    // retrieve the underlying implementation's read EGLSurface
     if (read != EGL_NO_SURFACE) {
-        egl_surface_t const * r = get_surface(read);
-        if (!r) return setError(EGL_BAD_SURFACE, EGL_FALSE);
-        if (r->impl != c->impl)
+        r = get_surface(read);
+        // make sure the EGLContext and EGLSurface passed in are for
+        // the same driver
+        if (c && r->impl != c->impl)
             return setError(EGL_BAD_MATCH, EGL_FALSE);
         impl_read = r->surface;
     }
-    EGLBoolean result = c->cnx->hooks->egl.eglMakeCurrent(
-            dp->dpys[c->impl], impl_draw, impl_read, c->context);
+
+    EGLBoolean result;
+
+    if (c) {
+        result = c->cnx->hooks->egl.eglMakeCurrent(
+                dp->disp[c->impl].dpy, impl_draw, impl_read, impl_ctx);
+    } else {
+        result = cur_c->cnx->hooks->egl.eglMakeCurrent(
+                dp->disp[cur_c->impl].dpy, impl_draw, impl_read, impl_ctx);
+    }
 
     if (result == EGL_TRUE) {
-        setGlThreadSpecific(c->cnx->hooks);
-        setContext(ctx);
-        c->read = read;
-        c->draw = draw;
+        // by construction, these are either 0 or valid (possibly terminated)
+        // it should be impossible for these to be invalid
+        ContextRef _cur_c(cur_c);
+        SurfaceRef _cur_r(cur_r);
+        SurfaceRef _cur_d(cur_d);
+
+        // cur_c has to be valid here (but could be terminated)
+        if (ctx != EGL_NO_CONTEXT) {
+            setGlThreadSpecific(c->cnx->hooks);
+            setContext(ctx);
+            _c.acquire();
+        } else {
+            setGlThreadSpecific(&gHooks[IMPL_NO_CONTEXT]);
+            setContext(EGL_NO_CONTEXT);
+        }
+        _cur_c.release();
+
+        _r.acquire();
+        _cur_r.release();
+        if (c) c->read = read;
+
+        _d.acquire();
+        _cur_d.release();
+        if (c) c->draw = draw;
     }
     return result;
 }
@@ -983,6 +1162,9 @@
 EGLBoolean eglQueryContext( EGLDisplay dpy, EGLContext ctx,
                             EGLint attribute, EGLint *value)
 {
+    ContextRef _c(ctx);
+    if (!_c.get()) return setError(EGL_BAD_CONTEXT, EGL_FALSE);
+
     if (!validate_display_context(dpy, ctx))
         return EGL_FALSE;    
     
@@ -990,7 +1172,7 @@
     egl_context_t * const c = get_context(ctx);
 
     return c->cnx->hooks->egl.eglQueryContext(
-            dp->dpys[c->impl], c->context, attribute, value);
+            dp->disp[c->impl].dpy, c->context, attribute, value);
 }
 
 EGLContext eglGetCurrentContext(void)
@@ -1158,22 +1340,28 @@
 
 EGLBoolean eglSwapBuffers(EGLDisplay dpy, EGLSurface draw)
 {
+    SurfaceRef _s(draw);
+    if (!_s.get()) return setError(EGL_BAD_SURFACE, EGL_FALSE);
+
     if (!validate_display_surface(dpy, draw))
         return EGL_FALSE;    
     egl_display_t const * const dp = get_display(dpy);
     egl_surface_t const * const s = get_surface(draw);
-    return s->cnx->hooks->egl.eglSwapBuffers(dp->dpys[s->impl], s->surface);
+    return s->cnx->hooks->egl.eglSwapBuffers(dp->disp[s->impl].dpy, s->surface);
 }
 
 EGLBoolean eglCopyBuffers(  EGLDisplay dpy, EGLSurface surface,
                             NativePixmapType target)
 {
+    SurfaceRef _s(surface);
+    if (!_s.get()) return setError(EGL_BAD_SURFACE, EGL_FALSE);
+
     if (!validate_display_surface(dpy, surface))
         return EGL_FALSE;    
     egl_display_t const * const dp = get_display(dpy);
     egl_surface_t const * const s = get_surface(surface);
     return s->cnx->hooks->egl.eglCopyBuffers(
-            dp->dpys[s->impl], s->surface, target);
+            dp->disp[s->impl].dpy, s->surface, target);
 }
 
 const char* eglQueryString(EGLDisplay dpy, EGLint name)
@@ -1200,13 +1388,16 @@
 EGLBoolean eglSurfaceAttrib(
         EGLDisplay dpy, EGLSurface surface, EGLint attribute, EGLint value)
 {
+    SurfaceRef _s(surface);
+    if (!_s.get()) return setError(EGL_BAD_SURFACE, EGL_FALSE);
+
     if (!validate_display_surface(dpy, surface))
         return EGL_FALSE;    
     egl_display_t const * const dp = get_display(dpy);
     egl_surface_t const * const s = get_surface(surface);
     if (s->cnx->hooks->egl.eglSurfaceAttrib) {
         return s->cnx->hooks->egl.eglSurfaceAttrib(
-                dp->dpys[s->impl], s->surface, attribute, value);
+                dp->disp[s->impl].dpy, s->surface, attribute, value);
     }
     return setError(EGL_BAD_SURFACE, EGL_FALSE);
 }
@@ -1214,13 +1405,16 @@
 EGLBoolean eglBindTexImage(
         EGLDisplay dpy, EGLSurface surface, EGLint buffer)
 {
+    SurfaceRef _s(surface);
+    if (!_s.get()) return setError(EGL_BAD_SURFACE, EGL_FALSE);
+
     if (!validate_display_surface(dpy, surface))
         return EGL_FALSE;    
     egl_display_t const * const dp = get_display(dpy);
     egl_surface_t const * const s = get_surface(surface);
     if (s->cnx->hooks->egl.eglBindTexImage) {
         return s->cnx->hooks->egl.eglBindTexImage(
-                dp->dpys[s->impl], s->surface, buffer);
+                dp->disp[s->impl].dpy, s->surface, buffer);
     }
     return setError(EGL_BAD_SURFACE, EGL_FALSE);
 }
@@ -1228,13 +1422,16 @@
 EGLBoolean eglReleaseTexImage(
         EGLDisplay dpy, EGLSurface surface, EGLint buffer)
 {
+    SurfaceRef _s(surface);
+    if (!_s.get()) return setError(EGL_BAD_SURFACE, EGL_FALSE);
+
     if (!validate_display_surface(dpy, surface))
         return EGL_FALSE;    
     egl_display_t const * const dp = get_display(dpy);
     egl_surface_t const * const s = get_surface(surface);
     if (s->cnx->hooks->egl.eglReleaseTexImage) {
         return s->cnx->hooks->egl.eglReleaseTexImage(
-                dp->dpys[s->impl], s->surface, buffer);
+                dp->disp[s->impl].dpy, s->surface, buffer);
     }
     return setError(EGL_BAD_SURFACE, EGL_FALSE);
 }
@@ -1249,7 +1446,8 @@
         egl_connection_t* const cnx = &gEGLImpl[i];
         if (cnx->dso) {
             if (cnx->hooks->egl.eglSwapInterval) {
-                if (cnx->hooks->egl.eglSwapInterval(dp->dpys[i], interval) == EGL_FALSE) {
+                if (cnx->hooks->egl.eglSwapInterval(
+                        dp->disp[i].dpy, interval) == EGL_FALSE) {
                     res = EGL_FALSE;
                 }
             }
@@ -1351,7 +1549,8 @@
     if (!cnx) return EGL_FALSE;
     if (cnx->hooks->egl.eglCreatePbufferFromClientBuffer) {
         return cnx->hooks->egl.eglCreatePbufferFromClientBuffer(
-                dp->dpys[i], buftype, buffer, dp->configs[i][index], attrib_list);
+                dp->disp[i].dpy, buftype, buffer, 
+                dp->disp[i].config[index], attrib_list);
     }
     return setError(EGL_BAD_CONFIG, EGL_NO_SURFACE);
 }
@@ -1363,6 +1562,9 @@
 EGLBoolean eglLockSurfaceKHR(EGLDisplay dpy, EGLSurface surface,
         const EGLint *attrib_list)
 {
+    SurfaceRef _s(surface);
+    if (!_s.get()) return setError(EGL_BAD_SURFACE, EGL_FALSE);
+
     if (!validate_display_surface(dpy, surface))
         return EGL_FALSE;
 
@@ -1371,13 +1573,16 @@
 
     if (s->cnx->hooks->egl.eglLockSurfaceKHR) {
         return s->cnx->hooks->egl.eglLockSurfaceKHR(
-                dp->dpys[s->impl], s->surface, attrib_list);
+                dp->disp[s->impl].dpy, s->surface, attrib_list);
     }
     return setError(EGL_BAD_DISPLAY, EGL_FALSE);
 }
 
 EGLBoolean eglUnlockSurfaceKHR(EGLDisplay dpy, EGLSurface surface)
 {
+    SurfaceRef _s(surface);
+    if (!_s.get()) return setError(EGL_BAD_SURFACE, EGL_FALSE);
+
     if (!validate_display_surface(dpy, surface))
         return EGL_FALSE;
 
@@ -1386,7 +1591,7 @@
 
     if (s->cnx->hooks->egl.eglUnlockSurfaceKHR) {
         return s->cnx->hooks->egl.eglUnlockSurfaceKHR(
-                dp->dpys[s->impl], s->surface);
+                dp->disp[s->impl].dpy, s->surface);
     }
     return setError(EGL_BAD_DISPLAY, EGL_FALSE);
 }
@@ -1395,13 +1600,15 @@
         EGLClientBuffer buffer, const EGLint *attrib_list)
 {
     if (ctx != EGL_NO_CONTEXT) {
+        ContextRef _c(ctx);
+        if (!_c.get()) return setError(EGL_BAD_CONTEXT, EGL_NO_IMAGE_KHR);
         if (!validate_display_context(dpy, ctx))
             return EGL_NO_IMAGE_KHR;
         egl_display_t const * const dp = get_display(dpy);
         egl_context_t * const c = get_context(ctx);
         // since we have an EGLContext, we know which implementation to use
         EGLImageKHR image = c->cnx->hooks->egl.eglCreateImageKHR(
-                dp->dpys[c->impl], c->context, target, buffer, attrib_list);
+                dp->disp[c->impl].dpy, c->context, target, buffer, attrib_list);
         if (image == EGL_NO_IMAGE_KHR)
             return image;
             
@@ -1425,7 +1632,7 @@
             if (cnx->dso) {
                 if (cnx->hooks->egl.eglCreateImageKHR) {
                     implImages[i] = cnx->hooks->egl.eglCreateImageKHR(
-                            dp->dpys[i], ctx, target, buffer, attrib_list);
+                            dp->disp[i].dpy, ctx, target, buffer, attrib_list);
                     if (implImages[i] != EGL_NO_IMAGE_KHR) {
                         success = true;
                     }
@@ -1443,16 +1650,15 @@
 
 EGLBoolean eglDestroyImageKHR(EGLDisplay dpy, EGLImageKHR img)
 {
-     egl_display_t const * const dp = get_display(dpy);
+    egl_display_t const * const dp = get_display(dpy);
      if (dp == 0) {
          return setError(EGL_BAD_DISPLAY, EGL_FALSE);
      }
 
-     egl_image_t* image = get_image(img);
-     if (!image->isValid()) {
-         return setError(EGL_BAD_PARAMETER, EGL_FALSE);
-     }
+     ImageRef _i(img);
+     if (!_i.get()) return setError(EGL_BAD_PARAMETER, EGL_FALSE);
 
+     egl_image_t* image = get_image(img);
      bool success = false;
      for (int i=0 ; i<IMPL_NUM_DRIVERS_IMPLEMENTATIONS ; i++) {
          egl_connection_t* const cnx = &gEGLImpl[i];
@@ -1460,7 +1666,7 @@
              if (cnx->dso) {
                  if (cnx->hooks->egl.eglCreateImageKHR) {
                      if (cnx->hooks->egl.eglDestroyImageKHR(
-                             dp->dpys[i], image->images[i])) {
+                             dp->disp[i].dpy, image->images[i])) {
                          success = true;
                      }
                  }
@@ -1470,7 +1676,7 @@
      if (!success)
          return EGL_FALSE;
 
-     delete image;
+     _i.terminate();
 
      return EGL_TRUE;
 }
@@ -1483,26 +1689,32 @@
 EGLBoolean eglSetSwapRectangleANDROID(EGLDisplay dpy, EGLSurface draw,
         EGLint left, EGLint top, EGLint width, EGLint height)
 {
+    SurfaceRef _s(draw);
+    if (!_s.get()) return setError(EGL_BAD_SURFACE, EGL_FALSE);
+
     if (!validate_display_surface(dpy, draw))
         return EGL_FALSE;    
     egl_display_t const * const dp = get_display(dpy);
     egl_surface_t const * const s = get_surface(draw);
     if (s->cnx->hooks->egl.eglSetSwapRectangleANDROID) {
-        return s->cnx->hooks->egl.eglSetSwapRectangleANDROID(dp->dpys[s->impl],
-                s->surface, left, top, width, height);
+        return s->cnx->hooks->egl.eglSetSwapRectangleANDROID(
+                dp->disp[s->impl].dpy, s->surface, left, top, width, height);
     }
     return setError(EGL_BAD_DISPLAY, NULL);
 }
 
 EGLClientBuffer eglGetRenderBufferANDROID(EGLDisplay dpy, EGLSurface draw)
 {
+    SurfaceRef _s(draw);
+    if (!_s.get()) return setError(EGL_BAD_SURFACE, (EGLClientBuffer*)0);
+
     if (!validate_display_surface(dpy, draw))
         return 0;    
     egl_display_t const * const dp = get_display(dpy);
     egl_surface_t const * const s = get_surface(draw);
     if (s->cnx->hooks->egl.eglGetRenderBufferANDROID) {
-        return s->cnx->hooks->egl.eglGetRenderBufferANDROID(dp->dpys[s->impl],
-                s->surface);
+        return s->cnx->hooks->egl.eglGetRenderBufferANDROID(
+                dp->disp[s->impl].dpy, s->surface);
     }
     return setError(EGL_BAD_DISPLAY, (EGLClientBuffer*)0);
 }