Merge change 21259 into eclair

* changes:
  Make certificate-handling-related constants public
diff --git a/im/java/android/im/BrandingResourceIDs.java b/im/java/android/im/BrandingResourceIDs.java
deleted file mode 100644
index 9960722..0000000
--- a/im/java/android/im/BrandingResourceIDs.java
+++ /dev/null
@@ -1,52 +0,0 @@
-/*
- * Copyright (C) 2008 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.
- */
-package android.im;
-
-/**
- * @hide
- * Defines the IDs of branding resources.
- */
-public interface BrandingResourceIDs {
-    /**
-     * The logo icon of the provider which is displayed in the landing page.
-     */
-    public static final int DRAWABLE_LOGO                = 100;
-    /**
-     * The icon of online presence status.
-     */
-    public static final int DRAWABLE_PRESENCE_ONLINE     = 102;
-    /**
-     * The icon of busy presence status.
-     */
-    public static final int DRAWABLE_PRESENCE_BUSY       = 103;
-    /**
-     * The icon of away presence status.
-     */
-    public static final int DRAWABLE_PRESENCE_AWAY       = 104;
-    /**
-     * The icon of invisible presence status.
-     */
-    public static final int DRAWABLE_PRESENCE_INVISIBLE  = 105;
-    /**
-     * The icon of offline presence status.
-     */
-    public static final int DRAWABLE_PRESENCE_OFFLINE    = 106;
-    /**
-     * The label of the menu to go to the contact list screen.
-     */
-    public static final int STRING_MENU_CONTACT_LIST     = 107;
-
-}
diff --git a/im/java/android/im/IImPlugin.aidl b/im/java/android/im/IImPlugin.aidl
deleted file mode 100644
index 229cd0e..0000000
--- a/im/java/android/im/IImPlugin.aidl
+++ /dev/null
@@ -1,69 +0,0 @@
-/*
- * Copyright (C) 2008 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.
- */
-package android.im;
-
-/**
- * @hide
- */
-interface IImPlugin {
-    /**
-     * Notify the plugin the front door activity is created. This gives the plugin a chance to
-     * start its own servics, etc.
-     */
-    void onStart();
-    
-    /**
-     * Notify the plugin the front door activity is stopping.
-     */
-    void onStop();
-
-    /**
-     * Sign in to the service for the account passed in.
-     *
-     * @param account the account id for the accont to be signed into.
-     */
-    void signIn(long account);
-
-    /**
-     * Sign out of the service for the account passed in.
-     *
-     * @param account the account id for the accont to be signed out of.
-     */
-    void signOut(long account);
-
-    /**
-     * Returns the package name used to load the resources for the given provider name.
-     *
-     * @return The package name to load the resourcs for the given provider.
-     */
-    String getResourcePackageNameForProvider(String providerName);
-
-    /**
-     * Returns a map of branding resources for the given provider. The keys are defined
-     * in {@link android.im.BrandingResourceIDs}. The values are the resource identifiers generated
-     * by the aapt tool.
-     *
-     * @return The map of branding resources for the given provider.
-     */
-    Map getResourceMapForProvider(String providerName);
-
-    /*
-     * Returns a list of supported IM providers.
-     *
-     * @return a List of supported providers.
-     */
-    List getSupportedProviders();
-}
diff --git a/im/java/android/im/ImPluginConsts.java b/im/java/android/im/ImPluginConsts.java
deleted file mode 100644
index 416493f..0000000
--- a/im/java/android/im/ImPluginConsts.java
+++ /dev/null
@@ -1,27 +0,0 @@
-/*
- * Copyright (C) 2008 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.
- */
-
-package android.im;
-
-/**
- * @hide
- */
-public class ImPluginConsts {
-    /**
-     * The intent action name for the plugin service.
-     */
-    public static final String PLUGIN_ACTION_NAME = "android.im.plugin";
-}
\ No newline at end of file
diff --git a/include/binder/MemoryHeapBase.h b/include/binder/MemoryHeapBase.h
index 83c7283..435540e 100644
--- a/include/binder/MemoryHeapBase.h
+++ b/include/binder/MemoryHeapBase.h
@@ -42,7 +42,7 @@
      * maps the memory referenced by fd. but DOESN'T take ownership
      * of the filedescriptor (it makes a copy with dup()
      */
-    MemoryHeapBase(int fd, size_t size, uint32_t flags = 0);
+    MemoryHeapBase(int fd, size_t size, uint32_t flags = 0, uint32_t offset = 0);
     
     /*
      * maps memory from the given device
@@ -82,7 +82,7 @@
             int flags = 0, const char* device = NULL);    
 
 private:
-    status_t mapfd(int fd, size_t size);
+    status_t mapfd(int fd, size_t size, uint32_t offset = 0);
 
     int         mFD;
     size_t      mSize;
diff --git a/include/binder/Parcel.h b/include/binder/Parcel.h
index 58c2d9a..ba6c711 100644
--- a/include/binder/Parcel.h
+++ b/include/binder/Parcel.h
@@ -74,6 +74,7 @@
     status_t            writeInt64(int64_t val);
     status_t            writeFloat(float val);
     status_t            writeDouble(double val);
+    status_t            writeIntPtr(intptr_t val);
     status_t            writeCString(const char* str);
     status_t            writeString8(const String8& str);
     status_t            writeString16(const String16& str);
@@ -109,6 +110,8 @@
     status_t            readFloat(float *pArg) const;
     double              readDouble() const;
     status_t            readDouble(double *pArg) const;
+    intptr_t            readIntPtr() const;
+    status_t            readIntPtr(intptr_t *pArg) const;
 
     const char*         readCString() const;
     String8             readString8() const;
@@ -163,6 +166,14 @@
     void                initState();
     void                scanForFds() const;
                         
+    template<class T>
+    status_t            readAligned(T *pArg) const;
+
+    template<class T>   T readAligned() const;
+
+    template<class T>
+    status_t            writeAligned(T val);
+
     status_t            mError;
     uint8_t*            mData;
     size_t              mDataSize;
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/include/ui/ISurfaceFlingerClient.h b/include/ui/ISurfaceFlingerClient.h
index 932a70a..5d231e6 100644
--- a/include/ui/ISurfaceFlingerClient.h
+++ b/include/ui/ISurfaceFlingerClient.h
@@ -52,6 +52,9 @@
     struct surface_data_t {
         int32_t             token;
         int32_t             identity;
+        uint32_t            width;
+        uint32_t            height;
+        uint32_t            format;
         status_t readFromParcel(const Parcel& parcel);
         status_t writeToParcel(Parcel* parcel) const;
     };
diff --git a/include/ui/Surface.h b/include/ui/Surface.h
index 4ff0e4a..30ab82f 100644
--- a/include/ui/Surface.h
+++ b/include/ui/Surface.h
@@ -146,16 +146,16 @@
     static bool isValid(const sp<Surface>& surface) {
         return (surface != 0) && surface->isValid();
     }
-    bool isValid() {
-        return mToken>=0 && mClient!=0;
-    }
+
     static bool isSameSurface(
             const sp<Surface>& lhs, const sp<Surface>& rhs);
-    SurfaceID   ID() const      { return mToken; }
-    uint32_t    getFlags() const { return mFlags; }
+
+    bool        isValid();
+    SurfaceID   ID() const          { return mToken; }
+    uint32_t    getFlags() const    { return mFlags; }
     uint32_t    getIdentity() const { return mIdentity; }
 
-
+    // the lock/unlock APIs must be used from the same thread
     status_t    lock(SurfaceInfo* info, bool blocking = true);
     status_t    lock(SurfaceInfo* info, Region* dirty, bool blocking = true);
     status_t    unlockAndPost();
@@ -175,14 +175,18 @@
     friend class SurfaceComposerClient;
     friend class SurfaceControl;
 
+    
     // camera and camcorder need access to the ISurface binder interface for preview
     friend class Camera;
     friend class MediaRecorder;
     // mediaplayer needs access to ISurface for display
     friend class MediaPlayer;
-    friend class Test;
     friend class IOMX;
-    const sp<ISurface>& getISurface() const { return mSurface; }
+    // this is just to be able to write some unit tests
+    friend class Test;
+
+    sp<SurfaceComposerClient> getClient() const;
+    sp<ISurface> getISurface() const;
 
     status_t getBufferLocked(int index, int usage);
    
@@ -210,24 +214,38 @@
     status_t queueBuffer(const sp<SurfaceBuffer>& buffer);
 
     
-    alloc_device_t*             mAllocDevice;
+    void setUsage(uint32_t reqUsage);
+    
+    // constants
     sp<SurfaceComposerClient>   mClient;
     sp<ISurface>                mSurface;
-    sp<SurfaceBuffer>           mBuffers[2];
-    sp<SurfaceBuffer>           mLockedBuffer;
     SurfaceID                   mToken;
     uint32_t                    mIdentity;
-    uint32_t                    mWidth;
-    uint32_t                    mHeight;
-    uint32_t                    mUsage;
     PixelFormat                 mFormat;
     uint32_t                    mFlags;
-    mutable Region              mDirtyRegion;
-    mutable Region              mOldDirtyRegion;
-    mutable uint8_t             mBackbufferIndex;
-    mutable Mutex               mSurfaceLock;
-    Rect                        mSwapRectangle;
     BufferMapper&               mBufferMapper;
+
+    // protected by mSurfaceLock
+    Rect                        mSwapRectangle;
+    uint32_t                    mUsage;
+    bool                        mUsageChanged;
+    
+    // protected by mSurfaceLock. These are also used from lock/unlock
+    // but in that case, they must be called form the same thread.
+    sp<SurfaceBuffer>           mBuffers[2];
+    mutable Region              mDirtyRegion;
+    mutable uint8_t             mBackbufferIndex;
+
+    // must be used from the lock/unlock thread
+    sp<SurfaceBuffer>           mLockedBuffer;
+    mutable Region              mOldDirtyRegion;
+
+    // query() must be called from dequeueBuffer() thread
+    uint32_t                    mWidth;
+    uint32_t                    mHeight;
+
+    // Inherently thread-safe
+    mutable Mutex               mSurfaceLock;
 };
 
 }; // namespace android
diff --git a/include/ui/egl/android_natives.h b/include/ui/egl/android_natives.h
index 363142c..3740db5 100644
--- a/include/ui/egl/android_natives.h
+++ b/include/ui/egl/android_natives.h
@@ -54,8 +54,8 @@
     void* reserved[4];
 
     /* reference-counting interface */
-    void (*incRef)(android_native_base_t* base);
-    void (*decRef)(android_native_base_t* base);
+    void (*incRef)(struct android_native_base_t* base);
+    void (*decRef)(struct android_native_base_t* base);
 } android_native_base_t;
 
 // ---------------------------------------------------------------------------
@@ -108,7 +108,7 @@
      * 
      * Returns 0 on success or -errno on error.
      */
-    int     (*setSwapInterval)(android_native_window_t* window,
+    int     (*setSwapInterval)(struct android_native_window_t* window,
                 int interval);
     
     /*
@@ -118,7 +118,7 @@
      * 
      * Returns 0 on success or -errno on error.
      */
-    int     (*dequeueBuffer)(android_native_window_t* window, 
+    int     (*dequeueBuffer)(struct android_native_window_t* window, 
                 struct android_native_buffer_t** buffer);
 
     /*
@@ -128,7 +128,7 @@
      * 
      * Returns 0 on success or -errno on error.
      */
-    int     (*lockBuffer)(android_native_window_t* window,
+    int     (*lockBuffer)(struct android_native_window_t* window,
                 struct android_native_buffer_t* buffer);
    /*
     * hook called by EGL when modifications to the render buffer are done. 
@@ -138,7 +138,7 @@
     * 
     * Returns 0 on success or -errno on error.
     */
-    int     (*queueBuffer)(android_native_window_t* window,
+    int     (*queueBuffer)(struct android_native_window_t* window,
                 struct android_native_buffer_t* buffer);
 
     /*
@@ -146,7 +146,7 @@
      * 
      * Returns 0 on success or -errno on error.
      */
-    int     (*query)(android_native_window_t* window,
+    int     (*query)(struct android_native_window_t* window,
                 int what, int* value);
     
     /*
@@ -162,7 +162,7 @@
      *  
      */
     
-    int     (*perform)(android_native_window_t* window,
+    int     (*perform)(struct android_native_window_t* window,
                 int operation, ... );
     
     void* reserved_proc[3];
diff --git a/include/utils/Debug.h b/include/utils/Debug.h
index 21d04bd..d9ed32d 100644
--- a/include/utils/Debug.h
+++ b/include/utils/Debug.h
@@ -29,6 +29,8 @@
 #define COMPILE_TIME_ASSERT(_exp) \
     template class CompileTimeAssert< (_exp) >;
 #endif
+#define COMPILE_TIME_ASSERT_FUNCTION_SCOPE(_exp) \
+    CompileTimeAssert<( _exp )>();
 
 // ---------------------------------------------------------------------------
 
diff --git a/libs/binder/MemoryHeapBase.cpp b/libs/binder/MemoryHeapBase.cpp
index ac38f51..5df078f 100644
--- a/libs/binder/MemoryHeapBase.cpp
+++ b/libs/binder/MemoryHeapBase.cpp
@@ -78,13 +78,13 @@
     }
 }
 
-MemoryHeapBase::MemoryHeapBase(int fd, size_t size, uint32_t flags)
+MemoryHeapBase::MemoryHeapBase(int fd, size_t size, uint32_t flags, uint32_t offset)
     : mFD(-1), mSize(0), mBase(MAP_FAILED), mFlags(flags),
       mDevice(0), mNeedUnmap(false)
 {
     const size_t pagesize = getpagesize();
     size = ((size + pagesize-1) & ~(pagesize-1));
-    mapfd(dup(fd), size);
+    mapfd(dup(fd), size, offset);
 }
 
 status_t MemoryHeapBase::init(int fd, void *base, int size, int flags, const char* device)
@@ -100,7 +100,7 @@
     return NO_ERROR;
 }
 
-status_t MemoryHeapBase::mapfd(int fd, size_t size)
+status_t MemoryHeapBase::mapfd(int fd, size_t size, uint32_t offset)
 {
     if (size == 0) {
         // try to figure out the size automatically
@@ -121,7 +121,7 @@
 
     if ((mFlags & DONT_MAP_LOCALLY) == 0) {
         void* base = (uint8_t*)mmap(0, size,
-                PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0);
+                PROT_READ|PROT_WRITE, MAP_SHARED, fd, offset);
         if (base == MAP_FAILED) {
             LOGE("mmap(fd=%d, size=%u) failed (%s)",
                     fd, uint32_t(size), strerror(errno));
diff --git a/libs/binder/Parcel.cpp b/libs/binder/Parcel.cpp
index 785a3c5..e397bce 100644
--- a/libs/binder/Parcel.cpp
+++ b/libs/binder/Parcel.cpp
@@ -562,54 +562,27 @@
 
 status_t Parcel::writeInt32(int32_t val)
 {
-    if ((mDataPos+sizeof(val)) <= mDataCapacity) {
-restart_write:
-        *reinterpret_cast<int32_t*>(mData+mDataPos) = val;
-        return finishWrite(sizeof(val));
-    }
-
-    status_t err = growData(sizeof(val));
-    if (err == NO_ERROR) goto restart_write;
-    return err;
+    return writeAligned(val);
 }
 
 status_t Parcel::writeInt64(int64_t val)
 {
-    if ((mDataPos+sizeof(val)) <= mDataCapacity) {
-restart_write:
-        *reinterpret_cast<int64_t*>(mData+mDataPos) = val;
-        return finishWrite(sizeof(val));
-    }
-
-    status_t err = growData(sizeof(val));
-    if (err == NO_ERROR) goto restart_write;
-    return err;
+    return writeAligned(val);
 }
 
 status_t Parcel::writeFloat(float val)
 {
-    if ((mDataPos+sizeof(val)) <= mDataCapacity) {
-restart_write:
-        *reinterpret_cast<float*>(mData+mDataPos) = val;
-        return finishWrite(sizeof(val));
-    }
-
-    status_t err = growData(sizeof(val));
-    if (err == NO_ERROR) goto restart_write;
-    return err;
+    return writeAligned(val);
 }
 
 status_t Parcel::writeDouble(double val)
 {
-    if ((mDataPos+sizeof(val)) <= mDataCapacity) {
-restart_write:
-        *reinterpret_cast<double*>(mData+mDataPos) = val;
-        return finishWrite(sizeof(val));
-    }
+    return writeAligned(val);
+}
 
-    status_t err = growData(sizeof(val));
-    if (err == NO_ERROR) goto restart_write;
-    return err;
+status_t Parcel::writeIntPtr(intptr_t val)
+{
+    return writeAligned(val);
 }
 
 status_t Parcel::writeCString(const char* str)
@@ -768,103 +741,98 @@
     return NULL;
 }
 
-status_t Parcel::readInt32(int32_t *pArg) const
-{
-    if ((mDataPos+sizeof(int32_t)) <= mDataSize) {
+template<class T>
+status_t Parcel::readAligned(T *pArg) const {
+    COMPILE_TIME_ASSERT_FUNCTION_SCOPE(PAD_SIZE(sizeof(T)) == sizeof(T));
+
+    if ((mDataPos+sizeof(T)) <= mDataSize) {
         const void* data = mData+mDataPos;
-        mDataPos += sizeof(int32_t);
-        *pArg =  *reinterpret_cast<const int32_t*>(data);
+        mDataPos += sizeof(T);
+        *pArg =  *reinterpret_cast<const T*>(data);
         return NO_ERROR;
     } else {
         return NOT_ENOUGH_DATA;
     }
 }
 
+template<class T>
+T Parcel::readAligned() const {
+    T result;
+    if (readAligned(&result) != NO_ERROR) {
+        result = 0;
+    }
+
+    return result;
+}
+
+template<class T>
+status_t Parcel::writeAligned(T val) {
+    COMPILE_TIME_ASSERT_FUNCTION_SCOPE(PAD_SIZE(sizeof(T)) == sizeof(T));
+
+    if ((mDataPos+sizeof(val)) <= mDataCapacity) {
+restart_write:
+        *reinterpret_cast<T*>(mData+mDataPos) = val;
+        return finishWrite(sizeof(val));
+    }
+
+    status_t err = growData(sizeof(val));
+    if (err == NO_ERROR) goto restart_write;
+    return err;
+}
+
+status_t Parcel::readInt32(int32_t *pArg) const
+{
+    return readAligned(pArg);
+}
+
 int32_t Parcel::readInt32() const
 {
-    if ((mDataPos+sizeof(int32_t)) <= mDataSize) {
-        const void* data = mData+mDataPos;
-        mDataPos += sizeof(int32_t);
-        LOGV("readInt32 Setting data pos of %p to %d\n", this, mDataPos);
-        return *reinterpret_cast<const int32_t*>(data);
-    }
-    return 0;
+    return readAligned<int32_t>();
 }
 
 
 status_t Parcel::readInt64(int64_t *pArg) const
 {
-    if ((mDataPos+sizeof(int64_t)) <= mDataSize) {
-        const void* data = mData+mDataPos;
-        mDataPos += sizeof(int64_t);
-        *pArg = *reinterpret_cast<const int64_t*>(data);
-        LOGV("readInt64 Setting data pos of %p to %d\n", this, mDataPos);
-        return NO_ERROR;
-    } else {
-        return NOT_ENOUGH_DATA;
-    }
+    return readAligned(pArg);
 }
 
 
 int64_t Parcel::readInt64() const
 {
-    if ((mDataPos+sizeof(int64_t)) <= mDataSize) {
-        const void* data = mData+mDataPos;
-        mDataPos += sizeof(int64_t);
-        LOGV("readInt64 Setting data pos of %p to %d\n", this, mDataPos);
-        return *reinterpret_cast<const int64_t*>(data);
-    }
-    return 0;
+    return readAligned<int64_t>();
 }
 
 status_t Parcel::readFloat(float *pArg) const
 {
-    if ((mDataPos+sizeof(float)) <= mDataSize) {
-        const void* data = mData+mDataPos;
-        mDataPos += sizeof(float);
-        LOGV("readFloat Setting data pos of %p to %d\n", this, mDataPos);
-        *pArg = *reinterpret_cast<const float*>(data);
-        return NO_ERROR;
-    } else {
-        return NOT_ENOUGH_DATA;
-    }
+    return readAligned(pArg);
 }
 
 
 float Parcel::readFloat() const
 {
-    if ((mDataPos+sizeof(float)) <= mDataSize) {
-        const void* data = mData+mDataPos;
-        mDataPos += sizeof(float);
-        LOGV("readFloat Setting data pos of %p to %d\n", this, mDataPos);
-        return *reinterpret_cast<const float*>(data);
-    }
-    return 0;
+    return readAligned<float>();
 }
 
 status_t Parcel::readDouble(double *pArg) const
 {
-    if ((mDataPos+sizeof(double)) <= mDataSize) {
-        const void* data = mData+mDataPos;
-        mDataPos += sizeof(double);
-        LOGV("readDouble Setting data pos of %p to %d\n", this, mDataPos);
-        *pArg = *reinterpret_cast<const double*>(data);
-        return NO_ERROR;
-    } else {
-        return NOT_ENOUGH_DATA;
-    }
+    return readAligned(pArg);
 }
 
 
 double Parcel::readDouble() const
 {
-    if ((mDataPos+sizeof(double)) <= mDataSize) {
-        const void* data = mData+mDataPos;
-        mDataPos += sizeof(double);
-        LOGV("readDouble Setting data pos of %p to %d\n", this, mDataPos);
-        return *reinterpret_cast<const double*>(data);
-    }
-    return 0;
+    return readAligned<double>();
+}
+
+status_t Parcel::readIntPtr(intptr_t *pArg) const
+{
+    return readAligned(pArg);
+}
+
+
+intptr_t Parcel::readIntPtr() const
+{
+    return readAligned<intptr_t>();
 }
 
 
diff --git a/libs/surfaceflinger/LayerBase.cpp b/libs/surfaceflinger/LayerBase.cpp
index 419574c..fd54e35 100644
--- a/libs/surfaceflinger/LayerBase.cpp
+++ b/libs/surfaceflinger/LayerBase.cpp
@@ -730,14 +730,6 @@
     return owner;
 }
 
-
-void LayerBaseClient::Surface::getSurfaceData(
-        ISurfaceFlingerClient::surface_data_t* params) const 
-{
-    params->token = mToken;
-    params->identity = mIdentity;
-}
-
 status_t LayerBaseClient::Surface::onTransact(
         uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
 {
diff --git a/libs/surfaceflinger/LayerBase.h b/libs/surfaceflinger/LayerBase.h
index 65bf55b..7791941 100644
--- a/libs/surfaceflinger/LayerBase.h
+++ b/libs/surfaceflinger/LayerBase.h
@@ -321,10 +321,9 @@
     class Surface : public BnSurface 
     {
     public:
+        int32_t getToken() const { return mToken; }
+        int32_t getIdentity() const { return mIdentity; }
         
-        virtual void getSurfaceData(
-                ISurfaceFlingerClient::surface_data_t* params) const;
-
     protected:
         Surface(const sp<SurfaceFlinger>& flinger, 
                 SurfaceID id, int identity, 
diff --git a/libs/surfaceflinger/LayerBitmap.cpp b/libs/surfaceflinger/LayerBitmap.cpp
index 5e74451..dd61e1a 100644
--- a/libs/surfaceflinger/LayerBitmap.cpp
+++ b/libs/surfaceflinger/LayerBitmap.cpp
@@ -97,11 +97,9 @@
     err = allocator.alloc(w, h, format, usage, &handle, &stride);
     
     if (err == NO_ERROR) {
-        if (err == NO_ERROR) {
-            width  = w;
-            height = h;
-            mVStride = 0;
-        }
+        width  = w;
+        height = h;
+        mVStride = 0;
     }
 
     return err;
diff --git a/libs/surfaceflinger/SurfaceFlinger.cpp b/libs/surfaceflinger/SurfaceFlinger.cpp
index 102899c..a72294a 100644
--- a/libs/surfaceflinger/SurfaceFlinger.cpp
+++ b/libs/surfaceflinger/SurfaceFlinger.cpp
@@ -186,6 +186,10 @@
         mFreezeDisplayTime(0),
         mDebugRegion(0),
         mDebugBackground(0),
+        mDebugInSwapBuffers(0),
+        mLastSwapBufferTime(0),
+        mDebugInTransaction(0),
+        mLastTransactionTime(0),
         mConsoleSignals(0),
         mSecureFrameBuffer(0)
 {
@@ -517,7 +521,11 @@
 
     if (!mInvalidRegion.isEmpty()) {
         const DisplayHardware& hw(graphicPlane(0).displayHardware());
+        const nsecs_t now = systemTime();
+        mDebugInSwapBuffers = now;
         hw.flip(mInvalidRegion);
+        mLastSwapBufferTime = systemTime() - now;
+        mDebugInSwapBuffers = 0;
         mInvalidRegion.clear();
     }
 }
@@ -555,7 +563,11 @@
 
     { // scope for the lock
         Mutex::Autolock _l(mStateLock);
+        const nsecs_t now = systemTime();
+        mDebugInTransaction = now;
         handleTransactionLocked(transactionFlags, ditchedLayers);
+        mLastTransactionTime = systemTime() - now;
+        mDebugInTransaction = 0;
     }
 
     // do this without lock held
@@ -1239,9 +1251,11 @@
     switch (flags & eFXSurfaceMask) {
         case eFXSurfaceNormal:
             if (UNLIKELY(flags & ePushBuffers)) {
-                layer = createPushBuffersSurfaceLocked(client, d, id, w, h, flags);
+                layer = createPushBuffersSurfaceLocked(client, d, id,
+                        w, h, flags);
             } else {
-                layer = createNormalSurfaceLocked(client, d, id, w, h, format, flags);
+                layer = createNormalSurfaceLocked(client, d, id,
+                        w, h, flags, format);
             }
             break;
         case eFXSurfaceBlur:
@@ -1255,8 +1269,13 @@
     if (layer != 0) {
         setTransactionFlags(eTransactionNeeded);
         surfaceHandle = layer->getSurface();
-        if (surfaceHandle != 0)
-            surfaceHandle->getSurfaceData(params);
+        if (surfaceHandle != 0) { 
+            params->token = surfaceHandle->getToken();
+            params->identity = surfaceHandle->getIdentity();
+            params->width = w;
+            params->height = h;
+            params->format = format;
+        }
     }
 
     return surfaceHandle;
@@ -1264,7 +1283,8 @@
 
 sp<LayerBaseClient> SurfaceFlinger::createNormalSurfaceLocked(
         const sp<Client>& client, DisplayID display,
-        int32_t id, uint32_t w, uint32_t h, PixelFormat format, uint32_t flags)
+        int32_t id, uint32_t w, uint32_t h, uint32_t flags,
+        PixelFormat& format)
 {
     // initialize the surfaces
     switch (format) { // TODO: take h/w into account
@@ -1459,7 +1479,29 @@
                 IPCThreadState::self()->getCallingUid());
         result.append(buffer);
     } else {
-        Mutex::Autolock _l(mStateLock);
+
+        // figure out if we're stuck somewhere
+        const nsecs_t now = systemTime();
+        const nsecs_t inSwapBuffers(mDebugInSwapBuffers);
+        const nsecs_t inTransaction(mDebugInTransaction);
+        nsecs_t inSwapBuffersDuration = (inSwapBuffers) ? now-inSwapBuffers : 0;
+        nsecs_t inTransactionDuration = (inTransaction) ? now-inTransaction : 0;
+
+        // Try to get the main lock, but don't insist if we can't
+        // (this would indicate SF is stuck, but we want to be able to
+        // print something in dumpsys).
+        int retry = 3;
+        while (mStateLock.tryLock()<0 && --retry>=0) {
+            usleep(1000000);
+        }
+        const bool locked(retry >= 0);
+        if (!locked) {
+            snprintf(buffer, SIZE, 
+                    "SurfaceFlinger appears to be unresponsive, "
+                    "dumping anyways (no locks held)\n");
+            result.append(buffer);
+        }
+
         size_t s = mClientsMap.size();
         char name[64];
         for (size_t i=0 ; i<s ; i++) {
@@ -1530,10 +1572,29 @@
                 mFreezeDisplay?"yes":"no", mFreezeCount,
                 mCurrentState.orientation, hw.canDraw());
         result.append(buffer);
+        snprintf(buffer, SIZE,
+                "  last eglSwapBuffers() time: %f us\n"
+                "  last transaction time     : %f us\n",
+                mLastSwapBufferTime/1000.0, mLastTransactionTime/1000.0);
+        result.append(buffer);
+        if (inSwapBuffersDuration || !locked) {
+            snprintf(buffer, SIZE, "  eglSwapBuffers time: %f us\n",
+                    inSwapBuffersDuration/1000.0);
+            result.append(buffer);
+        }
+        if (inTransactionDuration || !locked) {
+            snprintf(buffer, SIZE, "  transaction time: %f us\n",
+                    inTransactionDuration/1000.0);
+            result.append(buffer);
+        }
         snprintf(buffer, SIZE, "  client count: %d\n", mClientsMap.size());
         result.append(buffer);
         const BufferAllocator& alloc(BufferAllocator::get());
         alloc.dump(result);
+
+        if (locked) {
+            mStateLock.unlock();
+        }
     }
     write(fd, result.string(), result.size());
     return NO_ERROR;
diff --git a/libs/surfaceflinger/SurfaceFlinger.h b/libs/surfaceflinger/SurfaceFlinger.h
index 2569a0f..69e2f2e 100644
--- a/libs/surfaceflinger/SurfaceFlinger.h
+++ b/libs/surfaceflinger/SurfaceFlinger.h
@@ -195,8 +195,8 @@
 
     sp<LayerBaseClient> createNormalSurfaceLocked(
             const sp<Client>& client, DisplayID display,
-            int32_t id, uint32_t w, uint32_t h, 
-            PixelFormat format, uint32_t flags);
+            int32_t id, uint32_t w, uint32_t h, uint32_t flags,
+            PixelFormat& format);
 
     sp<LayerBaseClient> createBlurSurfaceLocked(
             const sp<Client>& client, DisplayID display,
@@ -348,6 +348,10 @@
                 // don't use a lock for these, we don't care
                 int                         mDebugRegion;
                 int                         mDebugBackground;
+                volatile nsecs_t            mDebugInSwapBuffers;
+                nsecs_t                     mLastSwapBufferTime;
+                volatile nsecs_t            mDebugInTransaction;
+                nsecs_t                     mLastTransactionTime;
 
                 // these are thread safe
     mutable     Barrier                     mReadyToRunBarrier;
diff --git a/libs/ui/ISurfaceFlingerClient.cpp b/libs/ui/ISurfaceFlingerClient.cpp
index 51e8422..4a6a1d7 100644
--- a/libs/ui/ISurfaceFlingerClient.cpp
+++ b/libs/ui/ISurfaceFlingerClient.cpp
@@ -189,8 +189,11 @@
 
 status_t ISurfaceFlingerClient::surface_data_t::readFromParcel(const Parcel& parcel)
 {
-    token = parcel.readInt32();
-    identity  = parcel.readInt32();
+    token    = parcel.readInt32();
+    identity = parcel.readInt32();
+    width    = parcel.readInt32();
+    height   = parcel.readInt32();
+    format   = parcel.readInt32();
     return NO_ERROR;
 }
 
@@ -198,6 +201,9 @@
 {
     parcel->writeInt32(token);
     parcel->writeInt32(identity);
+    parcel->writeInt32(width);
+    parcel->writeInt32(height);
+    parcel->writeInt32(format);
     return NO_ERROR;
 }
 
diff --git a/libs/ui/Surface.cpp b/libs/ui/Surface.cpp
index 2b6905f..474308a 100644
--- a/libs/ui/Surface.cpp
+++ b/libs/ui/Surface.cpp
@@ -64,11 +64,16 @@
 {
     // we own the handle in this case
     width  = data.readInt32();
-    height = data.readInt32();
-    stride = data.readInt32();
-    format = data.readInt32();
-    usage  = data.readInt32();
-    handle = data.readNativeHandle();
+    if (width < 0) {
+        width = height = stride = format = usage = 0;
+        handle = 0;
+    } else {
+        height = data.readInt32();
+        stride = data.readInt32();
+        format = data.readInt32();
+        usage  = data.readInt32();
+        handle = data.readNativeHandle();
+    }
 }
 
 SurfaceBuffer::~SurfaceBuffer()
@@ -108,16 +113,25 @@
 status_t SurfaceBuffer::writeToParcel(Parcel* reply, 
         android_native_buffer_t const* buffer)
 {
-    if (buffer == NULL) {
+    if (buffer == NULL)
         return BAD_VALUE;
+
+    if (buffer->width < 0 || buffer->height < 0)
+        return BAD_VALUE;
+
+    status_t err = NO_ERROR;
+    if (buffer->handle == NULL) {
+        // this buffer doesn't have a handle
+        reply->writeInt32(NO_MEMORY);
+    } else {
+        reply->writeInt32(buffer->width);
+        reply->writeInt32(buffer->height);
+        reply->writeInt32(buffer->stride);
+        reply->writeInt32(buffer->format);
+        reply->writeInt32(buffer->usage);
+        err = reply->writeNativeHandle(buffer->handle);
     }
-    reply->writeInt32(buffer->width);
-    reply->writeInt32(buffer->height);
-    reply->writeInt32(buffer->stride);
-    reply->writeInt32(buffer->format);
-    reply->writeInt32(buffer->usage);
-    reply->writeNativeHandle(buffer->handle);
-    return NO_ERROR;
+    return err;
 }
 
 // ----------------------------------------------------------------------
@@ -183,7 +197,8 @@
         uint32_t w, uint32_t h, PixelFormat format, uint32_t flags)
     : mClient(client), mSurface(surface),
       mToken(data.token), mIdentity(data.identity),
-      mWidth(w), mHeight(h), mFormat(format), mFlags(flags)
+      mWidth(data.width), mHeight(data.height), mFormat(data.format),
+      mFlags(flags)
 {
 }
         
@@ -382,9 +397,9 @@
 Surface::Surface(const sp<SurfaceControl>& surface)
     : mClient(surface->mClient), mSurface(surface->mSurface),
       mToken(surface->mToken), mIdentity(surface->mIdentity),
-      mWidth(surface->mWidth), mHeight(surface->mHeight),
       mFormat(surface->mFormat), mFlags(surface->mFlags),
-      mBufferMapper(BufferMapper::get())
+      mBufferMapper(BufferMapper::get()),
+      mWidth(surface->mWidth), mHeight(surface->mHeight)
 {
     init();
 }
@@ -426,15 +441,15 @@
     const_cast<uint32_t&>(android_native_window_t::flags) = 0;
     // be default we request a hardware surface
     mUsage = GRALLOC_USAGE_HW_RENDER;
+    mUsageChanged = true;
 }
 
-
 Surface::~Surface()
 {
     // this is a client-side operation, the surface is destroyed, unmap
     // its buffers in this process.
     for (int i=0 ; i<2 ; i++) {
-        if (mBuffers[i] != 0) {
+        if (mBuffers[i] != 0 && mBuffers[i]->handle != 0) {
             getBufferMapper().unregisterBuffer(mBuffers[i]->handle);
         }
     }
@@ -446,11 +461,24 @@
     IPCThreadState::self()->flushCommands();
 }
 
+sp<SurfaceComposerClient> Surface::getClient() const {
+    return mClient;
+}
+
+sp<ISurface> Surface::getISurface() const {
+    return mSurface;
+}
+
+bool Surface::isValid() {
+    return mToken>=0 && mClient!=0;
+}
+
 status_t Surface::validate(per_client_cblk_t const* cblk) const
 {
+    sp<SurfaceComposerClient> client(getClient());
     if (mToken<0 || mClient==0) {
         LOGE("invalid token (%d, identity=%u) or client (%p)", 
-                mToken, mIdentity, mClient.get());
+                mToken, mIdentity, client.get());
         return NO_INIT;
     }
     if (cblk == 0) {
@@ -477,6 +505,7 @@
 {
     if (lhs == 0 || rhs == 0)
         return false;
+
     return lhs->mSurface->asBinder() == rhs->mSurface->asBinder();
 }
 
@@ -532,10 +561,9 @@
 {
     android_native_buffer_t* out;
     status_t err = dequeueBuffer(&out);
-    *buffer = SurfaceBuffer::getSelf(out);
-    // reset the width/height with the what we get from the buffer
-    mWidth  = uint32_t(out->width);
-    mHeight = uint32_t(out->height);
+    if (err == NO_ERROR) {
+        *buffer = SurfaceBuffer::getSelf(out);
+    }
     return err;
 }
 
@@ -557,7 +585,8 @@
 
     Mutex::Autolock _l(mSurfaceLock);
 
-    per_client_cblk_t* const cblk = mClient->mControl;
+    sp<SurfaceComposerClient> client(getClient());
+    per_client_cblk_t* const cblk = client->mControl;
     status_t err = validate(cblk);
     if (err != NO_ERROR)
         return err;
@@ -572,18 +601,38 @@
 
     mBackbufferIndex = backIdx;
     layer_cblk_t* const lcblk = &(cblk->layers[index]);
-
     volatile const surface_info_t* const back = lcblk->surface + backIdx;
-    if (back->flags & surface_info_t::eNeedNewBuffer) {
+
+    const sp<SurfaceBuffer>& backBuffer(mBuffers[backIdx]);
+
+    if (backBuffer==0 &&
+            !((back->flags & surface_info_t::eNeedNewBuffer) || mUsageChanged)) {
+        LOGW("dequeueBuffer: backbuffer is null, but eNeedNewBuffer "
+                "is not set, fetching a buffer anyways...");
+    }
+
+    if ((back->flags & surface_info_t::eNeedNewBuffer) ||mUsageChanged ||
+            backBuffer==0) 
+    {
+        mUsageChanged = false;
         err = getBufferLocked(backIdx, mUsage);
+        if (err == NO_ERROR) {
+            // reset the width/height with the what we get from the buffer
+            const sp<SurfaceBuffer>& backBuffer(mBuffers[backIdx]);
+            mWidth  = uint32_t(backBuffer->width);
+            mHeight = uint32_t(backBuffer->height);
+        }
     }
 
     if (err == NO_ERROR) {
-        const sp<SurfaceBuffer>& backBuffer(mBuffers[backIdx]);
-        mDirtyRegion.set(backBuffer->width, backBuffer->height);
-        *buffer = backBuffer.get();
+        if (backBuffer != 0) {
+            mDirtyRegion.set(backBuffer->width, backBuffer->height);
+            *buffer = backBuffer.get();
+        } else {
+            err = NO_MEMORY;
+        }
     }
-  
+
     return err;
 }
 
@@ -591,7 +640,8 @@
 {
     Mutex::Autolock _l(mSurfaceLock);
 
-    per_client_cblk_t* const cblk = mClient->mControl;
+    sp<SurfaceComposerClient> client(getClient());
+    per_client_cblk_t* const cblk = client->mControl;
     status_t err = validate(cblk);
     if (err != NO_ERROR)
         return err;
@@ -604,7 +654,8 @@
 {   
     Mutex::Autolock _l(mSurfaceLock);
 
-    per_client_cblk_t* const cblk = mClient->mControl;
+    sp<SurfaceComposerClient> client(getClient());
+    per_client_cblk_t* const cblk = client->mControl;
     status_t err = validate(cblk);
     if (err != NO_ERROR)
         return err;
@@ -620,7 +671,7 @@
 
     uint32_t newstate = cblk->unlock_layer_and_post(size_t(index));
     if (!(newstate & eNextFlipPending))
-        mClient->signalServer();
+        client->signalServer();
 
     return NO_ERROR;
 }
@@ -646,7 +697,7 @@
     int res = NO_ERROR;
     switch (operation) {
         case NATIVE_WINDOW_SET_USAGE:
-            mUsage = va_arg(args, int);
+            setUsage( va_arg(args, int) );
             break;
         default:
             res = NAME_NOT_FOUND;
@@ -655,6 +706,15 @@
     return res;
 }
 
+void Surface::setUsage(uint32_t reqUsage)
+{
+    Mutex::Autolock _l(mSurfaceLock);
+    if (mUsage != reqUsage) {
+        mUsageChanged = true;
+        mUsage = reqUsage;
+    }
+}
+
 // ----------------------------------------------------------------------------
 
 status_t Surface::lock(SurfaceInfo* info, bool blocking) {
@@ -663,11 +723,9 @@
 
 status_t Surface::lock(SurfaceInfo* other, Region* dirtyIn, bool blocking) 
 {
-    // FIXME: needs some locking here
-
     // we're intending to do software rendering from this point
-    mUsage = GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_SW_WRITE_OFTEN;
-    
+    setUsage(GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_SW_WRITE_OFTEN);
+
     sp<SurfaceBuffer> backBuffer;
     status_t err = dequeueBuffer(&backBuffer);
     if (err == NO_ERROR) {
@@ -679,7 +737,8 @@
             Region scratch(bounds);
             Region& newDirtyRegion(dirtyIn ? *dirtyIn : scratch);
 
-            per_client_cblk_t* const cblk = mClient->mControl;
+            sp<SurfaceComposerClient> client(getClient());
+            per_client_cblk_t* const cblk = client->mControl;
             layer_cblk_t* const lcblk = &(cblk->layers[SurfaceID(mToken)]);
             volatile const surface_info_t* const back = lcblk->surface + mBackbufferIndex;
             if (back->flags & surface_info_t::eBufferDirty) {
@@ -689,7 +748,8 @@
             } else {
                 newDirtyRegion.andSelf(bounds);
                 const sp<SurfaceBuffer>& frontBuffer(mBuffers[1-mBackbufferIndex]);
-                if (backBuffer->width  == frontBuffer->width && 
+                if (frontBuffer !=0 &&
+                    backBuffer->width  == frontBuffer->width && 
                     backBuffer->height == frontBuffer->height &&
                     !(lcblk->flags & eNoCopyBack)) 
                 {
@@ -725,8 +785,6 @@
     
 status_t Surface::unlockAndPost() 
 {
-    // FIXME: needs some locking here
-
     if (mLockedBuffer == 0)
         return BAD_VALUE;
 
@@ -753,24 +811,34 @@
 }
 
 void Surface::setSwapRectangle(const Rect& r) {
+    Mutex::Autolock _l(mSurfaceLock);
     mSwapRectangle = r;
 }
 
 status_t Surface::getBufferLocked(int index, int usage)
 {
+    sp<ISurface> s(mSurface);
+    if (s == 0) return NO_INIT;
+
     status_t err = NO_MEMORY;
-    sp<SurfaceBuffer> buffer = mSurface->getBuffer(usage);
+
+    // free the current buffer
+    sp<SurfaceBuffer>& currentBuffer(mBuffers[index]);
+    if (currentBuffer != 0) {
+        getBufferMapper().unregisterBuffer(currentBuffer->handle);
+        currentBuffer.clear();
+    }
+
+    sp<SurfaceBuffer> buffer = s->getBuffer(usage);
     LOGE_IF(buffer==0, "ISurface::getBuffer() returned NULL");
-    if (buffer != 0) {
-        sp<SurfaceBuffer>& currentBuffer(mBuffers[index]);
-        if (currentBuffer != 0) {
-            getBufferMapper().unregisterBuffer(currentBuffer->handle);
-            currentBuffer.clear();
-        }
-        err = getBufferMapper().registerBuffer(buffer->handle);
-        LOGW_IF(err, "registerBuffer(...) failed %d (%s)", err, strerror(-err));
-        if (err == NO_ERROR) {
-            currentBuffer = buffer;
+    if (buffer != 0) { // this should never happen by construction
+        if (buffer->handle != NULL) { 
+            err = getBufferMapper().registerBuffer(buffer->handle);
+            LOGW_IF(err, "registerBuffer(...) failed %d (%s)",
+                    err, strerror(-err));
+            if (err == NO_ERROR) {
+                currentBuffer = buffer;
+            }
         }
     }
     return err; 
diff --git a/opengl/libagl/egl.cpp b/opengl/libagl/egl.cpp
index 0762ebf..9c0f7fd 100644
--- a/opengl/libagl/egl.cpp
+++ b/opengl/libagl/egl.cpp
@@ -141,7 +141,8 @@
 
                 egl_surface_t(EGLDisplay dpy, EGLConfig config, int32_t depthFormat);
     virtual     ~egl_surface_t();
-    virtual     bool    isValid() const = 0;
+                bool    isValid() const;
+    virtual     bool    initCheck() const = 0;
 
     virtual     EGLBoolean  bindDrawSurface(ogles_context_t* gl) = 0;
     virtual     EGLBoolean  bindReadSurface(ogles_context_t* gl) = 0;
@@ -175,6 +176,11 @@
     magic = 0;
     free(depth.data);
 }
+bool egl_surface_t::isValid() const {
+    LOGE_IF(magic != MAGIC, "invalid EGLSurface (%p)", this);
+    return magic == MAGIC; 
+}
+
 EGLBoolean egl_surface_t::swapBuffers() {
     return EGL_FALSE;
 }
@@ -208,9 +214,9 @@
             int32_t depthFormat,
             android_native_window_t* window);
 
-     ~egl_window_surface_v2_t();
+    ~egl_window_surface_v2_t();
 
-    virtual     bool        isValid() const { return nativeWindow->common.magic == ANDROID_NATIVE_WINDOW_MAGIC; }
+    virtual     bool        initCheck() const { return true; } // TODO: report failure if ctor fails
     virtual     EGLBoolean  swapBuffers();
     virtual     EGLBoolean  bindDrawSurface(ogles_context_t* gl);
     virtual     EGLBoolean  bindReadSurface(ogles_context_t* gl);
@@ -704,7 +710,7 @@
 
     virtual ~egl_pixmap_surface_t() { }
 
-    virtual     bool        isValid() const { return nativePixmap.version == sizeof(egl_native_pixmap_t); }
+    virtual     bool        initCheck() const { return !depth.format || depth.data!=0; } 
     virtual     EGLBoolean  bindDrawSurface(ogles_context_t* gl);
     virtual     EGLBoolean  bindReadSurface(ogles_context_t* gl);
     virtual     EGLint      getWidth() const    { return nativePixmap.width;  }
@@ -726,7 +732,6 @@
         depth.data    = (GGLubyte*)malloc(depth.stride*depth.height*2);
         if (depth.data == 0) {
             setError(EGL_BAD_ALLOC, EGL_NO_SURFACE);
-            return;
         }
     }
 }
@@ -768,7 +773,7 @@
 
     virtual ~egl_pbuffer_surface_t();
 
-    virtual     bool        isValid() const { return pbuffer.data != 0; }
+    virtual     bool        initCheck() const   { return pbuffer.data != 0; }
     virtual     EGLBoolean  bindDrawSurface(ogles_context_t* gl);
     virtual     EGLBoolean  bindReadSurface(ogles_context_t* gl);
     virtual     EGLint      getWidth() const    { return pbuffer.width;  }
@@ -1196,6 +1201,11 @@
     if (!(surfaceType & EGL_WINDOW_BIT))
         return setError(EGL_BAD_MATCH, EGL_NO_SURFACE);
 
+    if (static_cast<android_native_window_t*>(window)->common.magic !=
+            ANDROID_NATIVE_WINDOW_MAGIC) {
+        return setError(EGL_BAD_NATIVE_WINDOW, EGL_NO_SURFACE);
+    }
+        
     EGLint configID;
     if (getConfigAttrib(dpy, config, EGL_CONFIG_ID, &configID) == EGL_FALSE)
         return EGL_FALSE;
@@ -1241,7 +1251,7 @@
     surface = new egl_window_surface_v2_t(dpy, config, depthFormat,
             static_cast<android_native_window_t*>(window));
 
-    if (!surface->isValid()) {
+    if (!surface->initCheck()) {
         // there was a problem in the ctor, the error
         // flag has been set.
         delete surface;
@@ -1265,6 +1275,11 @@
     if (!(surfaceType & EGL_PIXMAP_BIT))
         return setError(EGL_BAD_MATCH, EGL_NO_SURFACE);
 
+    if (static_cast<egl_native_pixmap_t*>(pixmap)->version != 
+            sizeof(egl_native_pixmap_t)) {
+        return setError(EGL_BAD_NATIVE_PIXMAP, EGL_NO_SURFACE);
+    }
+    
     EGLint configID;
     if (getConfigAttrib(dpy, config, EGL_CONFIG_ID, &configID) == EGL_FALSE)
         return EGL_FALSE;
@@ -1307,7 +1322,7 @@
         new egl_pixmap_surface_t(dpy, config, depthFormat,
                 static_cast<egl_native_pixmap_t*>(pixmap));
 
-    if (!surface->isValid()) {
+    if (!surface->initCheck()) {
         // there was a problem in the ctor, the error
         // flag has been set.
         delete surface;
@@ -1375,7 +1390,7 @@
     egl_surface_t* surface =
         new egl_pbuffer_surface_t(dpy, config, depthFormat, w, h, pixelFormat);
 
-    if (!surface->isValid()) {
+    if (!surface->initCheck()) {
         // there was a problem in the ctor, the error
         // flag has been set.
         delete surface;
@@ -1590,7 +1605,7 @@
         return setError(EGL_BAD_DISPLAY, EGL_FALSE);
     if (eglSurface != EGL_NO_SURFACE) {
         egl_surface_t* surface( static_cast<egl_surface_t*>(eglSurface) );
-        if (surface->magic != egl_surface_t::MAGIC)
+        if (!surface->isValid())
             return setError(EGL_BAD_SURFACE, EGL_FALSE);
         if (surface->dpy != dpy)
             return setError(EGL_BAD_DISPLAY, EGL_FALSE);
@@ -1610,6 +1625,8 @@
     if (egl_display_t::is_valid(dpy) == EGL_FALSE)
         return setError(EGL_BAD_DISPLAY, EGL_FALSE);
     egl_surface_t* surface = static_cast<egl_surface_t*>(eglSurface);
+    if (!surface->isValid())
+        return setError(EGL_BAD_SURFACE, EGL_FALSE);
     if (surface->dpy != dpy)
         return setError(EGL_BAD_DISPLAY, EGL_FALSE);
 
@@ -1702,9 +1719,19 @@
         return setError(EGL_BAD_DISPLAY, EGL_FALSE);
     if (draw) {
         egl_surface_t* s = (egl_surface_t*)draw;
+        if (!s->isValid())
+            return setError(EGL_BAD_SURFACE, EGL_FALSE);
         if (s->dpy != dpy)
             return setError(EGL_BAD_DISPLAY, EGL_FALSE);
-        // TODO: check that draw and read are compatible with the context
+        // TODO: check that draw is compatible with the context
+    }
+    if (read && read!=draw) {
+        egl_surface_t* s = (egl_surface_t*)read;
+        if (!s->isValid())
+            return setError(EGL_BAD_SURFACE, EGL_FALSE);
+        if (s->dpy != dpy)
+            return setError(EGL_BAD_DISPLAY, EGL_FALSE);
+        // TODO: check that read is compatible with the context
     }
 
     EGLContext current_ctx = EGL_NO_CONTEXT;
@@ -1737,7 +1764,8 @@
             egl_surface_t* r = (egl_surface_t*)read;
             
             if (c->draw) {
-                reinterpret_cast<egl_surface_t*>(c->draw)->disconnect();
+                egl_surface_t* s = reinterpret_cast<egl_surface_t*>(c->draw);
+                s->disconnect();
             }
             if (c->read) {
                 // FIXME: unlock/disconnect the read surface too 
@@ -1860,6 +1888,8 @@
         return setError(EGL_BAD_DISPLAY, EGL_FALSE);
 
     egl_surface_t* d = static_cast<egl_surface_t*>(draw);
+    if (!d->isValid())
+        return setError(EGL_BAD_SURFACE, EGL_FALSE);
     if (d->dpy != dpy)
         return setError(EGL_BAD_DISPLAY, EGL_FALSE);
 
@@ -2073,6 +2103,8 @@
         return setError(EGL_BAD_DISPLAY, EGL_FALSE);
 
     egl_surface_t* d = static_cast<egl_surface_t*>(draw);
+    if (!d->isValid())
+        return setError(EGL_BAD_SURFACE, EGL_FALSE);
     if (d->dpy != dpy)
         return setError(EGL_BAD_DISPLAY, EGL_FALSE);
 
@@ -2088,6 +2120,8 @@
         return setError(EGL_BAD_DISPLAY, (EGLClientBuffer)0);
 
     egl_surface_t* d = static_cast<egl_surface_t*>(draw);
+    if (!d->isValid())
+        return setError(EGL_BAD_SURFACE, (EGLClientBuffer)0);
     if (d->dpy != dpy)
         return setError(EGL_BAD_DISPLAY, (EGLClientBuffer)0);
 
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/Loader.cpp b/opengl/libs/EGL/Loader.cpp
index 445e681..d51b333 100644
--- a/opengl/libs/EGL/Loader.cpp
+++ b/opengl/libs/EGL/Loader.cpp
@@ -224,12 +224,12 @@
 
 void *Loader::load_driver(const char* driver, gl_hooks_t* hooks, uint32_t mask)
 {
-    //LOGD("%s", driver);
     void* dso = dlopen(driver, RTLD_NOW | RTLD_LOCAL);
-    LOGE_IF(!dso, "%s", dlerror());
     if (dso == 0)
         return 0;
 
+    LOGD("loaded %s", driver);
+
     if (mask & EGL) {
         getProcAddress = (getProcAddressType)dlsym(dso, "eglGetProcAddress");
 
diff --git a/opengl/libs/EGL/egl.cpp b/opengl/libs/EGL/egl.cpp
index 64b82eb..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"
@@ -50,7 +52,7 @@
 #define VERSION_MAJOR 1
 #define VERSION_MINOR 4
 static char const * const gVendorString     = "Android";
-static char const * const gVersionString    = "1.31 Android META-EGL";
+static char const * const gVersionString    = "1.4 Android META-EGL";
 static char const * const gClientApiString  = "OpenGL ES";
 static char const * const gExtensionString  = 
         "EGL_KHR_image "
@@ -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;
 }
@@ -326,32 +418,6 @@
 
 // ----------------------------------------------------------------------------
 
-/*
- * To "loose" the GPU, use something like
- *    gEGLImpl[IMPL_HARDWARE].hooks = &gHooks[IMPL_CONTEXT_LOST];
- * 
- */
-
-static int gl_context_lost() {
-    setGlThreadSpecific(&gHooks[IMPL_CONTEXT_LOST]);
-    return 0;
-}
-static int egl_context_lost() {
-    setGlThreadSpecific(&gHooks[IMPL_CONTEXT_LOST]);
-    return EGL_FALSE;
-}
-static EGLBoolean egl_context_lost_swap_buffers(void*, void*) {
-    usleep(100000); // don't use all the CPU
-    setGlThreadSpecific(&gHooks[IMPL_CONTEXT_LOST]);
-    return EGL_FALSE;
-}
-static GLint egl_context_lost_get_error() {
-    return EGL_CONTEXT_LOST;
-}
-static int ext_context_lost() {
-    return 0;
-}
-
 static void gl_no_context() {
     tls_t* tls = getTLS();
     if (tls->logCallWithNoContext == EGL_TRUE) {
@@ -417,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];
@@ -431,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;
 }
@@ -444,114 +508,106 @@
 {
     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];
 }
 
+// ----------------------------------------------------------------------------
 
-EGLDisplay egl_init_displays(NativeDisplayType display)
+// this mutex protects:
+//    d->disp[]
+//    egl_init_drivers_locked()
+//
+static pthread_mutex_t gInitDriverMutex = PTHREAD_MUTEX_INITIALIZER;
+
+EGLBoolean egl_init_drivers_locked()
 {
     if (sEarlyInitState) {
-        return EGL_NO_DISPLAY;
+        // initialized by static ctor. should be set here.
+        return EGL_FALSE;
     }
 
-    uint32_t index = uint32_t(display);
-    if (index >= NUM_DISPLAYS) {
-        return EGL_NO_DISPLAY;
-    }
-    
-    EGLDisplay dpy = EGLDisplay(uintptr_t(display) + 1LU);
-    egl_display_t* d = &gDisplay[index];
-
     // get our driver loader
-    Loader& loader(Loader::getInstance());    
+    Loader& loader(Loader::getInstance());
     
-    // dynamically load all our EGL implementations for that display
-    // and call into the real eglGetGisplay()
-    egl_connection_t* cnx = &gEGLImpl[IMPL_SOFTWARE];
+    // dynamically load all our EGL implementations for all displays
+    // and retrieve the corresponding EGLDisplay
+    // if that fails, don't use this driver.
+    // TODO: currently we only deal with EGL_DEFAULT_DISPLAY
+    egl_connection_t* cnx;
+    egl_display_t* d = &gDisplay[0];
+
+    cnx = &gEGLImpl[IMPL_SOFTWARE];
     if (cnx->dso == 0) {
         cnx->hooks = &gHooks[IMPL_SOFTWARE];
-        cnx->dso = loader.open(display, 0, cnx->hooks);
-    }
-    if (cnx->dso && d->dpys[IMPL_SOFTWARE]==EGL_NO_DISPLAY) {
-        d->dpys[IMPL_SOFTWARE] = cnx->hooks->egl.eglGetDisplay(display);
-        LOGE_IF(d->dpys[IMPL_SOFTWARE]==EGL_NO_DISPLAY,
-                "No EGLDisplay for software EGL!");
+        cnx->dso = loader.open(EGL_DEFAULT_DISPLAY, 0, cnx->hooks);
+        if (cnx->dso) {
+            EGLDisplay dpy = cnx->hooks->egl.eglGetDisplay(EGL_DEFAULT_DISPLAY);
+            LOGE_IF(dpy==EGL_NO_DISPLAY, "No EGLDisplay for software EGL!");
+            d->disp[IMPL_SOFTWARE].dpy = dpy; 
+            if (dpy == EGL_NO_DISPLAY) {
+                loader.close(cnx->dso);
+                cnx->dso = NULL;
+            }
+        }
     }
 
     cnx = &gEGLImpl[IMPL_HARDWARE];
-    if (cnx->dso == 0 && cnx->unavailable == 0) {
+    if (cnx->dso == 0) {
         char value[PROPERTY_VALUE_MAX];
         property_get("debug.egl.hw", value, "1");
         if (atoi(value) != 0) {
             cnx->hooks = &gHooks[IMPL_HARDWARE];
-            cnx->dso = loader.open(display, 1, cnx->hooks);
+            cnx->dso = loader.open(EGL_DEFAULT_DISPLAY, 1, cnx->hooks);
+            if (cnx->dso) {
+                EGLDisplay dpy = cnx->hooks->egl.eglGetDisplay(EGL_DEFAULT_DISPLAY);
+                LOGE_IF(dpy==EGL_NO_DISPLAY, "No EGLDisplay for hardware EGL!");
+                d->disp[IMPL_HARDWARE].dpy = dpy; 
+                if (dpy == EGL_NO_DISPLAY) {
+                    loader.close(cnx->dso);
+                    cnx->dso = NULL;
+                }
+            }
         } else {
             LOGD("3D hardware acceleration is disabled");
         }
     }
-    if (cnx->dso && d->dpys[IMPL_HARDWARE]==EGL_NO_DISPLAY) {
-        android_memset32(
-                (uint32_t*)(void*)&gHooks[IMPL_CONTEXT_LOST].gl,
-                (uint32_t)((void*)gl_context_lost),
-                sizeof(gHooks[IMPL_CONTEXT_LOST].gl));
-        android_memset32(
-                (uint32_t*)(void*)&gHooks[IMPL_CONTEXT_LOST].egl,
-                (uint32_t)((void*)egl_context_lost),
-                sizeof(gHooks[IMPL_CONTEXT_LOST].egl));
-        android_memset32(
-                (uint32_t*)(void*)&gHooks[IMPL_CONTEXT_LOST].ext,
-                (uint32_t)((void*)ext_context_lost),
-                sizeof(gHooks[IMPL_CONTEXT_LOST].ext));
 
-        gHooks[IMPL_CONTEXT_LOST].egl.eglSwapBuffers =
-                egl_context_lost_swap_buffers;
-        
-        gHooks[IMPL_CONTEXT_LOST].egl.eglGetError =
-                egl_context_lost_get_error;
-
-        gHooks[IMPL_CONTEXT_LOST].egl.eglTerminate =
-                gHooks[IMPL_HARDWARE].egl.eglTerminate;
-        
-        d->dpys[IMPL_HARDWARE] = cnx->hooks->egl.eglGetDisplay(display);
-        if (d->dpys[IMPL_HARDWARE] == EGL_NO_DISPLAY) {
-            LOGE("h/w accelerated eglGetDisplay() failed (%s)",
-                    egl_strerror(cnx->hooks->egl.eglGetError()));
-            
-            loader.close(cnx->dso);
-            cnx->dso = 0;
-            // in case of failure, we want to make sure we don't try again
-            // as it's expensive.
-            cnx->unavailable = 1;
-        }
+    if (!gEGLImpl[IMPL_SOFTWARE].dso && !gEGLImpl[IMPL_HARDWARE].dso) {
+        return EGL_FALSE;
     }
 
-    return dpy;
+    return EGL_TRUE;
 }
 
+EGLBoolean egl_init_drivers()
+{
+    EGLBoolean res;
+    pthread_mutex_lock(&gInitDriverMutex);
+    res = egl_init_drivers_locked();
+    pthread_mutex_unlock(&gInitDriverMutex);
+    return res;
+}
 
 // ----------------------------------------------------------------------------
 }; // namespace android
@@ -561,7 +617,17 @@
 
 EGLDisplay eglGetDisplay(NativeDisplayType display)
 {
-    return egl_init_displays(display);
+    uint32_t index = uint32_t(display);
+    if (index >= NUM_DISPLAYS) {
+        return setError(EGL_BAD_PARAMETER, EGL_NO_DISPLAY);
+    }
+
+    if (egl_init_drivers() == EGL_FALSE) {
+        return setError(EGL_BAD_PARAMETER, EGL_NO_DISPLAY);
+    }
+    
+    EGLDisplay dpy = EGLDisplay(uintptr_t(display) + 1LU);
+    return dpy;
 }
 
 // ----------------------------------------------------------------------------
@@ -584,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;
@@ -592,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()));
         }
     }
 
@@ -619,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;
@@ -648,36 +732,36 @@
 
 EGLBoolean eglTerminate(EGLDisplay dpy)
 {
+    // NOTE: don't unload the drivers b/c some APIs can be called
+    // after eglTerminate() has been called. eglTerminate() only
+    // terminates an EGLDisplay, not a EGL itself.
+
     egl_display_t* const dp = get_display(dpy);
     if (!dp) return setError(EGL_BAD_DISPLAY, EGL_FALSE);
     if (android_atomic_dec(&dp->refs) != 1)
         return EGL_TRUE;
-        
-    Loader& loader(Loader::getInstance());    
 
     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]);
-            
-            /* REVISIT: it's unclear what to do if eglTerminate() fails,
-             * on one end we shouldn't care, on the other end if it fails
-             * it might not be safe to call dlclose() (there could be some
-             * threads around). */
-            
-            free(dp->configs[i]);
-            free((void*)dp->queryString[i].extensions);
-            dp->numConfigs[i] = 0;
-            dp->dpys[i] = EGL_NO_DISPLAY;
+        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->disp[i].config);
 
-            loader.close(cnx->dso);
-            cnx->dso = 0;
+            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;
@@ -701,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++;
@@ -758,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
@@ -773,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).
@@ -792,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);
@@ -833,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);
 }
 
 // ----------------------------------------------------------------------------
@@ -849,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;
@@ -867,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;
@@ -884,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;
@@ -895,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);
 }
 
 // ----------------------------------------------------------------------------
@@ -931,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;
@@ -942,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;
 }
@@ -1010,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;    
     
@@ -1017,17 +1172,23 @@
     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)
 {
+    // could be called before eglInitialize(), but we wouldn't have a context
+    // then, and this function would correctly return EGL_NO_CONTEXT.
+
     EGLContext ctx = getContext();
     return ctx;
 }
 
 EGLSurface eglGetCurrentSurface(EGLint readdraw)
 {
+    // could be called before eglInitialize(), but we wouldn't have a context
+    // then, and this function would correctly return EGL_NO_SURFACE.
+
     EGLContext ctx = getContext();
     if (ctx) {
         egl_context_t const * const c = get_context(ctx);
@@ -1043,6 +1204,9 @@
 
 EGLDisplay eglGetCurrentDisplay(void)
 {
+    // could be called before eglInitialize(), but we wouldn't have a context
+    // then, and this function would correctly return EGL_NO_DISPLAY.
+
     EGLContext ctx = getContext();
     if (ctx) {
         egl_context_t const * const c = get_context(ctx);
@@ -1054,6 +1218,9 @@
 
 EGLBoolean eglWaitGL(void)
 {
+    // could be called before eglInitialize(), but we wouldn't have a context
+    // then, and this function would return GL_TRUE, which isn't wrong.
+
     EGLBoolean res = EGL_TRUE;
     EGLContext ctx = getContext();
     if (ctx) {
@@ -1071,6 +1238,9 @@
 
 EGLBoolean eglWaitNative(EGLint engine)
 {
+    // could be called before eglInitialize(), but we wouldn't have a context
+    // then, and this function would return GL_TRUE, which isn't wrong.
+    
     EGLBoolean res = EGL_TRUE;
     EGLContext ctx = getContext();
     if (ctx) {
@@ -1107,9 +1277,11 @@
     // eglGetProcAddress() could be the very first function called
     // in which case we must make sure we've initialized ourselves, this
     // happens the first time egl_get_display() is called.
-    
-    if (egl_init_displays(EGL_DEFAULT_DISPLAY) == EGL_NO_DISPLAY)
-        return NULL;
+
+    if (egl_init_drivers() == EGL_FALSE) {
+        setError(EGL_BAD_PARAMETER, NULL);
+        return  NULL;
+    }
 
     __eglMustCastToProperFunctionPointerType addr;
     addr = findProcAddress(procname, gExtentionMap, NELEM(gExtentionMap));
@@ -1168,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)
@@ -1210,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);
 }
@@ -1224,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);
 }
@@ -1238,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);
 }
@@ -1259,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;
                 }
             }
@@ -1275,6 +1463,8 @@
 
 EGLBoolean eglWaitClient(void)
 {
+    // could be called before eglInitialize(), but we wouldn't have a context
+    // then, and this function would return GL_TRUE, which isn't wrong.
     EGLBoolean res = EGL_TRUE;
     EGLContext ctx = getContext();
     if (ctx) {
@@ -1296,6 +1486,10 @@
 
 EGLBoolean eglBindAPI(EGLenum api)
 {
+    if (egl_init_drivers() == EGL_FALSE) {
+        return setError(EGL_BAD_PARAMETER, EGL_FALSE);
+    }
+
     // bind this API on all EGLs
     EGLBoolean res = EGL_TRUE;
     for (int i=0 ; i<IMPL_NUM_DRIVERS_IMPLEMENTATIONS ; i++) {
@@ -1313,6 +1507,10 @@
 
 EGLenum eglQueryAPI(void)
 {
+    if (egl_init_drivers() == EGL_FALSE) {
+        return setError(EGL_BAD_PARAMETER, EGL_FALSE);
+    }
+
     for (int i=0 ; i<IMPL_NUM_DRIVERS_IMPLEMENTATIONS ; i++) {
         egl_connection_t* const cnx = &gEGLImpl[i];
         if (cnx->dso) {
@@ -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);
 }
diff --git a/opengl/libs/egl_impl.h b/opengl/libs/egl_impl.h
index c5f753d..ac286cb 100644
--- a/opengl/libs/egl_impl.h
+++ b/opengl/libs/egl_impl.h
@@ -35,7 +35,6 @@
     gl_hooks_t *        hooks;
     EGLint              major;
     EGLint              minor;
-    int                 unavailable;
 };
 
 EGLAPI EGLImageKHR egl_get_image_for_current_context(EGLImageKHR image);
diff --git a/opengl/libs/hooks.h b/opengl/libs/hooks.h
index 37292ee..8c0357e 100644
--- a/opengl/libs/hooks.h
+++ b/opengl/libs/hooks.h
@@ -60,12 +60,8 @@
 enum {
     IMPL_HARDWARE = 0,
     IMPL_SOFTWARE,
-    
     IMPL_NUM_DRIVERS_IMPLEMENTATIONS,
-
-    IMPL_CONTEXT_LOST = IMPL_NUM_DRIVERS_IMPLEMENTATIONS,
-    IMPL_NO_CONTEXT,
-    
+    IMPL_NO_CONTEXT = IMPL_NUM_DRIVERS_IMPLEMENTATIONS,
     IMPL_NUM_IMPLEMENTATIONS
 };