am afcd516e: Merge change Iaae72f66 into eclair-sdk

Merge commit 'afcd516e3e6378aaf97ff44b0b9ea233223ded65' into eclair

* commit 'afcd516e3e6378aaf97ff44b0b9ea233223ded65':
  docs: misc edits to samples page and intro docs
diff --git a/camera/libcameraservice/CameraService.cpp b/camera/libcameraservice/CameraService.cpp
index b63e97f..df59dcf 100644
--- a/camera/libcameraservice/CameraService.cpp
+++ b/camera/libcameraservice/CameraService.cpp
@@ -309,7 +309,7 @@
             oldClient = mCameraClient;
 
             // did the client actually change?
-            if (client->asBinder() == mCameraClient->asBinder()) {
+            if ((mCameraClient != NULL) && (client->asBinder() == mCameraClient->asBinder())) {
                 LOGD("Connect to the same client");
                 return NO_ERROR;
             }
@@ -683,22 +683,30 @@
 {
     LOGD("stopPreview (pid %d)", getCallingPid());
 
-    Mutex::Autolock lock(mLock);
-    if (checkPid() != NO_ERROR) return;
+    // hold main lock during state transition
+    {
+        Mutex::Autolock lock(mLock);
+        if (checkPid() != NO_ERROR) return;
 
-    if (mHardware == 0) {
-        LOGE("mHardware is NULL, returning.");
-        return;
+        if (mHardware == 0) {
+            LOGE("mHardware is NULL, returning.");
+            return;
+        }
+
+        mHardware->stopPreview();
+        mHardware->disableMsgType(CAMERA_MSG_PREVIEW_FRAME);
+        LOGD("stopPreview(), hardware stopped OK");
+
+        if (mSurface != 0 && !mUseOverlay) {
+            mSurface->unregisterBuffers();
+        }
     }
 
-    mHardware->stopPreview();
-    mHardware->disableMsgType(CAMERA_MSG_PREVIEW_FRAME);
-    LOGD("stopPreview(), hardware stopped OK");
-
-    if (mSurface != 0 && !mUseOverlay) {
-        mSurface->unregisterBuffers();
+    // hold preview buffer lock
+    {
+        Mutex::Autolock lock(mPreviewLock);
+        mPreviewBuffer.clear();
     }
-    mPreviewBuffer.clear();
 }
 
 // stop recording mode
@@ -706,24 +714,31 @@
 {
     LOGD("stopRecording (pid %d)", getCallingPid());
 
-    Mutex::Autolock lock(mLock);
-    if (checkPid() != NO_ERROR) return;
+    // hold main lock during state transition
+    {
+        Mutex::Autolock lock(mLock);
+        if (checkPid() != NO_ERROR) return;
 
-    if (mHardware == 0) {
-        LOGE("mHardware is NULL, returning.");
-        return;
+        if (mHardware == 0) {
+            LOGE("mHardware is NULL, returning.");
+            return;
+        }
+
+        if (mMediaPlayerBeep.get() != NULL) {
+            mMediaPlayerBeep->seekTo(0);
+            mMediaPlayerBeep->start();
+        }
+
+        mHardware->stopRecording();
+        mHardware->disableMsgType(CAMERA_MSG_VIDEO_FRAME);
+        LOGD("stopRecording(), hardware stopped OK");
     }
 
-    if (mMediaPlayerBeep.get() != NULL) {
-        mMediaPlayerBeep->seekTo(0);
-        mMediaPlayerBeep->start();
+    // hold preview buffer lock
+    {
+        Mutex::Autolock lock(mPreviewLock);
+        mPreviewBuffer.clear();
     }
-
-    mHardware->stopRecording();
-    mHardware->disableMsgType(CAMERA_MSG_VIDEO_FRAME);
-    LOGD("stopRecording(), hardware stopped OK");
-
-    mPreviewBuffer.clear();
 }
 
 // release a recording frame
@@ -865,7 +880,11 @@
 }
 
 // snapshot taken
-void CameraService::Client::handleShutter()
+void CameraService::Client::handleShutter(
+    image_rect_type *size // The width and height of yuv picture for
+                          // registerBuffer. If this is NULL, use the picture
+                          // size from parameters.
+)
 {
     // Play shutter sound.
     if (mMediaPlayerClick.get() != NULL) {
@@ -878,7 +897,10 @@
         mSurface->unregisterBuffers();
     }
 
-    mCameraClient->notifyCallback(CAMERA_MSG_SHUTTER, 0, 0);
+    sp<ICameraClient> c = mCameraClient;
+    if (c != NULL) {
+        c->notifyCallback(CAMERA_MSG_SHUTTER, 0, 0);
+    }
     mHardware->disableMsgType(CAMERA_MSG_SHUTTER);
 
     // It takes some time before yuvPicture callback to be called.
@@ -886,12 +908,21 @@
     if (mSurface != 0 && !mUseOverlay) {
         int w, h;
         CameraParameters params(mHardware->getParameters());
-        params.getPictureSize(&w, &h);
         uint32_t transform = 0;
         if (params.getOrientation() == CameraParameters::CAMERA_ORIENTATION_PORTRAIT) {
             LOGV("portrait mode");
             transform = ISurface::BufferHeap::ROT_90;
         }
+
+        if (size == NULL) {
+            params.getPictureSize(&w, &h);
+        } else {
+            w = size->width;
+            h = size->height;
+            w &= ~1;
+            h &= ~1;
+            LOGD("Snapshot image width=%d, height=%d", w, h);
+        }
         ISurface::BufferHeap buffers(w, h, w, h,
             PIXEL_FORMAT_YCbCr_420_SP, transform, 0, mHardware->getRawHeap());
 
@@ -932,31 +963,38 @@
         }
     }
 
-    // Is the callback enabled or not?
-    if (!(mPreviewCallbackFlag & FRAME_CALLBACK_FLAG_ENABLE_MASK)) {
+    // local copy of the callback flags
+    int flags = mPreviewCallbackFlag;
+
+    // is callback enabled?
+    if (!(flags & FRAME_CALLBACK_FLAG_ENABLE_MASK)) {
         // If the enable bit is off, the copy-out and one-shot bits are ignored
         LOGV("frame callback is diabled");
         return;
     }
 
-    // Is the received frame copied out or not?
-    if (mPreviewCallbackFlag & FRAME_CALLBACK_FLAG_COPY_OUT_MASK) {
-        LOGV("frame is copied out");
-        copyFrameAndPostCopiedFrame(heap, offset, size);
-    } else {
-        LOGV("frame is directly sent out without copying");
-        mCameraClient->dataCallback(CAMERA_MSG_PREVIEW_FRAME, mem);
-    }
+    // hold a strong pointer to the client
+    sp<ICameraClient> c = mCameraClient;
 
-    // Is this is one-shot only?
-    if (mPreviewCallbackFlag & FRAME_CALLBACK_FLAG_ONE_SHOT_MASK) {
-        LOGV("One-shot only, thus clear the bits and disable frame callback");
+    // clear callback flags if no client or one-shot mode
+    if ((c == NULL) || (mPreviewCallbackFlag & FRAME_CALLBACK_FLAG_ONE_SHOT_MASK)) {
+        LOGV("Disable preview callback");
         mPreviewCallbackFlag &= ~(FRAME_CALLBACK_FLAG_ONE_SHOT_MASK |
                                 FRAME_CALLBACK_FLAG_COPY_OUT_MASK |
                                 FRAME_CALLBACK_FLAG_ENABLE_MASK);
+        // TODO: Shouldn't we use this API for non-overlay hardware as well?
         if (mUseOverlay)
             mHardware->disableMsgType(CAMERA_MSG_PREVIEW_FRAME);
     }
+
+    // Is the received frame copied out or not?
+    if (flags & FRAME_CALLBACK_FLAG_COPY_OUT_MASK) {
+        LOGV("frame is copied");
+        copyFrameAndPostCopiedFrame(c, heap, offset, size);
+    } else {
+        LOGV("frame is forwarded");
+        c->dataCallback(CAMERA_MSG_PREVIEW_FRAME, mem);
+    }
 }
 
 // picture callback - postview image ready
@@ -972,7 +1010,10 @@
     }
 #endif
 
-    mCameraClient->dataCallback(CAMERA_MSG_POSTVIEW_FRAME, mem);
+    sp<ICameraClient> c = mCameraClient;
+    if (c != NULL) {
+        c->dataCallback(CAMERA_MSG_POSTVIEW_FRAME, mem);
+    }
     mHardware->disableMsgType(CAMERA_MSG_POSTVIEW_FRAME);
 }
 
@@ -997,7 +1038,10 @@
         mSurface->postBuffer(offset);
     }
 
-    mCameraClient->dataCallback(CAMERA_MSG_RAW_IMAGE, mem);
+    sp<ICameraClient> c = mCameraClient;
+    if (c != NULL) {
+        c->dataCallback(CAMERA_MSG_RAW_IMAGE, mem);
+    }
     mHardware->disableMsgType(CAMERA_MSG_RAW_IMAGE);
 }
 
@@ -1014,7 +1058,10 @@
     }
 #endif
 
-    mCameraClient->dataCallback(CAMERA_MSG_COMPRESSED_IMAGE, mem);
+    sp<ICameraClient> c = mCameraClient;
+    if (c != NULL) {
+        c->dataCallback(CAMERA_MSG_COMPRESSED_IMAGE, mem);
+    }
     mHardware->disableMsgType(CAMERA_MSG_COMPRESSED_IMAGE);
 }
 
@@ -1029,10 +1076,14 @@
 
     switch (msgType) {
         case CAMERA_MSG_SHUTTER:
-            client->handleShutter();
+            // ext1 is the dimension of the yuv picture.
+            client->handleShutter((image_rect_type *)ext1);
             break;
         default:
-            client->mCameraClient->notifyCallback(msgType, ext1, ext2);
+            sp<ICameraClient> c = client->mCameraClient;
+            if (c != NULL) {
+                c->notifyCallback(msgType, ext1, ext2);
+            }
             break;
     }
 
@@ -1053,10 +1104,13 @@
         return;
     }
 
+    sp<ICameraClient> c = client->mCameraClient;
     if (dataPtr == NULL) {
         LOGE("Null data returned in data callback");
-        client->mCameraClient->notifyCallback(CAMERA_MSG_ERROR, UNKNOWN_ERROR, 0);
-        client->mCameraClient->dataCallback(msgType, NULL);
+        if (c != NULL) {
+            c->notifyCallback(CAMERA_MSG_ERROR, UNKNOWN_ERROR, 0);
+            c->dataCallback(msgType, NULL);
+        }
         return;
     }
 
@@ -1074,7 +1128,9 @@
             client->handleCompressedPicture(dataPtr);
             break;
         default:
-            client->mCameraClient->dataCallback(msgType, dataPtr);
+            if (c != NULL) {
+                c->dataCallback(msgType, dataPtr);
+            }
             break;
     }
 
@@ -1095,15 +1151,20 @@
     if (client == 0) {
         return;
     }
+    sp<ICameraClient> c = client->mCameraClient;
 
     if (dataPtr == NULL) {
         LOGE("Null data returned in data with timestamp callback");
-        client->mCameraClient->notifyCallback(CAMERA_MSG_ERROR, UNKNOWN_ERROR, 0);
-        client->mCameraClient->dataCallbackTimestamp(0, msgType, NULL);
+        if (c != NULL) {
+            c->notifyCallback(CAMERA_MSG_ERROR, UNKNOWN_ERROR, 0);
+            c->dataCallbackTimestamp(0, msgType, NULL);
+        }
         return;
     }
 
-    client->mCameraClient->dataCallbackTimestamp(timestamp, msgType, dataPtr);
+    if (c != NULL) {
+        c->dataCallbackTimestamp(timestamp, msgType, dataPtr);
+    }
 
 #if DEBUG_CLIENT_REFERENCES
     if (client->getStrongCount() == 1) {
@@ -1161,32 +1222,40 @@
     return mHardware->sendCommand(cmd, arg1, arg2);
 }
 
-void CameraService::Client::copyFrameAndPostCopiedFrame(sp<IMemoryHeap> heap, size_t offset, size_t size)
+void CameraService::Client::copyFrameAndPostCopiedFrame(const sp<ICameraClient>& client,
+        const sp<IMemoryHeap>& heap, size_t offset, size_t size)
 {
     LOGV("copyFrameAndPostCopiedFrame");
     // It is necessary to copy out of pmem before sending this to
     // the callback. For efficiency, reuse the same MemoryHeapBase
     // provided it's big enough. Don't allocate the memory or
     // perform the copy if there's no callback.
-    if (mPreviewBuffer == 0) {
-        mPreviewBuffer = new MemoryHeapBase(size, 0, NULL);
-    } else if (size > mPreviewBuffer->virtualSize()) {
-        mPreviewBuffer.clear();
-        mPreviewBuffer = new MemoryHeapBase(size, 0, NULL);
+
+    // hold the preview lock while we grab a reference to the preview buffer
+    sp<MemoryHeapBase> previewBuffer;
+    {
+        Mutex::Autolock lock(mPreviewLock);
+        if (mPreviewBuffer == 0) {
+            mPreviewBuffer = new MemoryHeapBase(size, 0, NULL);
+        } else if (size > mPreviewBuffer->virtualSize()) {
+            mPreviewBuffer.clear();
+            mPreviewBuffer = new MemoryHeapBase(size, 0, NULL);
+        }
         if (mPreviewBuffer == 0) {
             LOGE("failed to allocate space for preview buffer");
             return;
         }
+        previewBuffer = mPreviewBuffer;
     }
-    memcpy(mPreviewBuffer->base(),
+    memcpy(previewBuffer->base(),
            (uint8_t *)heap->base() + offset, size);
 
-    sp<MemoryBase> frame = new MemoryBase(mPreviewBuffer, 0, size);
+    sp<MemoryBase> frame = new MemoryBase(previewBuffer, 0, size);
     if (frame == 0) {
         LOGE("failed to allocate space for frame callback");
         return;
     }
-    mCameraClient->dataCallback(CAMERA_MSG_PREVIEW_FRAME, frame);
+    client->dataCallback(CAMERA_MSG_PREVIEW_FRAME, frame);
 }
 
 status_t CameraService::dump(int fd, const Vector<String16>& args)
diff --git a/camera/libcameraservice/CameraService.h b/camera/libcameraservice/CameraService.h
index 2e3597f..3e3e54f 100644
--- a/camera/libcameraservice/CameraService.h
+++ b/camera/libcameraservice/CameraService.h
@@ -23,10 +23,9 @@
 #include <ui/CameraHardwareInterface.h>
 #include <ui/Camera.h>
 
-class android::MemoryHeapBase;
-
 namespace android {
 
+class MemoryHeapBase;
 class MediaPlayer;
 
 // ----------------------------------------------------------------------------
@@ -146,12 +145,13 @@
         static      sp<Client>  getClientFromCookie(void* user);
 
                     void        handlePreviewData(const sp<IMemory>&);
-                    void        handleShutter();
+                    void        handleShutter(image_rect_type *image);
                     void        handlePostview(const sp<IMemory>&);
                     void        handleRawPicture(const sp<IMemory>&);
                     void        handleCompressedPicture(const sp<IMemory>&);
 
-                    void        copyFrameAndPostCopiedFrame(sp<IMemoryHeap> heap, size_t offset, size_t size);
+                    void        copyFrameAndPostCopiedFrame(const sp<ICameraClient>& client,
+                                    const sp<IMemoryHeap>& heap, size_t offset, size_t size);
 
         // camera operation mode
         enum camera_mode {
@@ -181,7 +181,6 @@
         mutable     Condition                   mReady;
                     sp<CameraService>           mCameraService;
                     sp<ISurface>                mSurface;
-                    sp<MemoryHeapBase>          mPreviewBuffer;
                     int                         mPreviewCallbackFlag;
 
                     sp<MediaPlayer>             mMediaPlayerClick;
@@ -197,6 +196,9 @@
                     sp<OverlayRef>              mOverlayRef;
                     int                         mOverlayW;
                     int                         mOverlayH;
+
+        mutable     Mutex                       mPreviewLock;
+                    sp<MemoryHeapBase>          mPreviewBuffer;
     };
 
 // ----------------------------------------------------------------------------
diff --git a/include/binder/MemoryHeapBase.h b/include/binder/MemoryHeapBase.h
index 435540e..d793c24 100644
--- a/include/binder/MemoryHeapBase.h
+++ b/include/binder/MemoryHeapBase.h
@@ -35,7 +35,8 @@
         MAP_ONCE = IMemoryHeap::MAP_ONCE,
         // memory won't be mapped locally, but will be mapped in the remote
         // process.
-        DONT_MAP_LOCALLY = 0x00000100
+        DONT_MAP_LOCALLY = 0x00000100,
+        NO_CACHING = 0x00000200
     };
 
     /* 
diff --git a/include/private/opengles/gl_context.h b/include/private/opengles/gl_context.h
index 67c2dd8..26cde38 100644
--- a/include/private/opengles/gl_context.h
+++ b/include/private/opengles/gl_context.h
@@ -32,6 +32,8 @@
 #include <GLES/gl.h>
 #include <GLES/glext.h>
 
+struct android_native_buffer_t;
+
 namespace android {
 
 const unsigned int OGLES_NUM_COMPRESSED_TEXTURE_FORMATS = 10;
@@ -602,7 +604,7 @@
     copybit_device_t*       blitEngine;
     int32_t                 minScale;
     int32_t                 maxScale;
-    buffer_handle_t         drawSurfaceBuffer;
+    android_native_buffer_t* drawSurfaceBuffer;
 };
 
 struct ogles_context_t {
diff --git a/include/private/ui/RegionHelper.h b/include/private/ui/RegionHelper.h
index 926fddb..8d76533 100644
--- a/include/private/ui/RegionHelper.h
+++ b/include/private/ui/RegionHelper.h
@@ -86,7 +86,7 @@
                         rasterizer(current);
                     }
                 }
-            } while(!spannerInner.isDone());            
+            } while(!spannerInner.isDone());
         } while(!spanner.isDone());
     }
 
@@ -220,18 +220,21 @@
         }
 
         inline void prepare(int inside) {
-            SpannerBase::lhs_head = lhs.rects->left  + lhs.dx;
-            SpannerBase::lhs_tail = lhs.rects->right + lhs.dx;
-            SpannerBase::rhs_head = rhs.rects->left  + rhs.dx;
-            SpannerBase::rhs_tail = rhs.rects->right + rhs.dx;
             if (inside == SpannerBase::lhs_before_rhs) {
+                SpannerBase::lhs_head = lhs.rects->left  + lhs.dx;
+                SpannerBase::lhs_tail = lhs.rects->right + lhs.dx;
                 SpannerBase::rhs_head = max_value;
                 SpannerBase::rhs_tail = max_value;
             } else if (inside == SpannerBase::lhs_after_rhs) {
                 SpannerBase::lhs_head = max_value;
                 SpannerBase::lhs_tail = max_value;
+                SpannerBase::rhs_head = rhs.rects->left  + rhs.dx;
+                SpannerBase::rhs_tail = rhs.rects->right + rhs.dx;
             } else {
-                // use both spans
+                SpannerBase::lhs_head = lhs.rects->left  + lhs.dx;
+                SpannerBase::lhs_tail = lhs.rects->right + lhs.dx;
+                SpannerBase::rhs_head = rhs.rects->left  + rhs.dx;
+                SpannerBase::rhs_tail = rhs.rects->right + rhs.dx;
             }
         }
 
diff --git a/include/ui/CameraHardwareInterface.h b/include/ui/CameraHardwareInterface.h
index af40f31..240c134 100644
--- a/include/ui/CameraHardwareInterface.h
+++ b/include/ui/CameraHardwareInterface.h
@@ -25,6 +25,15 @@
 #include <ui/Overlay.h>
 
 namespace android {
+/**
+ *  The size of image for display.
+ */
+typedef struct image_rect_struct
+{
+  uint32_t width;      /* Image width */
+  uint32_t height;     /* Image height */
+} image_rect_type;
+
 
 typedef void (*notify_callback)(int32_t msgType,
                                 int32_t ext1,
diff --git a/include/ui/GraphicBuffer.h b/include/ui/GraphicBuffer.h
index 8897f03..b9c491b 100644
--- a/include/ui/GraphicBuffer.h
+++ b/include/ui/GraphicBuffer.h
@@ -66,7 +66,11 @@
     GraphicBuffer();
 
     // creates w * h buffer
-    GraphicBuffer(uint32_t w, uint32_t h, PixelFormat format, uint32_t ssage);
+    GraphicBuffer(uint32_t w, uint32_t h, PixelFormat format, uint32_t usage);
+
+    // create a buffer from an existing handle
+    GraphicBuffer(uint32_t w, uint32_t h, PixelFormat format, uint32_t usage,
+            uint32_t stride, native_handle_t* handle, bool keepOwnership);
 
     // return status
     status_t initCheck() const;
@@ -89,14 +93,22 @@
     
     void setIndex(int index);
     int getIndex() const;
+    void setVerticalStride(uint32_t vstride);
+    uint32_t getVerticalStride() const;
 
 protected:
     GraphicBuffer(const Parcel& reply);
     virtual ~GraphicBuffer();
 
+    enum {
+        ownNone   = 0,
+        ownHandle = 1,
+        ownData   = 2,
+    };
+
     inline const GraphicBufferMapper& getBufferMapper() const { return mBufferMapper; }
     inline GraphicBufferMapper& getBufferMapper() { return mBufferMapper; }
-    bool mOwner;
+    uint8_t mOwner;
 
 private:
     friend class Surface;
diff --git a/include/ui/Surface.h b/include/ui/Surface.h
index 70303cd..008c297 100644
--- a/include/ui/Surface.h
+++ b/include/ui/Surface.h
@@ -109,7 +109,7 @@
 
     ~SurfaceControl();
 
-    status_t validate(SharedClient const* cblk) const;
+    status_t validate() const;
     void destroy();
     
     sp<SurfaceComposerClient>   mClient;
@@ -190,7 +190,7 @@
 
     status_t getBufferLocked(int index, int usage);
    
-           status_t validate(SharedClient const* cblk) const;
+           status_t validate() const;
 
     inline const GraphicBufferMapper& getBufferMapper() const { return mBufferMapper; }
     inline GraphicBufferMapper& getBufferMapper() { return mBufferMapper; }
diff --git a/include/utils/ResourceTypes.h b/include/utils/ResourceTypes.h
index 17ccad6..49145e8 100644
--- a/include/utils/ResourceTypes.h
+++ b/include/utils/ResourceTypes.h
@@ -1272,7 +1272,7 @@
 
             if (version || o.version) {
                 if ((sdkVersion != o.sdkVersion) && requested->sdkVersion) {
-                    return (sdkVersion);
+                    return (sdkVersion > o.sdkVersion);
                 }
 
                 if ((minorVersion != o.minorVersion) &&
@@ -1384,7 +1384,7 @@
         }
         if (version != 0) {
             if (settings.sdkVersion != 0 && sdkVersion != 0
-                && sdkVersion != settings.sdkVersion) {
+                && sdkVersion > settings.sdkVersion) {
                 return false;
             }
             if (settings.minorVersion != 0 && minorVersion != 0
diff --git a/libs/audioflinger/AudioFlinger.cpp b/libs/audioflinger/AudioFlinger.cpp
index ba8b322..d918998 100644
--- a/libs/audioflinger/AudioFlinger.cpp
+++ b/libs/audioflinger/AudioFlinger.cpp
@@ -482,38 +482,17 @@
         }
     }
 
-    status_t ret = NO_ERROR;
-
-    if (stream == AudioSystem::VOICE_CALL ||
-        stream == AudioSystem::BLUETOOTH_SCO) {
-        float hwValue;
-        if (stream == AudioSystem::VOICE_CALL) {
-            hwValue = (float)AudioSystem::logToLinear(value)/100.0f;
-            // offset value to reflect actual hardware volume that never reaches 0
-            // 1% corresponds roughly to first step in VOICE_CALL stream volume setting (see AudioService.java)
-            value = 0.01 + 0.99 * value;
-        } else { // (type == AudioSystem::BLUETOOTH_SCO)
-            hwValue = 1.0f;
-        }
-
-        AutoMutex lock(mHardwareLock);
-        mHardwareStatus = AUDIO_SET_VOICE_VOLUME;
-        ret = mAudioHardware->setVoiceVolume(hwValue);
-        mHardwareStatus = AUDIO_HW_IDLE;
-
-    }
-
     mStreamTypes[stream].volume = value;
 
     if (thread == NULL) {
-        for (uint32_t i = 0; i < mPlaybackThreads.size(); i++)
+        for (uint32_t i = 0; i < mPlaybackThreads.size(); i++) {
            mPlaybackThreads.valueAt(i)->setStreamVolume(stream, value);
-
+        }
     } else {
         thread->setStreamVolume(stream, value);
     }
 
-    return ret;
+    return NO_ERROR;
 }
 
 status_t AudioFlinger::setStreamMute(int stream, bool muted)
@@ -553,11 +532,6 @@
         volume = mStreamTypes[stream].volume;
     }
 
-    // remove correction applied by setStreamVolume()
-    if (stream == AudioSystem::VOICE_CALL) {
-        volume = (volume - 0.01) / 0.99 ;
-    }
-
     return volume;
 }
 
@@ -644,6 +618,21 @@
     return mAudioHardware->getInputBufferSize(sampleRate, format, channelCount);
 }
 
+status_t AudioFlinger::setVoiceVolume(float value)
+{
+    // check calling permissions
+    if (!settingsAllowed()) {
+        return PERMISSION_DENIED;
+    }
+
+    AutoMutex lock(mHardwareLock);
+    mHardwareStatus = AUDIO_SET_VOICE_VOLUME;
+    status_t ret = mAudioHardware->setVoiceVolume(value);
+    mHardwareStatus = AUDIO_HW_IDLE;
+
+    return ret;
+}
+
 void AudioFlinger::registerClient(const sp<IAudioFlingerClient>& client)
 {
 
@@ -826,6 +815,58 @@
     mLock.unlock();
 }
 
+status_t AudioFlinger::ThreadBase::dumpBase(int fd, const Vector<String16>& args)
+{
+    const size_t SIZE = 256;
+    char buffer[SIZE];
+    String8 result;
+
+    bool locked = tryLock(mLock);
+    if (!locked) {
+        snprintf(buffer, SIZE, "thread %p maybe dead locked\n", this);
+        write(fd, buffer, strlen(buffer));
+    }
+
+    snprintf(buffer, SIZE, "standby: %d\n", mStandby);
+    result.append(buffer);
+    snprintf(buffer, SIZE, "Sample rate: %d\n", mSampleRate);
+    result.append(buffer);
+    snprintf(buffer, SIZE, "Frame count: %d\n", mFrameCount);
+    result.append(buffer);
+    snprintf(buffer, SIZE, "Channel Count: %d\n", mChannelCount);
+    result.append(buffer);
+    snprintf(buffer, SIZE, "Format: %d\n", mFormat);
+    result.append(buffer);
+    snprintf(buffer, SIZE, "Frame size: %d\n", mFrameSize);
+    result.append(buffer);
+
+    snprintf(buffer, SIZE, "\nPending setParameters commands: \n");
+    result.append(buffer);
+    result.append(" Index Command");
+    for (size_t i = 0; i < mNewParameters.size(); ++i) {
+        snprintf(buffer, SIZE, "\n %02d    ", i);
+        result.append(buffer);
+        result.append(mNewParameters[i]);
+    }
+
+    snprintf(buffer, SIZE, "\n\nPending config events: \n");
+    result.append(buffer);
+    snprintf(buffer, SIZE, " Index event param\n");
+    result.append(buffer);
+    for (size_t i = 0; i < mConfigEvents.size(); i++) {
+        snprintf(buffer, SIZE, " %02d    %02d    %d\n", i, mConfigEvents[i]->mEvent, mConfigEvents[i]->mParam);
+        result.append(buffer);
+    }
+    result.append("\n");
+
+    write(fd, result.string(), result.size());
+
+    if (locked) {
+        mLock.unlock();
+    }
+    return NO_ERROR;
+}
+
 
 // ----------------------------------------------------------------------------
 
@@ -867,7 +908,7 @@
 
     snprintf(buffer, SIZE, "Output thread %p tracks\n", this);
     result.append(buffer);
-    result.append("   Name Clien Typ Fmt Chn Buf S M F SRate LeftV RighV Serv User\n");
+    result.append("   Name Clien Typ Fmt Chn Buf  S M F SRate  LeftV RighV Serv     User\n");
     for (size_t i = 0; i < mTracks.size(); ++i) {
         sp<Track> track = mTracks[i];
         if (track != 0) {
@@ -878,7 +919,7 @@
 
     snprintf(buffer, SIZE, "Output thread %p active tracks\n", this);
     result.append(buffer);
-    result.append("   Name Clien Typ Fmt Chn Buf S M F SRate LeftV RighV Serv User\n");
+    result.append("   Name Clien Typ Fmt Chn Buf  S M F SRate  LeftV RighV Serv     User\n");
     for (size_t i = 0; i < mActiveTracks.size(); ++i) {
         wp<Track> wTrack = mActiveTracks[i];
         if (wTrack != 0) {
@@ -899,7 +940,7 @@
     char buffer[SIZE];
     String8 result;
 
-    snprintf(buffer, SIZE, "Output thread %p internals\n", this);
+    snprintf(buffer, SIZE, "\nOutput thread %p internals\n", this);
     result.append(buffer);
     snprintf(buffer, SIZE, "last write occurred (msecs): %llu\n", ns2ms(systemTime() - mLastWriteTime));
     result.append(buffer);
@@ -909,9 +950,10 @@
     result.append(buffer);
     snprintf(buffer, SIZE, "blocked in write: %d\n", mInWrite);
     result.append(buffer);
-    snprintf(buffer, SIZE, "standby: %d\n", mStandby);
-    result.append(buffer);
     write(fd, result.string(), result.size());
+
+    dumpBase(fd, args);
+
     return NO_ERROR;
 }
 
@@ -976,7 +1018,7 @@
         Mutex::Autolock _l(mLock);
         track = new Track(this, client, streamType, sampleRate, format,
                 channelCount, frameCount, sharedBuffer);
-        if (track->getCblk() == NULL) {
+        if (track->getCblk() == NULL || track->name() < 0) {
             lStatus = NO_MEMORY;
             goto Exit;
         }
@@ -1143,7 +1185,6 @@
     mFrameSize = mOutput->frameSize();
     mFrameCount = mOutput->bufferSize() / mFrameSize;
 
-    mMinBytesToWrite = (mOutput->latency() * mSampleRate * mFrameSize) / 1000;
     // FIXME - Current mixer implementation only supports stereo output: Always
     // Allocate a stereo buffer even if HW output is mono.
     if (mMixBuffer != NULL) delete mMixBuffer;
@@ -1173,23 +1214,25 @@
 
 bool AudioFlinger::MixerThread::threadLoop()
 {
-    uint32_t sleepTime = 0;
-    uint32_t maxBufferRecoveryInUsecs = getMaxBufferRecoveryInUsecs();
     int16_t* curBuf = mMixBuffer;
     Vector< sp<Track> > tracksToRemove;
-    size_t enabledTracks = 0;
+    uint32_t mixerStatus = MIXER_IDLE;
     nsecs_t standbyTime = systemTime();
     size_t mixBufferSize = mFrameCount * mFrameSize;
     // FIXME: Relaxed timing because of a certain device that can't meet latency
     // Should be reduced to 2x after the vendor fixes the driver issue
     nsecs_t maxPeriod = seconds(mFrameCount) / mSampleRate * 3;
     nsecs_t lastWarning = 0;
+    bool longStandbyExit = false;
+    uint32_t activeSleepTime = activeSleepTimeUs();
+    uint32_t idleSleepTime = idleSleepTimeUs();
+    uint32_t sleepTime = idleSleepTime;
 
     while (!exitPending())
     {
         processConfigEvents();
 
-        enabledTracks = 0;
+        mixerStatus = MIXER_IDLE;
         { // scope for mLock
 
             Mutex::Autolock _l(mLock);
@@ -1199,7 +1242,8 @@
                 // FIXME: Relaxed timing because of a certain device that can't meet latency
                 // Should be reduced to 2x after the vendor fixes the driver issue
                 maxPeriod = seconds(mFrameCount) / mSampleRate * 3;
-                maxBufferRecoveryInUsecs = getMaxBufferRecoveryInUsecs();
+                activeSleepTime = activeSleepTimeUs();
+                idleSleepTime = idleSleepTimeUs();
             }
 
             const SortedVector< wp<Track> >& activeTracks = mActiveTracks;
@@ -1235,14 +1279,15 @@
                     }
 
                     standbyTime = systemTime() + kStandbyTimeInNsecs;
+                    sleepTime = idleSleepTime;
                     continue;
                 }
             }
 
-            enabledTracks = prepareTracks_l(activeTracks, &tracksToRemove);
+            mixerStatus = prepareTracks_l(activeTracks, &tracksToRemove);
        }
 
-        if (LIKELY(enabledTracks)) {
+        if (LIKELY(mixerStatus == MIXER_TRACKS_READY)) {
             // mix buffers...
             mAudioMixer->process(curBuf);
             sleepTime = 0;
@@ -1251,15 +1296,22 @@
             // If no tracks are ready, sleep once for the duration of an output
             // buffer size, then write 0s to the output
             if (sleepTime == 0) {
-                sleepTime = maxBufferRecoveryInUsecs;
-            } else if (mBytesWritten != 0) {
+                if (mixerStatus == MIXER_TRACKS_ENABLED) {
+                    sleepTime = activeSleepTime;
+                } else {
+                    sleepTime = idleSleepTime;
+                }
+            } else if (mBytesWritten != 0 ||
+                       (mixerStatus == MIXER_TRACKS_ENABLED && longStandbyExit)) {
+                LOGV("NO DATA READY, %p", this);
                 memset (curBuf, 0, mixBufferSize);
                 sleepTime = 0;
+                LOGV_IF((mBytesWritten == 0 && (mixerStatus == MIXER_TRACKS_ENABLED && longStandbyExit)), "anticipated start");
             }
         }
 
         if (mSuspended) {
-            sleepTime = maxBufferRecoveryInUsecs;
+            sleepTime = idleSleepTime;
         }
         // sleepTime == 0 means we must write to audio hardware
         if (sleepTime == 0) {
@@ -1269,7 +1321,6 @@
             if (bytesWritten > 0) mBytesWritten += bytesWritten;
             mNumWrites++;
             mInWrite = false;
-            mStandby = false;
             nsecs_t now = systemTime();
             nsecs_t delta = now - mLastWriteTime;
             if (delta > maxPeriod) {
@@ -1279,7 +1330,11 @@
                             ns2ms(delta), mNumDelayedWrites, this);
                     lastWarning = now;
                 }
+                if (mStandby) {
+                    longStandbyExit = true;
+                }
             }
+            mStandby = false;
         } else {
             usleep(sleepTime);
         }
@@ -1299,10 +1354,10 @@
 }
 
 // prepareTracks_l() must be called with ThreadBase::mLock held
-size_t AudioFlinger::MixerThread::prepareTracks_l(const SortedVector< wp<Track> >& activeTracks, Vector< sp<Track> > *tracksToRemove)
+uint32_t AudioFlinger::MixerThread::prepareTracks_l(const SortedVector< wp<Track> >& activeTracks, Vector< sp<Track> > *tracksToRemove)
 {
 
-    size_t enabledTracks = 0;
+    uint32_t mixerStatus = MIXER_IDLE;
     // find out which tracks need to be processed
     size_t count = activeTracks.size();
     for (size_t i=0 ; i<count ; i++) {
@@ -1372,7 +1427,7 @@
 
             // reset retry count
             track->mRetryCount = kMaxTrackRetries;
-            enabledTracks++;
+            mixerStatus = MIXER_TRACKS_READY;
         } else {
             //LOGV("track %d u=%08x, s=%08x [NOT READY]", track->name(), cblk->user, cblk->server);
             if (track->isStopped()) {
@@ -1389,16 +1444,11 @@
                 if (--(track->mRetryCount) <= 0) {
                     LOGV("BUFFER TIMEOUT: remove(%d) from active list on thread %p", track->name(), this);
                     tracksToRemove->add(track);
+                } else if (mixerStatus != MIXER_TRACKS_READY) {
+                    mixerStatus = MIXER_TRACKS_ENABLED;
                 }
-                // For tracks using static shared memory buffer, make sure that we have
-                // written enough data to audio hardware before disabling the track
-                // NOTE: this condition with arrive before track->mRetryCount <= 0 so we
-                // don't care about code removing track from active list above.
-                if ((track->mSharedBuffer == 0) || (mBytesWritten >= mMinBytesToWrite)) {
-                    mAudioMixer->disable(AudioMixer::MIXING);
-                } else {
-                    enabledTracks++;
-                }
+
+                mAudioMixer->disable(AudioMixer::MIXING);
             }
         }
     }
@@ -1416,7 +1466,7 @@
         }
     }
 
-    return enabledTracks;
+    return mixerStatus;
 }
 
 void AudioFlinger::MixerThread::getTracks(
@@ -1503,8 +1553,6 @@
         AudioParameter param = AudioParameter(keyValuePair);
         int value;
 
-        mNewParameters.removeAt(0);
-
         if (param.getInt(String8(AudioParameter::keySamplingRate), value) == NO_ERROR) {
             reconfig = true;
         }
@@ -1556,6 +1604,9 @@
                 sendConfigEvent_l(AudioSystem::OUTPUT_CONFIG_CHANGED);
             }
         }
+
+        mNewParameters.removeAt(0);
+
         mParamStatus = status;
         mParamCond.signal();
         mWaitWorkCV.wait(mLock);
@@ -1577,14 +1628,14 @@
     return NO_ERROR;
 }
 
-uint32_t AudioFlinger::MixerThread::getMaxBufferRecoveryInUsecs()
+uint32_t AudioFlinger::MixerThread::activeSleepTimeUs()
 {
-    uint32_t time = ((mFrameCount * 1000) / mSampleRate) * 1000;
-    // Add some margin with regard to scheduling precision
-    if (time > 10000) {
-        time -= 10000;
-    }
-    return time;
+    return (uint32_t)(mOutput->latency() * 1000) / 2;
+}
+
+uint32_t AudioFlinger::MixerThread::idleSleepTimeUs()
+{
+    return (uint32_t)((mFrameCount * 1000) / mSampleRate) * 1000;
 }
 
 // ----------------------------------------------------------------------------
@@ -1602,25 +1653,31 @@
 
 bool AudioFlinger::DirectOutputThread::threadLoop()
 {
-    uint32_t sleepTime = 0;
-    uint32_t maxBufferRecoveryInUsecs = getMaxBufferRecoveryInUsecs();
+    uint32_t mixerStatus = MIXER_IDLE;
     sp<Track> trackToRemove;
     sp<Track> activeTrack;
     nsecs_t standbyTime = systemTime();
     int8_t *curBuf;
     size_t mixBufferSize = mFrameCount*mFrameSize;
+    uint32_t activeSleepTime = activeSleepTimeUs();
+    uint32_t idleSleepTime = idleSleepTimeUs();
+    uint32_t sleepTime = idleSleepTime;
+
 
     while (!exitPending())
     {
         processConfigEvents();
 
+        mixerStatus = MIXER_IDLE;
+
         { // scope for the mLock
 
             Mutex::Autolock _l(mLock);
 
             if (checkForNewParameters_l()) {
                 mixBufferSize = mFrameCount*mFrameSize;
-                maxBufferRecoveryInUsecs = getMaxBufferRecoveryInUsecs();
+                activeSleepTime = activeSleepTimeUs();
+                idleSleepTime = idleSleepTimeUs();
             }
 
             // put audio hardware into standby after short delay
@@ -1654,6 +1711,7 @@
                     }
 
                     standbyTime = systemTime() + kStandbyTimeInNsecs;
+                    sleepTime = idleSleepTime;
                     continue;
                 }
             }
@@ -1708,6 +1766,7 @@
                     // reset retry count
                     track->mRetryCount = kMaxTrackRetries;
                     activeTrack = t;
+                    mixerStatus = MIXER_TRACKS_READY;
                 } else {
                     //LOGV("track %d u=%08x, s=%08x [NOT READY]", track->name(), cblk->user, cblk->server);
                     if (track->isStopped()) {
@@ -1723,16 +1782,10 @@
                         if (--(track->mRetryCount) <= 0) {
                             LOGV("BUFFER TIMEOUT: remove(%d) from active list", track->name());
                             trackToRemove = track;
+                        } else {
+                            mixerStatus = MIXER_TRACKS_ENABLED;
                         }
-
-                        // For tracks using static shared memry buffer, make sure that we have
-                        // written enough data to audio hardware before disabling the track
-                        // NOTE: this condition with arrive before track->mRetryCount <= 0 so we
-                        // don't care about code removing track from active list above.
-                        if ((track->mSharedBuffer != 0) && (mBytesWritten < mMinBytesToWrite)) {
-                            activeTrack = t;
-                        }
-                     }
+                    }
                 }
             }
 
@@ -1746,7 +1799,7 @@
             }
        }
 
-        if (activeTrack != 0) {
+        if (LIKELY(mixerStatus == MIXER_TRACKS_READY)) {
             AudioBufferProvider::Buffer buffer;
             size_t frameCount = mFrameCount;
             curBuf = (int8_t *)mMixBuffer;
@@ -1767,7 +1820,11 @@
             standbyTime = systemTime() + kStandbyTimeInNsecs;
         } else {
             if (sleepTime == 0) {
-                sleepTime = maxBufferRecoveryInUsecs;
+                if (mixerStatus == MIXER_TRACKS_ENABLED) {
+                    sleepTime = activeSleepTime;
+                } else {
+                    sleepTime = idleSleepTime;
+                }
             } else if (mBytesWritten != 0 && AudioSystem::isLinearPCM(mFormat)) {
                 memset (mMixBuffer, 0, mFrameCount * mFrameSize);
                 sleepTime = 0;
@@ -1775,7 +1832,7 @@
         }
 
         if (mSuspended) {
-            sleepTime = maxBufferRecoveryInUsecs;
+            sleepTime = idleSleepTime;
         }
         // sleepTime == 0 means we must write to audio hardware
         if (sleepTime == 0) {
@@ -1827,8 +1884,6 @@
         AudioParameter param = AudioParameter(keyValuePair);
         int value;
 
-        mNewParameters.removeAt(0);
-
         if (param.getInt(String8(AudioParameter::keyFrameCount), value) == NO_ERROR) {
             // do not accept frame count changes if tracks are open as the track buffer
             // size depends on frame count and correct behavior would not be garantied
@@ -1852,6 +1907,9 @@
                 sendConfigEvent_l(AudioSystem::OUTPUT_CONFIG_CHANGED);
             }
         }
+
+        mNewParameters.removeAt(0);
+
         mParamStatus = status;
         mParamCond.signal();
         mWaitWorkCV.wait(mLock);
@@ -1859,15 +1917,22 @@
     return reconfig;
 }
 
-uint32_t AudioFlinger::DirectOutputThread::getMaxBufferRecoveryInUsecs()
+uint32_t AudioFlinger::DirectOutputThread::activeSleepTimeUs()
 {
     uint32_t time;
     if (AudioSystem::isLinearPCM(mFormat)) {
-        time = ((mFrameCount * 1000) / mSampleRate) * 1000;
-        // Add some margin with regard to scheduling precision
-        if (time > 10000) {
-            time -= 10000;
-        }
+        time = (uint32_t)(mOutput->latency() * 1000) / 2;
+    } else {
+        time = 10000;
+    }
+    return time;
+}
+
+uint32_t AudioFlinger::DirectOutputThread::idleSleepTimeUs()
+{
+    uint32_t time;
+    if (AudioSystem::isLinearPCM(mFormat)) {
+        time = (uint32_t)((mFrameCount * 1000) / mSampleRate) * 1000;
     } else {
         time = 10000;
     }
@@ -1890,28 +1955,30 @@
 
 bool AudioFlinger::DuplicatingThread::threadLoop()
 {
-    uint32_t sleepTime = 0;
-    uint32_t maxBufferRecoveryInUsecs = getMaxBufferRecoveryInUsecs();
     int16_t* curBuf = mMixBuffer;
     Vector< sp<Track> > tracksToRemove;
-    size_t enabledTracks = 0;
+    uint32_t mixerStatus = MIXER_IDLE;
     nsecs_t standbyTime = systemTime();
     size_t mixBufferSize = mFrameCount*mFrameSize;
     SortedVector< sp<OutputTrack> > outputTracks;
     uint32_t writeFrames = 0;
+    uint32_t activeSleepTime = activeSleepTimeUs();
+    uint32_t idleSleepTime = idleSleepTimeUs();
+    uint32_t sleepTime = idleSleepTime;
 
     while (!exitPending())
     {
         processConfigEvents();
 
-        enabledTracks = 0;
+        mixerStatus = MIXER_IDLE;
         { // scope for the mLock
 
             Mutex::Autolock _l(mLock);
 
             if (checkForNewParameters_l()) {
                 mixBufferSize = mFrameCount*mFrameSize;
-                maxBufferRecoveryInUsecs = getMaxBufferRecoveryInUsecs();
+                activeSleepTime = activeSleepTimeUs();
+                idleSleepTime = idleSleepTimeUs();
             }
 
             const SortedVector< wp<Track> >& activeTracks = mActiveTracks;
@@ -1951,21 +2018,26 @@
                     }
 
                     standbyTime = systemTime() + kStandbyTimeInNsecs;
+                    sleepTime = idleSleepTime;
                     continue;
                 }
             }
 
-            enabledTracks = prepareTracks_l(activeTracks, &tracksToRemove);
+            mixerStatus = prepareTracks_l(activeTracks, &tracksToRemove);
         }
 
-        if (LIKELY(enabledTracks)) {
+        if (LIKELY(mixerStatus == MIXER_TRACKS_READY)) {
             // mix buffers...
             mAudioMixer->process(curBuf);
             sleepTime = 0;
             writeFrames = mFrameCount;
         } else {
             if (sleepTime == 0) {
-                sleepTime = maxBufferRecoveryInUsecs;
+                if (mixerStatus == MIXER_TRACKS_ENABLED) {
+                    sleepTime = activeSleepTime;
+                } else {
+                    sleepTime = idleSleepTime;
+                }
             } else if (mBytesWritten != 0) {
                 // flush remaining overflow buffers in output tracks
                 for (size_t i = 0; i < outputTracks.size(); i++) {
@@ -1979,7 +2051,7 @@
         }
 
         if (mSuspended) {
-            sleepTime = maxBufferRecoveryInUsecs;
+            sleepTime = idleSleepTime;
         }
         // sleepTime == 0 means we must write to audio hardware
         if (sleepTime == 0) {
@@ -2261,7 +2333,7 @@
 
 void AudioFlinger::PlaybackThread::Track::dump(char* buffer, size_t size)
 {
-    snprintf(buffer, size, "  %5d %5d %3u %3u %3u %3u %1d %1d %1d %5u %5u %5u %04x %04x\n",
+    snprintf(buffer, size, "  %5d %5d %3u %3u %3u %04u %1d %1d %1d %5u %5u %5u  %08x %08x\n",
             mName - AudioMixer::TRACK0,
             (mClient == NULL) ? getpid() : mClient->pid(),
             mStreamType,
@@ -2517,6 +2589,19 @@
     }
 }
 
+void AudioFlinger::RecordThread::RecordTrack::dump(char* buffer, size_t size)
+{
+    snprintf(buffer, size, "   %05d %03u %03u %04u %01d %05u  %08x %08x\n",
+            (mClient == NULL) ? getpid() : mClient->pid(),
+            mFormat,
+            mCblk->channels,
+            mFrameCount,
+            mState,
+            mCblk->sampleRate,
+            mCblk->server,
+            mCblk->user);
+}
+
 
 // ----------------------------------------------------------------------------
 
@@ -3144,13 +3229,34 @@
     String8 result;
     pid_t pid = 0;
 
-    if (mActiveTrack != 0 && mActiveTrack->mClient != 0) {
-        snprintf(buffer, SIZE, "Record client pid: %d\n", mActiveTrack->mClient->pid());
+    snprintf(buffer, SIZE, "\nInput thread %p internals\n", this);
+    result.append(buffer);
+
+    if (mActiveTrack != 0) {
+        result.append("Active Track:\n");
+        result.append("   Clien Fmt Chn Buf  S SRate  Serv     User\n");
+        mActiveTrack->dump(buffer, SIZE);
         result.append(buffer);
+
+        snprintf(buffer, SIZE, "In index: %d\n", mRsmpInIndex);
+        result.append(buffer);
+        snprintf(buffer, SIZE, "In size: %d\n", mInputBytes);
+        result.append(buffer);
+        snprintf(buffer, SIZE, "Resampling: %d\n", (mResampler != 0));
+        result.append(buffer);
+        snprintf(buffer, SIZE, "Out channel count: %d\n", mReqChannelCount);
+        result.append(buffer);
+        snprintf(buffer, SIZE, "Out sample rate: %d\n", mReqSampleRate);
+        result.append(buffer);
+
+
     } else {
         result.append("No record client\n");
     }
     write(fd, result.string(), result.size());
+
+    dumpBase(fd, args);
+
     return NO_ERROR;
 }
 
@@ -3206,8 +3312,6 @@
         int reqSamplingRate = mReqSampleRate;
         int reqChannelCount = mReqChannelCount;
 
-        mNewParameters.removeAt(0);
-
         if (param.getInt(String8(AudioParameter::keySamplingRate), value) == NO_ERROR) {
             reqSamplingRate = value;
             reconfig = true;
@@ -3249,6 +3353,9 @@
                 }
             }
         }
+
+        mNewParameters.removeAt(0);
+
         mParamStatus = status;
         mParamCond.signal();
         mWaitWorkCV.wait(mLock);
diff --git a/libs/audioflinger/AudioFlinger.h b/libs/audioflinger/AudioFlinger.h
index 4bf73ce..594d878 100644
--- a/libs/audioflinger/AudioFlinger.h
+++ b/libs/audioflinger/AudioFlinger.h
@@ -133,6 +133,8 @@
 
     virtual status_t setStreamOutput(uint32_t stream, int output);
 
+    virtual status_t setVoiceVolume(float volume);
+
     // IBinder::DeathRecipient
     virtual     void        binderDied(const wp<IBinder>& who);
 
@@ -214,6 +216,8 @@
         ThreadBase (const sp<AudioFlinger>& audioFlinger);
         virtual             ~ThreadBase();
 
+        status_t dumpBase(int fd, const Vector<String16>& args);
+
         // base for record and playback
         class TrackBase : public AudioBufferProvider, public RefBase {
 
@@ -357,6 +361,12 @@
             DUPLICATING
         };
 
+        enum mixer_state {
+            MIXER_IDLE,
+            MIXER_TRACKS_ENABLED,
+            MIXER_TRACKS_READY
+        };
+
         // playback track
         class Track : public TrackBase {
         public:
@@ -526,7 +536,8 @@
 
         virtual int             getTrackName_l() = 0;
         virtual void            deleteTrackName_l(int name) = 0;
-        virtual uint32_t        getMaxBufferRecoveryInUsecs() = 0;
+        virtual uint32_t        activeSleepTimeUs() = 0;
+        virtual uint32_t        idleSleepTimeUs() = 0;
 
     private:
 
@@ -558,7 +569,6 @@
         int                             mNumWrites;
         int                             mNumDelayedWrites;
         bool                            mInWrite;
-        int                             mMinBytesToWrite;
     };
 
     class MixerThread : public PlaybackThread {
@@ -578,10 +588,11 @@
         virtual     status_t    dumpInternals(int fd, const Vector<String16>& args);
 
     protected:
-        size_t prepareTracks_l(const SortedVector< wp<Track> >& activeTracks, Vector< sp<Track> > *tracksToRemove);
+                    uint32_t    prepareTracks_l(const SortedVector< wp<Track> >& activeTracks, Vector< sp<Track> > *tracksToRemove);
         virtual     int         getTrackName_l();
         virtual     void        deleteTrackName_l(int name);
-        virtual     uint32_t    getMaxBufferRecoveryInUsecs();
+        virtual     uint32_t    activeSleepTimeUs();
+        virtual     uint32_t    idleSleepTimeUs();
 
         AudioMixer*                     mAudioMixer;
     };
@@ -600,7 +611,8 @@
     protected:
         virtual     int         getTrackName_l();
         virtual     void        deleteTrackName_l(int name);
-        virtual     uint32_t    getMaxBufferRecoveryInUsecs();
+        virtual     uint32_t    activeSleepTimeUs();
+        virtual     uint32_t    idleSleepTimeUs();
 
     private:
         float mLeftVolume;
@@ -676,6 +688,7 @@
                     bool        overflow() { bool tmp = mOverflow; mOverflow = false; return tmp; }
                     bool        setOverflow() { bool tmp = mOverflow; mOverflow = true; return tmp; }
 
+                    void        dump(char* buffer, size_t size);
         private:
             friend class AudioFlinger;
             friend class RecordThread;
diff --git a/libs/audioflinger/AudioPolicyManagerGeneric.cpp b/libs/audioflinger/AudioPolicyManagerGeneric.cpp
index 6323859..8cfc204 100644
--- a/libs/audioflinger/AudioPolicyManagerGeneric.cpp
+++ b/libs/audioflinger/AudioPolicyManagerGeneric.cpp
@@ -459,6 +459,61 @@
     return NO_ERROR;
 }
 
+status_t AudioPolicyManagerGeneric::dump(int fd)
+{
+    const size_t SIZE = 256;
+    char buffer[SIZE];
+    String8 result;
+
+    snprintf(buffer, SIZE, "\nAudioPolicyManager Dump: %p\n", this);
+    result.append(buffer);
+    snprintf(buffer, SIZE, " Hardware Output: %d\n", mHardwareOutput);
+    result.append(buffer);
+    snprintf(buffer, SIZE, " Output devices: %08x\n", mAvailableOutputDevices);
+    result.append(buffer);
+    snprintf(buffer, SIZE, " Input devices: %08x\n", mAvailableInputDevices);
+    result.append(buffer);
+    snprintf(buffer, SIZE, " Phone state: %d\n", mPhoneState);
+    result.append(buffer);
+    snprintf(buffer, SIZE, " Ringer mode: %d\n", mRingerMode);
+    result.append(buffer);
+    snprintf(buffer, SIZE, " Force use for communications %d\n", mForceUse[AudioSystem::FOR_COMMUNICATION]);
+    result.append(buffer);
+    snprintf(buffer, SIZE, " Force use for media %d\n", mForceUse[AudioSystem::FOR_MEDIA]);
+    result.append(buffer);
+    snprintf(buffer, SIZE, " Force use for record %d\n", mForceUse[AudioSystem::FOR_RECORD]);
+    result.append(buffer);
+    write(fd, result.string(), result.size());
+
+    snprintf(buffer, SIZE, "\nOutputs dump:\n");
+    write(fd, buffer, strlen(buffer));
+    for (size_t i = 0; i < mOutputs.size(); i++) {
+        snprintf(buffer, SIZE, "- Output %d dump:\n", mOutputs.keyAt(i));
+        write(fd, buffer, strlen(buffer));
+        mOutputs.valueAt(i)->dump(fd);
+    }
+
+    snprintf(buffer, SIZE, "\nInputs dump:\n");
+    write(fd, buffer, strlen(buffer));
+    for (size_t i = 0; i < mInputs.size(); i++) {
+        snprintf(buffer, SIZE, "- Input %d dump:\n", mInputs.keyAt(i));
+        write(fd, buffer, strlen(buffer));
+        mInputs.valueAt(i)->dump(fd);
+    }
+
+    snprintf(buffer, SIZE, "\nStreams dump:\n");
+    write(fd, buffer, strlen(buffer));
+    snprintf(buffer, SIZE, " Stream  Index Min  Index Max  Index Cur  Mute Count  Can be muted\n");
+    write(fd, buffer, strlen(buffer));
+    for (size_t i = 0; i < AudioSystem::NUM_STREAM_TYPES; i++) {
+        snprintf(buffer, SIZE, " %02d", i);
+        mStreams[i].dump(buffer + 3, SIZE);
+        write(fd, buffer, strlen(buffer));
+    }
+
+    return NO_ERROR;
+}
+
 // ----------------------------------------------------------------------------
 // AudioPolicyManagerGeneric
 // ----------------------------------------------------------------------------
@@ -815,6 +870,35 @@
     return refcount;
 }
 
+status_t AudioPolicyManagerGeneric::AudioOutputDescriptor::dump(int fd)
+{
+    const size_t SIZE = 256;
+    char buffer[SIZE];
+    String8 result;
+
+    snprintf(buffer, SIZE, " Sampling rate: %d\n", mSamplingRate);
+    result.append(buffer);
+    snprintf(buffer, SIZE, " Format: %d\n", mFormat);
+    result.append(buffer);
+    snprintf(buffer, SIZE, " Channels: %08x\n", mChannels);
+    result.append(buffer);
+    snprintf(buffer, SIZE, " Latency: %d\n", mLatency);
+    result.append(buffer);
+    snprintf(buffer, SIZE, " Flags %08x\n", mFlags);
+    result.append(buffer);
+    snprintf(buffer, SIZE, " Devices %08x\n", mDevice);
+    result.append(buffer);
+    snprintf(buffer, SIZE, " Stream refCount\n");
+    result.append(buffer);
+    for (int i = 0; i < AudioSystem::NUM_STREAM_TYPES; i++) {
+        snprintf(buffer, SIZE, " %02d     %d\n", i, mRefCount[i]);
+        result.append(buffer);
+    }
+    write(fd, result.string(), result.size());
+
+    return NO_ERROR;
+}
+
 // --- AudioInputDescriptor class implementation
 
 AudioPolicyManagerGeneric::AudioInputDescriptor::AudioInputDescriptor()
@@ -823,4 +907,39 @@
 {
 }
 
+status_t AudioPolicyManagerGeneric::AudioInputDescriptor::dump(int fd)
+{
+    const size_t SIZE = 256;
+    char buffer[SIZE];
+    String8 result;
+
+    snprintf(buffer, SIZE, " Sampling rate: %d\n", mSamplingRate);
+    result.append(buffer);
+    snprintf(buffer, SIZE, " Format: %d\n", mFormat);
+    result.append(buffer);
+    snprintf(buffer, SIZE, " Channels: %08x\n", mChannels);
+    result.append(buffer);
+    snprintf(buffer, SIZE, " Acoustics %08x\n", mAcoustics);
+    result.append(buffer);
+    snprintf(buffer, SIZE, " Devices %08x\n", mDevice);
+    result.append(buffer);
+    snprintf(buffer, SIZE, " Ref Count %d\n", mRefCount);
+    result.append(buffer);
+    write(fd, result.string(), result.size());
+
+    return NO_ERROR;
+}
+
+// --- StreamDescriptor class implementation
+
+void AudioPolicyManagerGeneric::StreamDescriptor::dump(char* buffer, size_t size)
+{
+    snprintf(buffer, size, "      %02d         %02d         %02d         %02d          %d\n",
+            mIndexMin,
+            mIndexMax,
+            mIndexCur,
+            mMuteCount,
+            mCanBeMuted);
+}
+
 }; // namespace android
diff --git a/libs/audioflinger/AudioPolicyManagerGeneric.h b/libs/audioflinger/AudioPolicyManagerGeneric.h
index d904520..4997cdf 100644
--- a/libs/audioflinger/AudioPolicyManagerGeneric.h
+++ b/libs/audioflinger/AudioPolicyManagerGeneric.h
@@ -76,6 +76,8 @@
         virtual status_t setStreamVolumeIndex(AudioSystem::stream_type stream, int index);
         virtual status_t getStreamVolumeIndex(AudioSystem::stream_type stream, int *index);
 
+        virtual status_t dump(int fd);
+
 private:
 
         enum routing_strategy {
@@ -93,6 +95,7 @@
         public:
             AudioOutputDescriptor();
 
+            status_t    dump(int fd);
 
             uint32_t device();
             void changeRefCount(AudioSystem::stream_type, int delta);
@@ -115,6 +118,8 @@
         public:
             AudioInputDescriptor();
 
+            status_t    dump(int fd);
+
             uint32_t mSamplingRate;                     //
             uint32_t mFormat;                           // input configuration
             uint32_t mChannels;                         //
@@ -130,6 +135,8 @@
             StreamDescriptor()
             :   mIndexMin(0), mIndexMax(1), mIndexCur(1), mMuteCount(0), mCanBeMuted(true) {}
 
+            void dump(char* buffer, size_t size);
+
             int mIndexMin;      // min volume index
             int mIndexMax;      // max volume index
             int mIndexCur;      // current volume index
diff --git a/libs/audioflinger/AudioPolicyService.cpp b/libs/audioflinger/AudioPolicyService.cpp
index 5c3cc8e..aa48019 100644
--- a/libs/audioflinger/AudioPolicyService.cpp
+++ b/libs/audioflinger/AudioPolicyService.cpp
@@ -43,6 +43,12 @@
 
 namespace android {
 
+static const char* kDeadlockedString = "AudioPolicyService may be deadlocked\n";
+static const char* kCmdDeadlockedString = "AudioPolicyService command thread may be deadlocked\n";
+
+static const int kDumpLockRetries = 50;
+static const int kDumpLockSleep = 20000;
+
 static bool checkPermission() {
 #ifndef HAVE_ANDROID_OS
     return true;
@@ -335,17 +341,65 @@
     LOGW("binderDied() %p, tid %d, calling tid %d", who.unsafe_get(), gettid(), IPCThreadState::self()->getCallingPid());
 }
 
+static bool tryLock(Mutex& mutex)
+{
+    bool locked = false;
+    for (int i = 0; i < kDumpLockRetries; ++i) {
+        if (mutex.tryLock() == NO_ERROR) {
+            locked = true;
+            break;
+        }
+        usleep(kDumpLockSleep);
+    }
+    return locked;
+}
+
+status_t AudioPolicyService::dumpInternals(int fd)
+{
+    const size_t SIZE = 256;
+    char buffer[SIZE];
+    String8 result;
+
+    snprintf(buffer, SIZE, "PolicyManager Interface: %p\n", mpPolicyManager);
+    result.append(buffer);
+    snprintf(buffer, SIZE, "Command Thread: %p\n", mAudioCommandThread.get());
+    result.append(buffer);
+    snprintf(buffer, SIZE, "Tones Thread: %p\n", mTonePlaybackThread.get());
+    result.append(buffer);
+
+    write(fd, result.string(), result.size());
+    return NO_ERROR;
+}
+
 status_t AudioPolicyService::dump(int fd, const Vector<String16>& args)
 {
     if (checkCallingPermission(String16("android.permission.DUMP")) == false) {
-        dumpPermissionDenial(fd, args);
+        dumpPermissionDenial(fd);
     } else {
+        bool locked = tryLock(mLock);
+        if (!locked) {
+            String8 result(kDeadlockedString);
+            write(fd, result.string(), result.size());
+        }
 
+        dumpInternals(fd);
+        if (mAudioCommandThread != NULL) {
+            mAudioCommandThread->dump(fd);
+        }
+        if (mTonePlaybackThread != NULL) {
+            mTonePlaybackThread->dump(fd);
+        }
+
+        if (mpPolicyManager) {
+            mpPolicyManager->dump(fd);
+        }
+
+        if (locked) mLock.unlock();
     }
     return NO_ERROR;
 }
 
-status_t AudioPolicyService::dumpPermissionDenial(int fd, const Vector<String16>& args)
+status_t AudioPolicyService::dumpPermissionDenial(int fd)
 {
     const size_t SIZE = 256;
     char buffer[SIZE];
@@ -495,6 +549,10 @@
     return NO_ERROR;
 }
 
+status_t AudioPolicyService::setVoiceVolume(float volume, int delayMs)
+{
+    return mAudioCommandThread->voiceVolumeCommand(volume, delayMs);
+}
 
 // -----------  AudioPolicyService::AudioCommandThread implementation ----------
 
@@ -534,6 +592,8 @@
             if (mAudioCommands[0]->mTime <= curTime) {
                 AudioCommand *command = mAudioCommands[0];
                 mAudioCommands.removeAt(0);
+                mLastCommand = *command;
+
                 switch (command->mCommand) {
                 case START_TONE: {
                     mLock.unlock();
@@ -577,6 +637,16 @@
                      }
                      delete data;
                      }break;
+                case SET_VOICE_VOLUME: {
+                    VoiceVolumeData *data = (VoiceVolumeData *)command->mParam;
+                    LOGV("AudioCommandThread() processing set voice volume volume %f", data->mVolume);
+                    command->mStatus = AudioSystem::setVoiceVolume(data->mVolume);
+                    if (command->mWaitStatus) {
+                        command->mCond.signal();
+                        mWaitWorkCV.wait(mLock);
+                    }
+                    delete data;
+                    }break;
                 default:
                     LOGW("AudioCommandThread() unknown command %d", command->mCommand);
                 }
@@ -595,9 +665,42 @@
     return false;
 }
 
+status_t AudioPolicyService::AudioCommandThread::dump(int fd)
+{
+    const size_t SIZE = 256;
+    char buffer[SIZE];
+    String8 result;
+
+    snprintf(buffer, SIZE, "AudioCommandThread %p Dump\n", this);
+    result.append(buffer);
+    write(fd, result.string(), result.size());
+
+    bool locked = tryLock(mLock);
+    if (!locked) {
+        String8 result2(kCmdDeadlockedString);
+        write(fd, result2.string(), result2.size());
+    }
+
+    snprintf(buffer, SIZE, "- Commands:\n");
+    result = String8(buffer);
+    result.append("   Command Time        Wait pParam\n");
+    for (int i = 0; i < (int)mAudioCommands.size(); i++) {
+        mAudioCommands[i]->dump(buffer, SIZE);
+        result.append(buffer);
+    }
+    result.append("  Last Command\n");
+    mLastCommand.dump(buffer, SIZE);
+    result.append(buffer);
+
+    write(fd, result.string(), result.size());
+
+    if (locked) mLock.unlock();
+
+    return NO_ERROR;
+}
+
 void AudioPolicyService::AudioCommandThread::startToneCommand(int type, int stream)
 {
-    Mutex::Autolock _l(mLock);
     AudioCommand *command = new AudioCommand();
     command->mCommand = START_TONE;
     ToneData *data = new ToneData();
@@ -605,6 +708,7 @@
     data->mStream = stream;
     command->mParam = (void *)data;
     command->mWaitStatus = false;
+    Mutex::Autolock _l(mLock);
     insertCommand_l(command);
     LOGV("AudioCommandThread() adding tone start type %d, stream %d", type, stream);
     mWaitWorkCV.signal();
@@ -612,11 +716,11 @@
 
 void AudioPolicyService::AudioCommandThread::stopToneCommand()
 {
-    Mutex::Autolock _l(mLock);
     AudioCommand *command = new AudioCommand();
     command->mCommand = STOP_TONE;
     command->mParam = NULL;
     command->mWaitStatus = false;
+    Mutex::Autolock _l(mLock);
     insertCommand_l(command);
     LOGV("AudioCommandThread() adding tone stop");
     mWaitWorkCV.signal();
@@ -626,7 +730,6 @@
 {
     status_t status = NO_ERROR;
 
-    Mutex::Autolock _l(mLock);
     AudioCommand *command = new AudioCommand();
     command->mCommand = SET_VOLUME;
     VolumeData *data = new VolumeData();
@@ -639,6 +742,7 @@
     } else {
         command->mWaitStatus = false;
     }
+    Mutex::Autolock _l(mLock);
     insertCommand_l(command, delayMs);
     LOGV("AudioCommandThread() adding set volume stream %d, volume %f, output %d", stream, volume, output);
     mWaitWorkCV.signal();
@@ -654,7 +758,6 @@
 {
     status_t status = NO_ERROR;
 
-    Mutex::Autolock _l(mLock);
     AudioCommand *command = new AudioCommand();
     command->mCommand = SET_PARAMETERS;
     ParametersData *data = new ParametersData();
@@ -666,6 +769,7 @@
     } else {
         command->mWaitStatus = false;
     }
+    Mutex::Autolock _l(mLock);
     insertCommand_l(command, delayMs);
     LOGV("AudioCommandThread() adding set parameter string %s, io %d ,delay %d", keyValuePairs.string(), ioHandle, delayMs);
     mWaitWorkCV.signal();
@@ -677,6 +781,32 @@
     return status;
 }
 
+status_t AudioPolicyService::AudioCommandThread::voiceVolumeCommand(float volume, int delayMs)
+{
+    status_t status = NO_ERROR;
+
+    AudioCommand *command = new AudioCommand();
+    command->mCommand = SET_VOICE_VOLUME;
+    VoiceVolumeData *data = new VoiceVolumeData();
+    data->mVolume = volume;
+    command->mParam = data;
+    if (delayMs == 0) {
+        command->mWaitStatus = true;
+    } else {
+        command->mWaitStatus = false;
+    }
+    Mutex::Autolock _l(mLock);
+    insertCommand_l(command, delayMs);
+    LOGV("AudioCommandThread() adding set voice volume volume %f", volume);
+    mWaitWorkCV.signal();
+    if (command->mWaitStatus) {
+        command->mCond.wait(mLock);
+        status =  command->mStatus;
+        mWaitWorkCV.signal();
+    }
+    return status;
+}
+
 // insertCommand_l() must be called with mLock held
 void AudioPolicyService::AudioCommandThread::insertCommand_l(AudioCommand *command, int delayMs)
 {
@@ -768,4 +898,14 @@
     requestExitAndWait();
 }
 
+void AudioPolicyService::AudioCommandThread::AudioCommand::dump(char* buffer, size_t size)
+{
+    snprintf(buffer, size, "   %02d      %06d.%03d  %01u    %p\n",
+            mCommand,
+            (int)ns2s(mTime),
+            (int)ns2ms(mTime)%1000,
+            mWaitStatus,
+            mParam);
+}
+
 }; // namespace android
diff --git a/libs/audioflinger/AudioPolicyService.h b/libs/audioflinger/AudioPolicyService.h
index 56a85e1..b9234ec 100644
--- a/libs/audioflinger/AudioPolicyService.h
+++ b/libs/audioflinger/AudioPolicyService.h
@@ -105,11 +105,14 @@
     virtual String8 getParameters(audio_io_handle_t ioHandle, const String8& keys);
     virtual status_t startTone(ToneGenerator::tone_type tone, AudioSystem::stream_type stream);
     virtual status_t stopTone();
+    virtual status_t setVoiceVolume(float volume, int delayMs = 0);
 
 private:
                         AudioPolicyService();
     virtual             ~AudioPolicyService();
 
+            status_t dumpInternals(int fd);
+
     // Thread used for tone playback and to send audio config commands to audio flinger
     // For tone playback, using a separate thread is necessary to avoid deadlock with mLock because startTone()
     // and stopTone() are normally called with mLock locked and requesting a tone start or stop will cause
@@ -125,12 +128,15 @@
             START_TONE,
             STOP_TONE,
             SET_VOLUME,
-            SET_PARAMETERS
+            SET_PARAMETERS,
+            SET_VOICE_VOLUME
         };
 
         AudioCommandThread ();
         virtual             ~AudioCommandThread();
 
+                    status_t    dump(int fd);
+
         // Thread virtuals
         virtual     void        onFirstRef();
         virtual     bool        threadLoop();
@@ -140,12 +146,19 @@
                     void        stopToneCommand();
                     status_t    volumeCommand(int stream, float volume, int output, int delayMs = 0);
                     status_t    parametersCommand(int ioHandle, const String8& keyValuePairs, int delayMs = 0);
+                    status_t    voiceVolumeCommand(float volume, int delayMs = 0);
                     void        insertCommand_l(AudioCommand *command, int delayMs = 0);
 
     private:
         // descriptor for requested tone playback event
         class AudioCommand {
+
         public:
+            AudioCommand()
+            : mCommand(-1) {}
+
+            void dump(char* buffer, size_t size);
+
             int mCommand;   // START_TONE, STOP_TONE ...
             nsecs_t mTime;  // time stamp
             Condition mCond; // condition for status return
@@ -166,21 +179,27 @@
             float mVolume;
             int mIO;
         };
+
         class ParametersData {
         public:
             int mIO;
             String8 mKeyValuePairs;
         };
 
+        class VoiceVolumeData {
+        public:
+            float mVolume;
+        };
 
         Mutex   mLock;
         Condition mWaitWorkCV;
         Vector <AudioCommand *> mAudioCommands; // list of pending commands
         ToneGenerator *mpToneGenerator;     // the tone generator
+        AudioCommand mLastCommand;
     };
 
     // Internal dump utilities.
-    status_t dumpPermissionDenial(int fd, const Vector<String16>& args);
+    status_t dumpPermissionDenial(int fd);
 
 
     Mutex   mLock;      // prevents concurrent access to AudioPolicy manager functions changing device
diff --git a/libs/binder/IPCThreadState.cpp b/libs/binder/IPCThreadState.cpp
index c371a23..b2a7db8 100644
--- a/libs/binder/IPCThreadState.cpp
+++ b/libs/binder/IPCThreadState.cpp
@@ -14,10 +14,13 @@
  * limitations under the License.
  */
 
+#define LOG_TAG "IPCThreadState"
+
 #include <binder/IPCThreadState.h>
 
 #include <binder/Binder.h>
 #include <binder/BpBinder.h>
+#include <cutils/sched_policy.h>
 #include <utils/Debug.h>
 #include <utils/Log.h>
 #include <utils/TextOutput.h>
@@ -418,9 +421,26 @@
                 alog << "Processing top-level Command: "
                     << getReturnString(cmd) << endl;
             }
+
+
             result = executeCommand(cmd);
         }
         
+        // After executing the command, ensure that the thread is returned to the
+        // default cgroup and priority before rejoining the pool.  This is a failsafe
+        // in case the command implementation failed to properly restore the thread's
+        // scheduling parameters upon completion.
+        int my_id;
+#ifdef HAVE_GETTID
+        my_id = gettid();
+#else
+        my_id = getpid();
+#endif
+        if (!set_sched_policy(my_id, SP_FOREGROUND)) {
+            // success; reset the priority as well
+            setpriority(PRIO_PROCESS, my_id, ANDROID_PRIORITY_NORMAL);
+        }
+
         // Let this thread exit the thread pool if it is no longer
         // needed and it is not the main process thread.
         if(result == TIMED_OUT && !isMain) {
diff --git a/libs/binder/MemoryHeapBase.cpp b/libs/binder/MemoryHeapBase.cpp
index 5df078f..624f7eb 100644
--- a/libs/binder/MemoryHeapBase.cpp
+++ b/libs/binder/MemoryHeapBase.cpp
@@ -67,7 +67,11 @@
     : mFD(-1), mSize(0), mBase(MAP_FAILED), mFlags(flags),
       mDevice(0), mNeedUnmap(false)
 {
-    int fd = open(device, O_RDWR);
+    int open_flags = O_RDWR;
+    if (flags & NO_CACHING)
+        open_flags |= O_SYNC;
+
+    int fd = open(device, open_flags);
     LOGE_IF(fd<0, "error opening %s: %s", device, strerror(errno));
     if (fd >= 0) {
         const size_t pagesize = getpagesize();
diff --git a/libs/binder/MemoryHeapPmem.cpp b/libs/binder/MemoryHeapPmem.cpp
index 3806a42..c660947 100644
--- a/libs/binder/MemoryHeapPmem.cpp
+++ b/libs/binder/MemoryHeapPmem.cpp
@@ -132,7 +132,7 @@
     char const * const device = pmemHeap->getDevice();
 #if HAVE_ANDROID_OS
     if (device) {
-        int fd = open(device, O_RDWR);
+        int fd = open(device, O_RDWR | (flags & NO_CACHING ? O_SYNC : 0));
         LOGE_IF(fd<0, "couldn't open %s (%s)", device, strerror(errno));
         if (fd >= 0) {
             int err = ioctl(fd, PMEM_CONNECT, pmemHeap->heapID());
diff --git a/libs/binder/ProcessState.cpp b/libs/binder/ProcessState.cpp
index d7daf73..2d4e10d 100644
--- a/libs/binder/ProcessState.cpp
+++ b/libs/binder/ProcessState.cpp
@@ -41,7 +41,7 @@
 #include <sys/mman.h>
 #include <sys/stat.h>
 
-#define BINDER_VM_SIZE (1*1024*1024)
+#define BINDER_VM_SIZE ((1*1024*1024) - (4096 *2))
 
 static bool gSingleProcess = false;
 
diff --git a/libs/surfaceflinger/Android.mk b/libs/surfaceflinger/Android.mk
index eb51c22..b3fed58 100644
--- a/libs/surfaceflinger/Android.mk
+++ b/libs/surfaceflinger/Android.mk
@@ -22,9 +22,6 @@
 ifeq ($(TARGET_BOARD_PLATFORM), msm7k)
 	LOCAL_CFLAGS += -DDIM_WITH_TEXTURE
 endif
-ifeq ($(TARGET_BOARD_PLATFORM), qsd8k)
-	LOCAL_CFLAGS += -DDIM_WITH_TEXTURE
-endif
 
 # need "-lrt" on Linux simulator to pick up clock_gettime
 ifeq ($(TARGET_SIMULATOR),true)
diff --git a/libs/surfaceflinger/DisplayHardware/DisplayHardware.cpp b/libs/surfaceflinger/DisplayHardware/DisplayHardware.cpp
index f84933e..79c003f 100644
--- a/libs/surfaceflinger/DisplayHardware/DisplayHardware.cpp
+++ b/libs/surfaceflinger/DisplayHardware/DisplayHardware.cpp
@@ -246,22 +246,28 @@
     LOGI("version   : %s", glGetString(GL_VERSION));
     LOGI("extensions: %s", gl_extensions);
 
-    if (strstr(gl_renderer, "PowerVR SGX 530")) {
+    if (strstr(gl_renderer, "PowerVR SGX 530") ||
+        strstr(gl_renderer, "Adreno")) {
         LOGD("Assuming uncached graphics buffers.");
         mFlags &= ~CACHED_BUFFERS;
     }
+
     if (strstr(gl_extensions, "GL_ARB_texture_non_power_of_two")) {
         mFlags |= NPOT_EXTENSION;
     }
     if (strstr(gl_extensions, "GL_OES_draw_texture")) {
         mFlags |= DRAW_TEXTURE_EXTENSION;
     }
+#ifdef EGL_ANDROID_image_native_buffer
     if (strstr( gl_extensions, "GL_OES_EGL_image") &&
         (strstr(egl_extensions, "EGL_KHR_image_base") || 
                 strstr(egl_extensions, "EGL_KHR_image")) &&
         strstr(egl_extensions, "EGL_ANDROID_image_native_buffer")) {
         mFlags |= DIRECT_TEXTURE;
     }
+#else
+#warning "EGL_ANDROID_image_native_buffer not supported"
+#endif
 
     // Unbind the context from this thread
     eglMakeCurrent(display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
diff --git a/libs/surfaceflinger/Layer.cpp b/libs/surfaceflinger/Layer.cpp
index 7fd5434..f5a5a0b 100644
--- a/libs/surfaceflinger/Layer.cpp
+++ b/libs/surfaceflinger/Layer.cpp
@@ -134,87 +134,113 @@
 {
     Mutex::Autolock _l(mLock);
     sp<GraphicBuffer> buffer(getFrontBufferLocked());
-    if (LIKELY((mFlags & DisplayHardware::DIRECT_TEXTURE) &&
-            (buffer->usage & GRALLOC_USAGE_HW_TEXTURE))) {
-        int index = mFrontBufferIndex;
-        if (LIKELY(!mTextures[index].dirty)) {
-            glBindTexture(GL_TEXTURE_2D, mTextures[index].name);
+    int index = mFrontBufferIndex;
+
+    // create the new texture name if needed
+    if (UNLIKELY(mTextures[index].name == -1U)) {
+        mTextures[index].name = createTexture();
+        mTextures[index].width = 0;
+        mTextures[index].height = 0;
+    }
+
+#ifdef EGL_ANDROID_image_native_buffer
+    if (mFlags & DisplayHardware::DIRECT_TEXTURE) {
+        if (buffer->usage & GraphicBuffer::USAGE_HW_TEXTURE) {
+            if (mTextures[index].dirty) {
+                initializeEglImage(buffer, &mTextures[index]);
+            }
         } else {
-            // we need to recreate the texture
-            EGLDisplay dpy(mFlinger->graphicPlane(0).getEGLDisplay());
-            
-            // create the new texture name if needed
-            if (UNLIKELY(mTextures[index].name == -1U)) {
-                mTextures[index].name = createTexture();
-            } else {
-                glBindTexture(GL_TEXTURE_2D, mTextures[index].name);
+            if (mHybridBuffer==0 || (mHybridBuffer->width != buffer->width ||
+                    mHybridBuffer->height != buffer->height)) {
+                mHybridBuffer.clear();
+                mHybridBuffer = new GraphicBuffer(
+                        buffer->width, buffer->height, buffer->format,
+                        GraphicBuffer::USAGE_SW_WRITE_OFTEN |
+                        GraphicBuffer::USAGE_HW_TEXTURE);
+                initializeEglImage(
+                        mHybridBuffer, &mTextures[0]);
             }
 
-            // free the previous image
-            if (mTextures[index].image != EGL_NO_IMAGE_KHR) {
-                eglDestroyImageKHR(dpy, mTextures[index].image);
-                mTextures[index].image = EGL_NO_IMAGE_KHR;
-            }
-            
-            // construct an EGL_NATIVE_BUFFER_ANDROID
-            android_native_buffer_t* clientBuf = buffer->getNativeBuffer();
-            
-            // create the new EGLImageKHR
-            const EGLint attrs[] = { 
-                    EGL_IMAGE_PRESERVED_KHR,    EGL_TRUE, 
-                    EGL_NONE,                   EGL_NONE 
-            };
-            mTextures[index].image = eglCreateImageKHR(
-                    dpy, EGL_NO_CONTEXT, EGL_NATIVE_BUFFER_ANDROID,
-                    (EGLClientBuffer)clientBuf, attrs);
+            GGLSurface t;
+            status_t res = buffer->lock(&t, GRALLOC_USAGE_SW_READ_OFTEN);
+            LOGE_IF(res, "error %d (%s) locking buffer %p",
+                    res, strerror(res), buffer.get());
+            if (res == NO_ERROR) {
+                Texture* const texture(&mTextures[0]);
 
-            LOGE_IF(mTextures[index].image == EGL_NO_IMAGE_KHR,
-                    "eglCreateImageKHR() failed. err=0x%4x",
-                    eglGetError());
-            
-            if (mTextures[index].image != EGL_NO_IMAGE_KHR) {
-                glEGLImageTargetTexture2DOES(GL_TEXTURE_2D, 
-                        (GLeglImageOES)mTextures[index].image);
-                GLint error = glGetError();
-                if (UNLIKELY(error != GL_NO_ERROR)) {
-                    // this failed, for instance, because we don't support
-                    // NPOT.
-                    // FIXME: do something!
-                    LOGD("layer=%p, glEGLImageTargetTexture2DOES(%p) "
-                         "failed err=0x%04x",
-                         this, mTextures[index].image, error);
-                    mFlags &= ~DisplayHardware::DIRECT_TEXTURE;
-                } else {
-                    // Everything went okay!
-                    mTextures[index].NPOTAdjust = false;
-                    mTextures[index].dirty  = false;
-                    mTextures[index].width  = clientBuf->width;
-                    mTextures[index].height = clientBuf->height;
+                glBindTexture(GL_TEXTURE_2D, texture->name);
+
+                sp<GraphicBuffer> buf(mHybridBuffer);
+                void* vaddr;
+                res = buf->lock(GraphicBuffer::USAGE_SW_WRITE_OFTEN, &vaddr);
+                if (res == NO_ERROR) {
+                    int bpp = 0;
+                    switch (t.format) {
+                    case GGL_PIXEL_FORMAT_RGB_565:
+                    case GGL_PIXEL_FORMAT_RGBA_4444:
+                        bpp = 2;
+                        break;
+                    case GGL_PIXEL_FORMAT_RGBA_8888:
+                    case GGL_PIXEL_FORMAT_RGBX_8888:
+                        bpp = 4;
+                        break;
+                    case GGL_PIXEL_FORMAT_YCbCr_422_SP:
+                    case GGL_PIXEL_FORMAT_YCbCr_420_SP:
+                        // just show the Y plane of YUV buffers
+                        bpp = 1;
+                        break;
+                    default:
+                        // oops, we don't handle this format!
+                        LOGE("layer %p, texture=%d, using format %d, which is not "
+                                "supported by the GL", this, texture->name, t.format);
+                    }
+                    if (bpp) {
+                        const Rect bounds(dirty.getBounds());
+                        size_t src_stride = t.stride;
+                        size_t dst_stride = buf->stride;
+                        if (src_stride == dst_stride &&
+                            bounds.width() == t.width &&
+                            bounds.height() == t.height)
+                        {
+                            memcpy(vaddr, t.data, t.height * t.stride * bpp);
+                        } else {
+                            GLubyte const * src = t.data +
+                                (bounds.left + bounds.top * src_stride) * bpp;
+                            GLubyte * dst = (GLubyte *)vaddr +
+                                (bounds.left + bounds.top * dst_stride) * bpp;
+                            const size_t length = bounds.width() * bpp;
+                            size_t h = bounds.height();
+                            src_stride *= bpp;
+                            dst_stride *= bpp;
+                            while (h--) {
+                                memcpy(dst, src, length);
+                                dst += dst_stride;
+                                src += src_stride;
+                            }
+                        }
+                    }
+                    buf->unlock();
                 }
-            }                
+                buffer->unlock();
+            }
         }
-    } else {
-        for (size_t i=0 ; i<NUM_BUFFERS ; i++)
+    } else
+#endif
+    {
+        for (size_t i=0 ; i<NUM_BUFFERS ; i++) {
             mTextures[i].image = EGL_NO_IMAGE_KHR;
-
+        }
         GGLSurface t;
         status_t res = buffer->lock(&t, GRALLOC_USAGE_SW_READ_OFTEN);
         LOGE_IF(res, "error %d (%s) locking buffer %p",
                 res, strerror(res), buffer.get());
-        
         if (res == NO_ERROR) {
-            if (UNLIKELY(mTextures[0].name == -1U)) {
-                mTextures[0].name = createTexture();
-                mTextures[0].width = 0;
-                mTextures[0].height = 0;
-            }
             loadTexture(&mTextures[0], dirty, t);
             buffer->unlock();
         }
     }
 }
 
-
 void Layer::onDraw(const Region& clip) const
 {
     int index = mFrontBufferIndex;
diff --git a/libs/surfaceflinger/Layer.h b/libs/surfaceflinger/Layer.h
index 702c51a..1310ecc 100644
--- a/libs/surfaceflinger/Layer.h
+++ b/libs/surfaceflinger/Layer.h
@@ -118,6 +118,7 @@
             // protected by mLock
             sp<GraphicBuffer> mBuffers[NUM_BUFFERS];
             Texture         mTextures[NUM_BUFFERS];
+            sp<GraphicBuffer> mHybridBuffer;
             uint32_t        mWidth;
             uint32_t        mHeight;
             
diff --git a/libs/surfaceflinger/LayerBase.cpp b/libs/surfaceflinger/LayerBase.cpp
index b376e72..8003d22 100644
--- a/libs/surfaceflinger/LayerBase.cpp
+++ b/libs/surfaceflinger/LayerBase.cpp
@@ -507,7 +507,7 @@
         // uh?
         return;
     }
-    
+
     glBindTexture(GL_TEXTURE_2D, texture->name);
 
     /*
@@ -617,6 +617,63 @@
     }
 }
 
+status_t LayerBase::initializeEglImage(
+        const sp<GraphicBuffer>& buffer, Texture* texture)
+{
+    status_t err = NO_ERROR;
+
+    // we need to recreate the texture
+    EGLDisplay dpy(mFlinger->graphicPlane(0).getEGLDisplay());
+
+    // free the previous image
+    if (texture->image != EGL_NO_IMAGE_KHR) {
+        eglDestroyImageKHR(dpy, texture->image);
+        texture->image = EGL_NO_IMAGE_KHR;
+    }
+
+    // construct an EGL_NATIVE_BUFFER_ANDROID
+    android_native_buffer_t* clientBuf = buffer->getNativeBuffer();
+
+    // create the new EGLImageKHR
+    const EGLint attrs[] = {
+            EGL_IMAGE_PRESERVED_KHR,    EGL_TRUE,
+            EGL_NONE,                   EGL_NONE
+    };
+    texture->image = eglCreateImageKHR(
+            dpy, EGL_NO_CONTEXT, EGL_NATIVE_BUFFER_ANDROID,
+            (EGLClientBuffer)clientBuf, attrs);
+
+    LOGE_IF(texture->image == EGL_NO_IMAGE_KHR,
+            "eglCreateImageKHR() failed. err=0x%4x",
+            eglGetError());
+
+    if (texture->image != EGL_NO_IMAGE_KHR) {
+        glBindTexture(GL_TEXTURE_2D, texture->name);
+        glEGLImageTargetTexture2DOES(GL_TEXTURE_2D,
+                (GLeglImageOES)texture->image);
+        GLint error = glGetError();
+        if (UNLIKELY(error != GL_NO_ERROR)) {
+            // this failed, for instance, because we don't support NPOT.
+            // FIXME: do something!
+            LOGE("layer=%p, glEGLImageTargetTexture2DOES(%p) "
+                 "failed err=0x%04x",
+                 this, texture->image, error);
+            mFlags &= ~DisplayHardware::DIRECT_TEXTURE;
+            err = INVALID_OPERATION;
+        } else {
+            // Everything went okay!
+            texture->NPOTAdjust = false;
+            texture->dirty  = false;
+            texture->width  = clientBuf->width;
+            texture->height = clientBuf->height;
+        }
+    } else {
+        err = INVALID_OPERATION;
+    }
+    return err;
+}
+
+
 // ---------------------------------------------------------------------------
 
 int32_t LayerBaseClient::sIdentity = 0;
diff --git a/libs/surfaceflinger/LayerBase.h b/libs/surfaceflinger/LayerBase.h
index efa4f8c..ed07b3f 100644
--- a/libs/surfaceflinger/LayerBase.h
+++ b/libs/surfaceflinger/LayerBase.h
@@ -261,6 +261,8 @@
           void drawWithOpenGL(const Region& clip, const Texture& texture) const;
           void loadTexture(Texture* texture, 
                   const Region& dirty, const GGLSurface& t) const;
+          status_t initializeEglImage(
+                  const sp<GraphicBuffer>& buffer, Texture* texture);
 
           
                 sp<SurfaceFlinger> mFlinger;
diff --git a/libs/surfaceflinger/LayerBlur.cpp b/libs/surfaceflinger/LayerBlur.cpp
index 744f2e9..5d4a38b 100644
--- a/libs/surfaceflinger/LayerBlur.cpp
+++ b/libs/surfaceflinger/LayerBlur.cpp
@@ -40,9 +40,10 @@
 
 LayerBlur::LayerBlur(SurfaceFlinger* flinger, DisplayID display,
         const sp<Client>& client, int32_t i)
-: LayerBaseClient(flinger, display, client, i), mCacheDirty(true),
-mRefreshCache(true), mCacheAge(0), mTextureName(-1U), 
-mWidthScale(1.0f), mHeightScale(1.0f)
+    : LayerBaseClient(flinger, display, client, i), mCacheDirty(true),
+          mRefreshCache(true), mCacheAge(0), mTextureName(-1U),
+          mWidthScale(1.0f), mHeightScale(1.0f),
+          mBlurFormat(GGL_PIXEL_FORMAT_RGB_565)
 {
 }
 
@@ -168,6 +169,7 @@
             // This reads the frame-buffer, so a h/w GL would have to
             // finish() its rendering first. we don't want to do that
             // too often. Read data is 4-bytes aligned.
+            glFinish();
             glReadPixels(X, Y, w, h, mReadFormat, mReadType, pixels);
 
             // blur that texture.
diff --git a/libs/surfaceflinger/LayerBuffer.cpp b/libs/surfaceflinger/LayerBuffer.cpp
index 7e27a02..28d7c48 100644
--- a/libs/surfaceflinger/LayerBuffer.cpp
+++ b/libs/surfaceflinger/LayerBuffer.cpp
@@ -26,6 +26,8 @@
 #include <ui/GraphicBuffer.h>
 #include <ui/PixelFormat.h>
 #include <ui/FramebufferNativeWindow.h>
+#include <ui/Rect.h>
+#include <ui/Region.h>
 
 #include <hardware/copybit.h>
 
@@ -33,26 +35,28 @@
 #include "SurfaceFlinger.h"
 #include "DisplayHardware/DisplayHardware.h"
 
-#include "gralloc_priv.h"   // needed for msm / copybit
-
 namespace android {
 
 // ---------------------------------------------------------------------------
 
 const uint32_t LayerBuffer::typeInfo = LayerBaseClient::typeInfo | 0x20;
 const char* const LayerBuffer::typeID = "LayerBuffer";
+gralloc_module_t const* LayerBuffer::sGrallocModule = 0;
 
 // ---------------------------------------------------------------------------
 
 LayerBuffer::LayerBuffer(SurfaceFlinger* flinger, DisplayID display,
         const sp<Client>& client, int32_t i)
     : LayerBaseClient(flinger, display, client, i),
-      mNeedsBlending(false)
+      mNeedsBlending(false), mBlitEngine(0)
 {
 }
 
 LayerBuffer::~LayerBuffer()
 {
+    if (mBlitEngine) {
+        copybit_close(mBlitEngine);
+    }
 }
 
 void LayerBuffer::onFirstRef()
@@ -60,6 +64,20 @@
     LayerBaseClient::onFirstRef();
     mSurface = new SurfaceLayerBuffer(mFlinger, clientIndex(),
             const_cast<LayerBuffer *>(this));
+
+    hw_module_t const* module = (hw_module_t const*)sGrallocModule;
+    if (!module) {
+        // NOTE: technically there is a race here, but it shouldn't
+        // cause any problem since hw_get_module() always returns
+        // the same value.
+        if (hw_get_module(GRALLOC_HARDWARE_MODULE_ID, &module) == 0) {
+            sGrallocModule = (gralloc_module_t const *)module;
+        }
+    }
+
+    if (hw_get_module(COPYBIT_HARDWARE_MODULE_ID, &module) == 0) {
+        copybit_open(module, &mBlitEngine);
+    }
 }
 
 sp<LayerBaseClient::Surface> LayerBuffer::createSurface() const
@@ -243,30 +261,36 @@
     : mBufferHeap(buffers)
 {
     NativeBuffer& src(mNativeBuffer);
-    
-    src.crop.l = 0;
-    src.crop.t = 0;
-    src.crop.r = buffers.w;
-    src.crop.b = buffers.h;
-    
-    src.img.w       = buffers.hor_stride ?: buffers.w;
-    src.img.h       = buffers.ver_stride ?: buffers.h;
-    src.img.format  = buffers.format;
-    src.img.base    = (void*)(intptr_t(buffers.heap->base()) + offset);
+    src.img.handle = 0;
 
-    // FIXME: gross hack, we should never access private_handle_t from here,
-    // but this is needed by msm drivers
-    private_handle_t* hnd = new private_handle_t(
-            buffers.heap->heapID(), buffers.heap->getSize(), 0);
-    hnd->offset = offset;
-    src.img.handle = hnd;
+    gralloc_module_t const * module = LayerBuffer::getGrallocModule();
+    if (module && module->perform) {
+        int err = module->perform(module,
+                GRALLOC_MODULE_PERFORM_CREATE_HANDLE_FROM_BUFFER,
+                buffers.heap->heapID(), buffers.heap->getSize(),
+                offset, buffers.heap->base(),
+                &src.img.handle);
+
+        if (err == NO_ERROR) {
+            src.crop.l = 0;
+            src.crop.t = 0;
+            src.crop.r = buffers.w;
+            src.crop.b = buffers.h;
+
+            src.img.w       = buffers.hor_stride ?: buffers.w;
+            src.img.h       = buffers.ver_stride ?: buffers.h;
+            src.img.format  = buffers.format;
+            src.img.base    = (void*)(intptr_t(buffers.heap->base()) + offset);
+        }
+    }
 }
 
 LayerBuffer::Buffer::~Buffer()
 {
     NativeBuffer& src(mNativeBuffer);
-    if (src.img.handle)
-        delete (private_handle_t*)src.img.handle;
+    if (src.img.handle) {
+        native_handle_delete(src.img.handle);
+    }
 }
 
 // ============================================================================
@@ -335,16 +359,39 @@
         return;
     }
 
+    if (mLayer.mBlitEngine) {
+        // create our temporary buffer and corresponding EGLImageKHR.
+        // note that the size of this buffer doesn't really matter,
+        // the final image will always be drawn with proper aspect ratio.
+
+        int w = buffers.w;
+        int h = buffers.h;
+        mTempGraphicBuffer.clear();
+        mTempGraphicBuffer = new GraphicBuffer(
+                w, h, HAL_PIXEL_FORMAT_RGBX_8888,
+                GraphicBuffer::USAGE_HW_TEXTURE |
+                GraphicBuffer::USAGE_HW_2D);
+
+        if (mTempGraphicBuffer->initCheck() == NO_ERROR) {
+            NativeBuffer& dst(mTempBuffer);
+            dst.img.w = mTempGraphicBuffer->getStride();
+            dst.img.h = mTempGraphicBuffer->getHeight();
+            dst.img.format = mTempGraphicBuffer->getPixelFormat();
+            dst.img.handle = (native_handle_t *)mTempGraphicBuffer->handle;
+            dst.img.base = 0;
+            dst.crop.l = 0;
+            dst.crop.t = 0;
+            dst.crop.r = mTempGraphicBuffer->getWidth();
+            dst.crop.b = mTempGraphicBuffer->getHeight();
+        } else {
+            mTempGraphicBuffer.clear();
+        }
+    }
+
     mBufferHeap = buffers;
     mLayer.setNeedsBlending((info.h_alpha - info.l_alpha) > 0);    
     mBufferSize = info.getScanlineSize(buffers.hor_stride)*buffers.ver_stride;
     mLayer.forceVisibilityTransaction();
-
-    hw_module_t const* module;
-    mBlitEngine = NULL;
-    if (hw_get_module(COPYBIT_HARDWARE_MODULE_ID, &module) == 0) {
-        copybit_open(module, &mBlitEngine);
-    }
 }
 
 LayerBuffer::BufferSource::~BufferSource()
@@ -352,8 +399,9 @@
     if (mTexture.name != -1U) {
         glDeleteTextures(1, &mTexture.name);
     }
-    if (mBlitEngine) {
-        copybit_close(mBlitEngine);
+    if (mTexture.image != EGL_NO_IMAGE_KHR) {
+        EGLDisplay dpy(mLayer.mFlinger->graphicPlane(0).getEGLDisplay());
+        eglDestroyImageKHR(dpy, mTexture.image);
     }
 }
 
@@ -421,124 +469,50 @@
     status_t err = NO_ERROR;
     NativeBuffer src(ourBuffer->getBuffer());
     const Rect transformedBounds(mLayer.getTransformedBounds());
-    copybit_device_t* copybit = mBlitEngine;
 
-    if (copybit)  {
-        const int src_width  = src.crop.r - src.crop.l;
-        const int src_height = src.crop.b - src.crop.t;
-        int W = transformedBounds.width();
-        int H = transformedBounds.height();
-        if (mLayer.getOrientation() & Transform::ROT_90) {
-            int t(W); W=H; H=t;
-        }
+    if (UNLIKELY(mTexture.name == -1LU)) {
+        mTexture.name = mLayer.createTexture();
+    }
 
-#ifdef EGL_ANDROID_get_render_buffer
-        EGLDisplay dpy = eglGetCurrentDisplay();
-        EGLSurface draw = eglGetCurrentSurface(EGL_DRAW); 
-        EGLClientBuffer clientBuf = eglGetRenderBufferANDROID(dpy, draw);
-        android_native_buffer_t* nb = (android_native_buffer_t*)clientBuf;
-        if (nb == 0) {
-            err = BAD_VALUE;
+#if defined(EGL_ANDROID_image_native_buffer)
+    if (mLayer.mFlags & DisplayHardware::DIRECT_TEXTURE) {
+        copybit_device_t* copybit = mLayer.mBlitEngine;
+        if (copybit) {
+            // create our EGLImageKHR the first time
+            if (mTexture.image == EGL_NO_IMAGE_KHR) {
+                err = NO_MEMORY;
+                if (mTempGraphicBuffer!=0) {
+                    err = mLayer.initializeEglImage(
+                            mTempGraphicBuffer, &mTexture);
+                    // once the EGLImage has been created (whether it fails
+                    // or not) we don't need the graphic buffer reference
+                    // anymore.
+                    mTempGraphicBuffer.clear();
+                }
+            }
+
+            if (err == NO_ERROR) {
+                // NOTE: Assume the buffer is allocated with the proper USAGE flags
+                const NativeBuffer& dst(mTempBuffer);
+                region_iterator clip(Region(Rect(dst.crop.r, dst.crop.b)));
+                copybit->set_parameter(copybit, COPYBIT_TRANSFORM, 0);
+                copybit->set_parameter(copybit, COPYBIT_PLANE_ALPHA, 0xFF);
+                copybit->set_parameter(copybit, COPYBIT_DITHER, COPYBIT_ENABLE);
+                err = copybit->stretch(copybit, &dst.img, &src.img,
+                        &dst.crop, &src.crop, &clip);
+
+            }
         } else {
-            copybit_image_t dst;
-            dst.w       = nb->width;
-            dst.h       = nb->height;
-            dst.format  = nb->format;
-            dst.base    = NULL; // unused by copybit on msm7k
-            dst.handle  = (native_handle_t *)nb->handle;
-
-            /* With LayerBuffer, it is likely that we'll have to rescale the
-             * surface, because this is often used for video playback or
-             * camera-preview. Since we want these operation as fast as possible
-             * we make sure we can use the 2D H/W even if it doesn't support
-             * the requested scale factor, in which case we perform the scaling
-             * in several passes. */
-
-            const float min = copybit->get(copybit, COPYBIT_MINIFICATION_LIMIT);
-            const float mag = copybit->get(copybit, COPYBIT_MAGNIFICATION_LIMIT);
-
-            float xscale = 1.0f;
-            if (src_width > W*min)          xscale = 1.0f / min;
-            else if (src_width*mag < W)     xscale = mag;
-
-            float yscale = 1.0f;
-            if (src_height > H*min)         yscale = 1.0f / min;
-            else if (src_height*mag < H)    yscale = mag;
-
-            if (UNLIKELY(xscale!=1.0f || yscale!=1.0f)) {
-                const int tmp_w = floorf(src_width  * xscale);
-                const int tmp_h = floorf(src_height * yscale);
-                
-                if (mTempBitmap==0 || 
-                        mTempBitmap->getWidth() < size_t(tmp_w) || 
-                        mTempBitmap->getHeight() < size_t(tmp_h)) {
-                    mTempBitmap.clear();
-                    mTempBitmap = new GraphicBuffer(
-                            tmp_w, tmp_h, src.img.format, 
-                            GraphicBuffer::USAGE_HW_2D);
-                    err = mTempBitmap->initCheck();
-                }
-
-                if (LIKELY(err == NO_ERROR)) {
-                    NativeBuffer tmp;
-                    tmp.img.w = tmp_w;
-                    tmp.img.h = tmp_h;
-                    tmp.img.format = src.img.format;
-                    tmp.img.handle = (native_handle_t*)mTempBitmap->getNativeBuffer()->handle;
-                    tmp.crop.l = 0;
-                    tmp.crop.t = 0;
-                    tmp.crop.r = tmp.img.w;
-                    tmp.crop.b = tmp.img.h;
-
-                    region_iterator tmp_it(Region(Rect(tmp.crop.r, tmp.crop.b)));
-                    copybit->set_parameter(copybit, COPYBIT_TRANSFORM, 0);
-                    copybit->set_parameter(copybit, COPYBIT_PLANE_ALPHA, 0xFF);
-                    copybit->set_parameter(copybit, COPYBIT_DITHER, COPYBIT_DISABLE);
-                    err = copybit->stretch(copybit,
-                            &tmp.img, &src.img, &tmp.crop, &src.crop, &tmp_it);
-                    src = tmp;
-                }
-            }
-
-            const Rect transformedBounds(mLayer.getTransformedBounds());
-            const copybit_rect_t& drect =
-                reinterpret_cast<const copybit_rect_t&>(transformedBounds);
-            const State& s(mLayer.drawingState());
-            region_iterator it(clip);
-
-            // pick the right orientation for this buffer
-            int orientation = mLayer.getOrientation();
-            if (UNLIKELY(mBufferHeap.transform)) {
-                Transform rot90;
-                GraphicPlane::orientationToTransfrom(
-                        ISurfaceComposer::eOrientation90, 0, 0, &rot90);
-                const Transform& planeTransform(mLayer.graphicPlane(0).transform());
-                const Layer::State& s(mLayer.drawingState());
-                Transform tr(planeTransform * s.transform * rot90);
-                orientation = tr.getOrientation();
-            }
-
-            copybit->set_parameter(copybit, COPYBIT_TRANSFORM, orientation);
-            copybit->set_parameter(copybit, COPYBIT_PLANE_ALPHA, s.alpha);
-            copybit->set_parameter(copybit, COPYBIT_DITHER, COPYBIT_ENABLE);
-
-            err = copybit->stretch(copybit,
-                    &dst, &src.img, &drect, &src.crop, &it);
-            if (err != NO_ERROR) {
-                LOGE("copybit failed (%s)", strerror(err));
-            }
+            err = INVALID_OPERATION;
         }
     }
 #endif
-    
-    if (!copybit || err) 
-    {
-        // OpenGL fall-back
-        if (UNLIKELY(mTexture.name == -1LU)) {
-            mTexture.name = mLayer.createTexture();
-        }
-        GLuint w = 0;
-        GLuint h = 0;
+    else {
+        err = INVALID_OPERATION;
+    }
+
+    if (err != NO_ERROR) {
+        // slower fallback
         GGLSurface t;
         t.version = sizeof(GGLSurface);
         t.width  = src.crop.r;
@@ -549,11 +523,11 @@
         t.data = (GGLubyte*)src.img.base;
         const Region dirty(Rect(t.width, t.height));
         mLayer.loadTexture(&mTexture, dirty, t);
-        mTexture.transform = mBufferHeap.transform;
-        mLayer.drawWithOpenGL(clip, mTexture);
     }
-}
 
+    mTexture.transform = mBufferHeap.transform;
+    mLayer.drawWithOpenGL(clip, mTexture);
+}
 
 // ---------------------------------------------------------------------------
 
diff --git a/libs/surfaceflinger/LayerBuffer.h b/libs/surfaceflinger/LayerBuffer.h
index 5eb472c..1abb103 100644
--- a/libs/surfaceflinger/LayerBuffer.h
+++ b/libs/surfaceflinger/LayerBuffer.h
@@ -91,6 +91,11 @@
         copybit_rect_t    crop;
     };
 
+    static gralloc_module_t const* sGrallocModule;
+    static gralloc_module_t const* getGrallocModule() {
+        return sGrallocModule;
+    }
+
     class Buffer : public LightRefBase<Buffer> {
     public:
         Buffer(const ISurface::BufferHeap& buffers, ssize_t offset);
@@ -130,9 +135,9 @@
         status_t                        mStatus;
         ISurface::BufferHeap            mBufferHeap;
         size_t                          mBufferSize;
-        mutable sp<GraphicBuffer>       mTempBitmap;
         mutable LayerBase::Texture      mTexture;
-        copybit_device_t*               mBlitEngine;
+        NativeBuffer                    mTempBuffer;
+        mutable sp<GraphicBuffer>       mTempGraphicBuffer;
     };
     
     class OverlaySource : public Source {
@@ -201,6 +206,7 @@
     sp<Surface>     mSurface;
     bool            mInvalidate;
     bool            mNeedsBlending;
+    copybit_device_t* mBlitEngine;
 };
 
 // ---------------------------------------------------------------------------
diff --git a/libs/surfaceflinger/LayerDim.cpp b/libs/surfaceflinger/LayerDim.cpp
index 538dc77..fd61e30 100644
--- a/libs/surfaceflinger/LayerDim.cpp
+++ b/libs/surfaceflinger/LayerDim.cpp
@@ -55,8 +55,8 @@
     sHeight = h;
     sUseTexture = false;
     
-#ifdef DIM_WITH_TEXTURE
-    
+#if defined(DIM_WITH_TEXTURE) && defined(EGL_ANDROID_image_native_buffer)
+
 #warning "using a texture to implement LayerDim"
     
     /* On some h/w like msm7K, it is faster to use a texture because the
@@ -69,7 +69,6 @@
     uint32_t flags = hw.getFlags();
 
     if (LIKELY(flags & DisplayHardware::DIRECT_TEXTURE)) {
-        // TODO: api to pass the usage flags
         sp<GraphicBuffer> buffer = new GraphicBuffer(w, h, PIXEL_FORMAT_RGB_565,
                  GraphicBuffer::USAGE_SW_WRITE_OFTEN |
                  GraphicBuffer::USAGE_HW_TEXTURE);
@@ -123,7 +122,7 @@
         glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
         glColor4x(0, 0, 0, alpha);
         
-#ifdef DIM_WITH_TEXTURE
+#if defined(DIM_WITH_TEXTURE) && defined(EGL_ANDROID_image_native_buffer)
         if (sUseTexture) {
             glBindTexture(GL_TEXTURE_2D, sTexId);
             glEnable(GL_TEXTURE_2D);
diff --git a/libs/surfaceflinger/SurfaceFlinger.h b/libs/surfaceflinger/SurfaceFlinger.h
index 6698e00..f9bfe6c 100644
--- a/libs/surfaceflinger/SurfaceFlinger.h
+++ b/libs/surfaceflinger/SurfaceFlinger.h
@@ -246,8 +246,10 @@
     virtual status_t    readyToRun();
     virtual void        onFirstRef();
 
+public:     // hack to work around gcc 4.0.3 bug
     const GraphicPlane&     graphicPlane(int dpy) const;
           GraphicPlane&     graphicPlane(int dpy);
+private:
 
             void        waitForEvent();
 public:     // hack to work around gcc 4.0.3 bug
diff --git a/libs/ui/GraphicBuffer.cpp b/libs/ui/GraphicBuffer.cpp
index 1cf20d7..6a5c8a9 100644
--- a/libs/ui/GraphicBuffer.cpp
+++ b/libs/ui/GraphicBuffer.cpp
@@ -37,7 +37,7 @@
 // ===========================================================================
 
 GraphicBuffer::GraphicBuffer()
-    : BASE(), mOwner(false), mBufferMapper(GraphicBufferMapper::get()),
+    : BASE(), mOwner(ownData), mBufferMapper(GraphicBufferMapper::get()),
       mInitCheck(NO_ERROR),  mVStride(0), mIndex(-1)
 {
     width  = 
@@ -50,7 +50,7 @@
 
 GraphicBuffer::GraphicBuffer(uint32_t w, uint32_t h, 
         PixelFormat reqFormat, uint32_t reqUsage)
-    : BASE(), mOwner(false), mBufferMapper(GraphicBufferMapper::get()),
+    : BASE(), mOwner(ownData), mBufferMapper(GraphicBufferMapper::get()),
       mInitCheck(NO_ERROR),  mVStride(0), mIndex(-1)
 {
     width  = 
@@ -62,8 +62,23 @@
     mInitCheck = initSize(w, h, reqFormat, reqUsage);
 }
 
+GraphicBuffer::GraphicBuffer(uint32_t w, uint32_t h,
+        PixelFormat inFormat, uint32_t inUsage,
+        uint32_t inStride, native_handle_t* inHandle, bool keepOwnership)
+    : BASE(), mOwner(keepOwnership ? ownHandle : ownNone),
+      mBufferMapper(GraphicBufferMapper::get()),
+      mInitCheck(NO_ERROR),  mVStride(0), mIndex(-1)
+{
+    width  = w;
+    height = h;
+    stride = inStride;
+    format = inFormat;
+    usage  = inUsage;
+    handle = inHandle;
+}
+
 GraphicBuffer::GraphicBuffer(const Parcel& data) 
-    : BASE(), mOwner(true), mBufferMapper(GraphicBufferMapper::get()),
+    : BASE(), mOwner(ownHandle), mBufferMapper(GraphicBufferMapper::get()),
       mInitCheck(NO_ERROR),  mVStride(0), mIndex(-1)
 {
     // we own the handle in this case
@@ -83,10 +98,10 @@
 GraphicBuffer::~GraphicBuffer()
 {
     if (handle) {
-        if (mOwner) {
+        if (mOwner == ownHandle) {
             native_handle_close(handle);
             native_handle_delete(const_cast<native_handle*>(handle));
-        } else {
+        } else if (mOwner == ownData) {
             GraphicBufferAllocator& allocator(GraphicBufferAllocator::get());
             allocator.free(handle);
         }
@@ -106,6 +121,9 @@
 status_t GraphicBuffer::reallocate(uint32_t w, uint32_t h, PixelFormat f,
         uint32_t reqUsage)
 {
+    if (mOwner != ownData)
+        return INVALID_OPERATION;
+
     if (handle) {
         GraphicBufferAllocator& allocator(GraphicBufferAllocator::get());
         allocator.free(handle);
@@ -208,6 +226,14 @@
     return mIndex;
 }
 
+void GraphicBuffer::setVerticalStride(uint32_t vstride) {
+    mVStride = vstride;
+}
+
+uint32_t GraphicBuffer::getVerticalStride() const {
+    return mVStride;
+}
+
 // ---------------------------------------------------------------------------
 
 }; // namespace android
diff --git a/libs/ui/Surface.cpp b/libs/ui/Surface.cpp
index f51ca7a..24ae27f 100644
--- a/libs/ui/Surface.cpp
+++ b/libs/ui/Surface.cpp
@@ -152,96 +152,85 @@
 
 status_t SurfaceControl::setLayer(int32_t layer) {
     const sp<SurfaceComposerClient>& client(mClient);
-    if (client == 0) return NO_INIT;
-    status_t err = validate(client->mControl);
+    status_t err = validate();
     if (err < 0) return err;
     return client->setLayer(mToken, layer);
 }
 status_t SurfaceControl::setPosition(int32_t x, int32_t y) {
     const sp<SurfaceComposerClient>& client(mClient);
-    if (client == 0) return NO_INIT;
-    status_t err = validate(client->mControl);
+    status_t err = validate();
     if (err < 0) return err;
     return client->setPosition(mToken, x, y);
 }
 status_t SurfaceControl::setSize(uint32_t w, uint32_t h) {
     const sp<SurfaceComposerClient>& client(mClient);
-    if (client == 0) return NO_INIT;
-    status_t err = validate(client->mControl);
+    status_t err = validate();
     if (err < 0) return err;
     return client->setSize(mToken, w, h);
 }
 status_t SurfaceControl::hide() {
     const sp<SurfaceComposerClient>& client(mClient);
-    if (client == 0) return NO_INIT;
-    status_t err = validate(client->mControl);
+    status_t err = validate();
     if (err < 0) return err;
     return client->hide(mToken);
 }
 status_t SurfaceControl::show(int32_t layer) {
     const sp<SurfaceComposerClient>& client(mClient);
-    if (client == 0) return NO_INIT;
-    status_t err = validate(client->mControl);
+    status_t err = validate();
     if (err < 0) return err;
     return client->show(mToken, layer);
 }
 status_t SurfaceControl::freeze() {
     const sp<SurfaceComposerClient>& client(mClient);
-    if (client == 0) return NO_INIT;
-    status_t err = validate(client->mControl);
+    status_t err = validate();
     if (err < 0) return err;
     return client->freeze(mToken);
 }
 status_t SurfaceControl::unfreeze() {
     const sp<SurfaceComposerClient>& client(mClient);
-    if (client == 0) return NO_INIT;
-    status_t err = validate(client->mControl);
+    status_t err = validate();
     if (err < 0) return err;
     return client->unfreeze(mToken);
 }
 status_t SurfaceControl::setFlags(uint32_t flags, uint32_t mask) {
     const sp<SurfaceComposerClient>& client(mClient);
-    if (client == 0) return NO_INIT;
-    status_t err = validate(client->mControl);
+    status_t err = validate();
     if (err < 0) return err;
     return client->setFlags(mToken, flags, mask);
 }
 status_t SurfaceControl::setTransparentRegionHint(const Region& transparent) {
     const sp<SurfaceComposerClient>& client(mClient);
-    if (client == 0) return NO_INIT;
-    status_t err = validate(client->mControl);
+    status_t err = validate();
     if (err < 0) return err;
     return client->setTransparentRegionHint(mToken, transparent);
 }
 status_t SurfaceControl::setAlpha(float alpha) {
     const sp<SurfaceComposerClient>& client(mClient);
-    if (client == 0) return NO_INIT;
-    status_t err = validate(client->mControl);
+    status_t err = validate();
     if (err < 0) return err;
     return client->setAlpha(mToken, alpha);
 }
 status_t SurfaceControl::setMatrix(float dsdx, float dtdx, float dsdy, float dtdy) {
     const sp<SurfaceComposerClient>& client(mClient);
-    if (client == 0) return NO_INIT;
-    status_t err = validate(client->mControl);
+    status_t err = validate();
     if (err < 0) return err;
     return client->setMatrix(mToken, dsdx, dtdx, dsdy, dtdy);
 }
 status_t SurfaceControl::setFreezeTint(uint32_t tint) {
     const sp<SurfaceComposerClient>& client(mClient);
-    if (client == 0) return NO_INIT;
-    status_t err = validate(client->mControl);
+    status_t err = validate();
     if (err < 0) return err;
     return client->setFreezeTint(mToken, tint);
 }
 
-status_t SurfaceControl::validate(SharedClient const* cblk) const
+status_t SurfaceControl::validate() const
 {
     if (mToken<0 || mClient==0) {
         LOGE("invalid token (%d, identity=%u) or client (%p)", 
                 mToken, mIdentity, mClient.get());
         return NO_INIT;
     }
+    SharedClient const* cblk = mClient->mControl;
     if (cblk == 0) {
         LOGE("cblk is null (surface id=%d, identity=%u)", mToken, mIdentity);
         return NO_INIT;
@@ -394,7 +383,7 @@
     return mToken>=0 && mClient!=0;
 }
 
-status_t Surface::validate(SharedClient const* cblk) const
+status_t Surface::validate() const
 {
     sp<SurfaceComposerClient> client(getClient());
     if (mToken<0 || mClient==0) {
@@ -402,6 +391,7 @@
                 mToken, mIdentity, client.get());
         return NO_INIT;
     }
+    SharedClient const* cblk = mClient->mControl;
     if (cblk == 0) {
         LOGE("cblk is null (surface id=%d, identity=%u)", mToken, mIdentity);
         return NO_INIT;
@@ -488,7 +478,7 @@
 int Surface::dequeueBuffer(android_native_buffer_t** buffer)
 {
     sp<SurfaceComposerClient> client(getClient());
-    status_t err = validate(client->mControl);
+    status_t err = validate();
     if (err != NO_ERROR)
         return err;
 
@@ -533,7 +523,7 @@
 int Surface::lockBuffer(android_native_buffer_t* buffer)
 {
     sp<SurfaceComposerClient> client(getClient());
-    status_t err = validate(client->mControl);
+    status_t err = validate();
     if (err != NO_ERROR)
         return err;
 
@@ -546,7 +536,7 @@
 int Surface::queueBuffer(android_native_buffer_t* buffer)
 {   
     sp<SurfaceComposerClient> client(getClient());
-    status_t err = validate(client->mControl);
+    status_t err = validate();
     if (err != NO_ERROR)
         return err;
 
diff --git a/libs/ui/tests/region.cpp b/libs/ui/tests/region.cpp
index 0deb2ba..ef15de9 100644
--- a/libs/ui/tests/region.cpp
+++ b/libs/ui/tests/region.cpp
@@ -25,9 +25,16 @@
 
 int main()
 {
+    Region empty;
     Region reg0( Rect(  0, 0,  100, 100 ) );
     Region reg1 = reg0;
     Region reg2, reg3;
+
+    Region reg4 = empty | reg1;
+    Region reg5 = reg1 | empty;
+
+    reg4.dump("reg4");
+    reg5.dump("reg5");
     
     reg0.dump("reg0");
     reg1.dump("reg1");
diff --git a/opengl/libagl/Android.mk b/opengl/libagl/Android.mk
index 2522656..9837845 100644
--- a/opengl/libagl/Android.mk
+++ b/opengl/libagl/Android.mk
@@ -25,6 +25,13 @@
 	primitives.cpp.arm	        \
 	vertex.cpp.arm
 
+LOCAL_CFLAGS += -DLOG_TAG=\"libagl\"
+LOCAL_CFLAGS += -DGL_GLEXT_PROTOTYPES -DEGL_EGLEXT_PROTOTYPES
+LOCAL_CFLAGS += -fvisibility=hidden
+
+LOCAL_SHARED_LIBRARIES := libcutils libhardware libutils libpixelflinger
+LOCAL_LDLIBS := -lpthread -ldl
+
 ifeq ($(TARGET_ARCH),arm)
 	LOCAL_SRC_FILES += fixed_asm.S iterators.S
 	LOCAL_CFLAGS += -fstrict-aliasing
@@ -38,15 +45,9 @@
 ifeq ($(LIBAGL_USE_GRALLOC_COPYBITS),1)
     LOCAL_CFLAGS += -DLIBAGL_USE_GRALLOC_COPYBITS
     LOCAL_SRC_FILES += copybit.cpp
+    LOCAL_SHARED_LIBRARIES += libui
 endif
 
-LOCAL_CFLAGS += -DLOG_TAG=\"libagl\"
-LOCAL_CFLAGS += -DGL_GLEXT_PROTOTYPES -DEGL_EGLEXT_PROTOTYPES
-
-LOCAL_SHARED_LIBRARIES := libcutils libhardware libutils libpixelflinger
-LOCAL_CFLAGS += -fvisibility=hidden
-
-LOCAL_LDLIBS := -lpthread -ldl
 
 LOCAL_MODULE_PATH := $(TARGET_OUT_SHARED_LIBRARIES)/egl
 LOCAL_MODULE:= libGLES_android
diff --git a/opengl/libagl/copybit.cpp b/opengl/libagl/copybit.cpp
index 867459d..a68750e 100644
--- a/opengl/libagl/copybit.cpp
+++ b/opengl/libagl/copybit.cpp
@@ -33,6 +33,10 @@
 #include <hardware/copybit.h>
 #include <private/ui/android_natives_priv.h>
 
+#include <ui/GraphicBuffer.h>
+#include <ui/Region.h>
+#include <ui/Rect.h>
+
 
 #define DEBUG_COPYBIT true
 
@@ -41,13 +45,25 @@
 namespace android {
 
 static void textureToCopyBitImage(
-        const GGLSurface* surface, buffer_handle_t buffer, copybit_image_t* img) 
+        const GGLSurface* surface, int32_t opFormat, 
+        android_native_buffer_t* buffer, copybit_image_t* img)
 {
+    uint32_t vstride = 0;
+    if (opFormat == COPYBIT_FORMAT_YCbCr_422_SP ||
+            opFormat == COPYBIT_FORMAT_YCbCr_420_SP) {
+        // NOTE: this static_cast is really not safe b/c we can't know for
+        // sure the buffer passed is of the right type.
+        // However, since we do this only for YUV formats, we should be safe
+        // since only SurfaceFlinger makes use of them.
+        GraphicBuffer* graphicBuffer = static_cast<GraphicBuffer*>(buffer);
+        vstride = graphicBuffer->getVerticalStride();
+    }
+
     img->w      = surface->stride;
-    img->h      = surface->height;
-    img->format = surface->format;
+    img->h      = vstride ? vstride : surface->height;
+    img->format = opFormat;
     img->base   = surface->data;
-    img->handle = (native_handle_t *)buffer;
+    img->handle = (native_handle_t *)buffer->handle;
 }
 
 struct clipRectRegion : public copybit_region_t {
@@ -69,6 +85,7 @@
     static int iterate_done(copybit_region_t const *, copybit_rect_t*) {
         return 0;
     }
+public:
     copybit_rect_t r;
 };
 
@@ -149,6 +166,8 @@
         int transform,
         ogles_context_t* c)
 {
+    status_t err = NO_ERROR;
+
     // We assume checkContext has already been called and has already
     // returned true.
 
@@ -174,16 +193,6 @@
         dtdy /= screen_h;
     }
     dtdy = -dtdy; // see equation of dtdy above
-    if (dsdx < c->copybits.minScale || dsdx > c->copybits.maxScale
-            || dtdy < c->copybits.minScale || dtdy > c->copybits.maxScale) {
-        // The requested scale is out of the range the hardware
-        // can support.
-        LOGD_IF(DEBUG_COPYBIT,
-                "scale out of range dsdx=%08x (Wcr=%d / w=%d), "
-                "dtdy=%08x (Hcr=%d / h=%d), Ucr=%d, Vcr=%d", 
-                dsdx, Wcr, w, dtdy, Hcr, h, Ucr, Vcr);
-        return false;
-    }
 
     // copybit doesn't say anything about filtering, so we can't
     // discriminate. On msm7k, copybit will always filter.
@@ -205,41 +214,16 @@
     
     const uint32_t enables = c->rasterizer.state.enables;
     int planeAlpha = 255;
+    bool alphaPlaneWorkaround = false;
     static const int tmu = 0;
     texture_t& tev(c->rasterizer.state.texture[tmu]);
-    bool srcTextureHasAlpha = hasAlpha(textureObject->surface.format);
+    int32_t opFormat = textureObject->surface.format;
+    const bool srcTextureHasAlpha = hasAlpha(opFormat);
     if (!srcTextureHasAlpha) {
         planeAlpha = fixedToByte(c->currentColorClamped.a);
     }
 
-    switch (tev.env) {
-    case GGL_REPLACE:
-        break;
-    case GGL_MODULATE:
-        if (! (c->currentColorClamped.r == FIXED_ONE &&
-               c->currentColorClamped.g == FIXED_ONE &&
-               c->currentColorClamped.b == FIXED_ONE)) {
-            LOGD_IF(DEBUG_COPYBIT, 
-                    "MODULATE and non white color (%08x, %08x, %08x)",
-                    c->currentColorClamped.r,
-                    c->currentColorClamped.g,
-                    c->currentColorClamped.b);
-            return false;
-        }
-        if (srcTextureHasAlpha && c->currentColorClamped.a < FIXED_ONE) {
-            LOGD_IF(DEBUG_COPYBIT, 
-                    "MODULATE and texture w/alpha and alpha=%08x)",
-                    c->currentColorClamped.a);
-            return false;
-        }
-        break;
-
-    default:
-        // Incompatible texture environment.
-        LOGD_IF(DEBUG_COPYBIT, "incompatible texture environment");
-        return false;
-    }
-
+    const bool cbHasAlpha = hasAlpha(cbSurface.format);
     bool blending = false;
     if ((enables & GGL_ENABLE_BLENDING)
             && !(c->rasterizer.state.blend.src == GL_ONE
@@ -262,41 +246,228 @@
         }
         blending = true;
     } else {
-        // No blending is OK if we are not using alpha.
-        if (srcTextureHasAlpha || planeAlpha != 255) {
-            // Incompatible alpha
-            LOGD_IF(DEBUG_COPYBIT, "incompatible alpha");
-            return false;
+        if (cbHasAlpha) {
+            // NOTE: the result will be slightly wrong in this case because
+            // the destination alpha channel will be set to 1.0 instead of
+            // the iterated alpha value. *shrug*.
+        }
+        // disable plane blending and src blending for supported formats
+        planeAlpha = 255;
+        if (opFormat == COPYBIT_FORMAT_RGBA_8888) {
+            opFormat = COPYBIT_FORMAT_RGBX_8888;
+        } else {
+            if (srcTextureHasAlpha) {
+                LOGD_IF(DEBUG_COPYBIT, "texture format requires blending");
+                return false;
+            }
         }
     }
 
-    if (srcTextureHasAlpha && planeAlpha != 255) {
-        // Can't do two types of alpha at once.
-        LOGD_IF(DEBUG_COPYBIT, "src alpha and plane alpha");
+    switch (tev.env) {
+    case GGL_REPLACE:
+        break;
+    case GGL_MODULATE:
+        // only cases allowed is:
+        // RGB  source, color={1,1,1,a} -> can be done with GL_REPLACE
+        // RGBA source, color={1,1,1,1} -> can be done with GL_REPLACE
+        if (blending) {
+            if (c->currentColorClamped.r == c->currentColorClamped.a &&
+                c->currentColorClamped.g == c->currentColorClamped.a &&
+                c->currentColorClamped.b == c->currentColorClamped.a) {
+                // TODO: RGBA source, color={1,1,1,a} / regular-blending
+                // is equivalent
+                alphaPlaneWorkaround = true;
+                break;
+            }
+        }
+        LOGD_IF(DEBUG_COPYBIT, "GGL_MODULATE");
+        return false;
+    default:
+        // Incompatible texture environment.
+        LOGD_IF(DEBUG_COPYBIT, "incompatible texture environment");
         return false;
     }
 
-    // LOGW("calling copybits");
-
     copybit_device_t* copybit = c->copybits.blitEngine;
-
-    copybit_image_t dst;
-    buffer_handle_t target_hnd = c->copybits.drawSurfaceBuffer;
-    textureToCopyBitImage(&cbSurface, target_hnd, &dst);
-    copybit_rect_t drect = {x, y, x+w, y+h};
-
     copybit_image_t src;
-    buffer_handle_t source_hnd = textureObject->buffer->handle;
-    textureToCopyBitImage(&textureObject->surface, source_hnd, &src);
+    textureToCopyBitImage(&textureObject->surface, opFormat,
+            textureObject->buffer, &src);
     copybit_rect_t srect = { Ucr, Vcr + Hcr, Ucr + Wcr, Vcr };
 
-    copybit->set_parameter(copybit, COPYBIT_TRANSFORM, transform);
-    copybit->set_parameter(copybit, COPYBIT_PLANE_ALPHA, planeAlpha);
-    copybit->set_parameter(copybit, COPYBIT_DITHER,
-            (enables & GGL_ENABLE_DITHER) ? COPYBIT_ENABLE : COPYBIT_DISABLE);
+    /*
+     *  Below we perform extra passes needed to emulate things the h/w
+     * cannot do.
+     */
 
-    clipRectRegion it(c);
-    status_t err = copybit->stretch(copybit, &dst, &src, &drect, &srect, &it);
+    const GLfixed minScaleInv = gglDivQ(0x10000, c->copybits.minScale, 16);
+    const GLfixed maxScaleInv = gglDivQ(0x10000, c->copybits.maxScale, 16);
+
+    sp<GraphicBuffer> tempBitmap;
+
+    if (dsdx < maxScaleInv || dsdx > minScaleInv ||
+        dtdy < maxScaleInv || dtdy > minScaleInv)
+    {
+        // The requested scale is out of the range the hardware
+        // can support.
+        LOGD_IF(DEBUG_COPYBIT,
+                "scale out of range dsdx=%08x (Wcr=%d / w=%d), "
+                "dtdy=%08x (Hcr=%d / h=%d), Ucr=%d, Vcr=%d",
+                dsdx, Wcr, w, dtdy, Hcr, h, Ucr, Vcr);
+
+        int32_t xscale=0x10000, yscale=0x10000;
+        if (dsdx > minScaleInv)         xscale = c->copybits.minScale;
+        else if (dsdx < maxScaleInv)    xscale = c->copybits.maxScale;
+        if (dtdy > minScaleInv)         yscale = c->copybits.minScale;
+        else if (dtdy < maxScaleInv)    yscale = c->copybits.maxScale;
+        dsdx = gglMulx(dsdx, xscale);
+        dtdy = gglMulx(dtdy, yscale);
+
+        /* we handle only one step of resizing below. Handling an arbitrary
+         * number is relatively easy (replace "if" above by "while"), but requires
+         * two intermediate buffers and so far we never had the need.
+         */
+
+        if (dsdx < maxScaleInv || dsdx > minScaleInv ||
+            dtdy < maxScaleInv || dtdy > minScaleInv) {
+            LOGD_IF(DEBUG_COPYBIT,
+                    "scale out of range dsdx=%08x (Wcr=%d / w=%d), "
+                    "dtdy=%08x (Hcr=%d / h=%d), Ucr=%d, Vcr=%d",
+                    dsdx, Wcr, w, dtdy, Hcr, h, Ucr, Vcr);
+            return false;
+        }
+
+        const int tmp_w = gglMulx(srect.r - srect.l, xscale, 16);
+        const int tmp_h = gglMulx(srect.b - srect.t, yscale, 16);
+
+        LOGD_IF(DEBUG_COPYBIT,
+                "xscale=%08x, yscale=%08x, dsdx=%08x, dtdy=%08x, tmp_w=%d, tmp_h=%d",
+                xscale, yscale, dsdx, dtdy, tmp_w, tmp_h);
+
+        tempBitmap = new GraphicBuffer(
+                    tmp_w, tmp_h, src.format,
+                    GraphicBuffer::USAGE_HW_2D);
+
+        err = tempBitmap->initCheck();
+        if (err == NO_ERROR) {
+            copybit_image_t tmp_dst;
+            copybit_rect_t tmp_rect;
+            tmp_dst.w = tmp_w;
+            tmp_dst.h = tmp_h;
+            tmp_dst.format = tempBitmap->format;
+            tmp_dst.handle = (native_handle_t*)tempBitmap->getNativeBuffer()->handle;
+            tmp_rect.l = 0;
+            tmp_rect.t = 0;
+            tmp_rect.r = tmp_dst.w;
+            tmp_rect.b = tmp_dst.h;
+            region_iterator tmp_it(Region(Rect(tmp_rect.r, tmp_rect.b)));
+            copybit->set_parameter(copybit, COPYBIT_TRANSFORM, 0);
+            copybit->set_parameter(copybit, COPYBIT_PLANE_ALPHA, 0xFF);
+            copybit->set_parameter(copybit, COPYBIT_DITHER, COPYBIT_DISABLE);
+            err = copybit->stretch(copybit,
+                    &tmp_dst, &src, &tmp_rect, &srect, &tmp_it);
+            src = tmp_dst;
+            srect = tmp_rect;
+        }
+    }
+
+    copybit_image_t dst;
+    textureToCopyBitImage(&cbSurface, cbSurface.format,
+            c->copybits.drawSurfaceBuffer, &dst);
+    copybit_rect_t drect = {x, y, x+w, y+h};
+
+
+    /* and now the alpha-plane hack. This handles the "Fade" case of a
+     * texture with an alpha channel.
+     */
+    if (alphaPlaneWorkaround) {
+        sp<GraphicBuffer> tempCb = new GraphicBuffer(
+                    w, h, COPYBIT_FORMAT_RGB_565,
+                    GraphicBuffer::USAGE_HW_2D);
+
+        err = tempCb->initCheck();
+
+        copybit_image_t tmpCbImg;
+        copybit_rect_t tmpCbRect;
+        copybit_rect_t tmpdrect = drect;
+        tmpCbImg.w = w;
+        tmpCbImg.h = h;
+        tmpCbImg.format = tempCb->format;
+        tmpCbImg.handle = (native_handle_t*)tempCb->getNativeBuffer()->handle;
+        tmpCbRect.l = 0;
+        tmpCbRect.t = 0;
+
+        if (drect.l < 0) {
+            tmpCbRect.l = -tmpdrect.l;
+            tmpdrect.l = 0;
+        }
+        if (drect.t < 0) {
+            tmpCbRect.t = -tmpdrect.t;
+            tmpdrect.t = 0;
+        }
+        if (drect.l + tmpCbImg.w > dst.w) {
+            tmpCbImg.w = dst.w - drect.l;
+            tmpdrect.r = dst.w;
+        }
+        if (drect.t + tmpCbImg.h > dst.h) {
+            tmpCbImg.h = dst.h - drect.t;
+            tmpdrect.b = dst.h;
+        }
+
+        tmpCbRect.r = tmpCbImg.w;
+        tmpCbRect.b = tmpCbImg.h;
+
+        if (!err) {
+            // first make a copy of the destination buffer
+            region_iterator tmp_it(Region(Rect(w, h)));
+            copybit->set_parameter(copybit, COPYBIT_TRANSFORM, 0);
+            copybit->set_parameter(copybit, COPYBIT_PLANE_ALPHA, 0xFF);
+            copybit->set_parameter(copybit, COPYBIT_DITHER, COPYBIT_DISABLE);
+            err = copybit->stretch(copybit,
+                    &tmpCbImg, &dst, &tmpCbRect, &tmpdrect, &tmp_it);
+        }
+        if (!err) {
+            // then proceed as usual, but without the alpha plane
+            copybit->set_parameter(copybit, COPYBIT_TRANSFORM, transform);
+            copybit->set_parameter(copybit, COPYBIT_PLANE_ALPHA, 0xFF);
+            copybit->set_parameter(copybit, COPYBIT_DITHER,
+                    (enables & GGL_ENABLE_DITHER) ?
+                            COPYBIT_ENABLE : COPYBIT_DISABLE);
+            clipRectRegion it(c);
+            err = copybit->stretch(copybit, &dst, &src, &drect, &srect, &it);
+        }
+        if (!err) {
+            // finally copy back the destination on top with 1-alphaplane
+            int invPlaneAlpha = 0xFF - fixedToByte(c->currentColorClamped.a);
+            clipRectRegion it(c);
+            copybit->set_parameter(copybit, COPYBIT_TRANSFORM, 0);
+            copybit->set_parameter(copybit, COPYBIT_PLANE_ALPHA, invPlaneAlpha);
+            copybit->set_parameter(copybit, COPYBIT_DITHER, COPYBIT_ENABLE);
+            err = copybit->stretch(copybit,
+                    &dst, &tmpCbImg, &tmpdrect, &tmpCbRect, &it);
+        }
+    } else {
+        copybit->set_parameter(copybit, COPYBIT_TRANSFORM, transform);
+        copybit->set_parameter(copybit, COPYBIT_PLANE_ALPHA, planeAlpha);
+        copybit->set_parameter(copybit, COPYBIT_DITHER,
+                (enables & GGL_ENABLE_DITHER) ?
+                        COPYBIT_ENABLE : COPYBIT_DISABLE);
+        clipRectRegion it(c);
+
+        LOGD_IF(0,
+             "dst={%d, %d, %d, %p, %p}, "
+             "src={%d, %d, %d, %p, %p}, "
+             "drect={%d,%d,%d,%d}, "
+             "srect={%d,%d,%d,%d}, "
+             "it={%d,%d,%d,%d}, " ,
+             dst.w, dst.h, dst.format, dst.base, dst.handle,
+             src.w, src.h, src.format, src.base, src.handle,
+             drect.l, drect.t, drect.r, drect.b,
+             srect.l, srect.t, srect.r, srect.b,
+             it.r.l, it.r.t, it.r.r, it.r.b
+        );
+
+        err = copybit->stretch(copybit, &dst, &src, &drect, &srect, &it);
+    }
     if (err != NO_ERROR) {
         c->textures.tmu[0].texture->try_copybit = false;
     }
diff --git a/opengl/libagl/egl.cpp b/opengl/libagl/egl.cpp
index 37628b7..781b8c3 100644
--- a/opengl/libagl/egl.cpp
+++ b/opengl/libagl/egl.cpp
@@ -40,6 +40,7 @@
 #include <pixelflinger/pixelflinger.h>
 
 #include <private/ui/android_natives_priv.h>
+#include <private/ui/sw_gralloc_handle.h>
 
 #include <hardware/copybit.h>
 
@@ -449,15 +450,26 @@
 status_t egl_window_surface_v2_t::lock(
         android_native_buffer_t* buf, int usage, void** vaddr)
 {
-    int err = module->lock(module, buf->handle, 
-            usage, 0, 0, buf->width, buf->height, vaddr);
+    int err;
+    if (sw_gralloc_handle_t::validate(buf->handle) < 0) {
+        err = module->lock(module, buf->handle,
+                usage, 0, 0, buf->width, buf->height, vaddr);
+    } else {
+        sw_gralloc_handle_t const* hnd =
+                reinterpret_cast<sw_gralloc_handle_t const*>(buf->handle);
+        *vaddr = (void*)hnd->base;
+        err = NO_ERROR;
+    }
     return err;
 }
 
 status_t egl_window_surface_v2_t::unlock(android_native_buffer_t* buf)
 {
     if (!buf) return BAD_VALUE;
-    int err = module->unlock(module, buf->handle);
+    int err = NO_ERROR;
+    if (sw_gralloc_handle_t::validate(buf->handle) < 0) {
+        err = module->unlock(module, buf->handle);
+    }
     return err;
 }
 
@@ -623,6 +635,7 @@
     switch (format) {
     case HAL_PIXEL_FORMAT_RGB_565:
     case HAL_PIXEL_FORMAT_RGBA_8888:
+    case HAL_PIXEL_FORMAT_RGBX_8888:
     case HAL_PIXEL_FORMAT_RGBA_4444:
     case HAL_PIXEL_FORMAT_RGBA_5551:
     case HAL_PIXEL_FORMAT_BGRA_8888:
@@ -651,7 +664,7 @@
         if (supportedCopybitsDestinationFormat(buffer.format)) {
             buffer_handle_t handle = this->buffer->handle;
             if (handle != NULL) {
-                gl->copybits.drawSurfaceBuffer = handle;
+                gl->copybits.drawSurfaceBuffer = this->buffer;
             }
         }
     }
@@ -792,6 +805,7 @@
         case GGL_PIXEL_FORMAT_A_8:          size *= 1; break;
         case GGL_PIXEL_FORMAT_RGB_565:      size *= 2; break;
         case GGL_PIXEL_FORMAT_RGBA_8888:    size *= 4; break;
+        case GGL_PIXEL_FORMAT_RGBX_8888:    size *= 4; break;
         default:
             LOGE("incompatible pixel format for pbuffer (format=%d)", f);
             pbuffer.data = 0;
@@ -862,7 +876,7 @@
 #define VERSION_MAJOR 1
 #define VERSION_MINOR 2
 static char const * const gVendorString     = "Google Inc.";
-static char const * const gVersionString    = "1.2 Android Driver";
+static char const * const gVersionString    = "1.2 Android Driver 1.1.0";
 static char const * const gClientApiString  = "OpenGL ES";
 static char const * const gExtensionsString =
         "EGL_KHR_image_base "
@@ -953,12 +967,17 @@
         { EGL_BIND_TO_TEXTURE_RGB,        EGL_FALSE                         },
         { EGL_MIN_SWAP_INTERVAL,          1                                 },
         { EGL_MAX_SWAP_INTERVAL,          1                                 },
+        { EGL_LUMINANCE_SIZE,             0                                 },
+        { EGL_ALPHA_MASK_SIZE,            0                                 },
+        { EGL_COLOR_BUFFER_TYPE,          EGL_RGB_BUFFER                    },
         { EGL_RENDERABLE_TYPE,            EGL_OPENGL_ES_BIT                 },
+        { EGL_CONFORMANT,                 0                                 }
 };
 
 // These configs can override the base attribute list
 // NOTE: when adding a config here, don't forget to update eglCreate*Surface()
 
+// 565 configs
 static config_pair_t const config_0_attribute_list[] = {
         { EGL_BUFFER_SIZE,     16 },
         { EGL_ALPHA_SIZE,       0 },
@@ -981,8 +1000,32 @@
         { EGL_SURFACE_TYPE,     EGL_WINDOW_BIT|EGL_PBUFFER_BIT|EGL_PIXMAP_BIT },
 };
 
+// RGB 888 configs
 static config_pair_t const config_2_attribute_list[] = {
         { EGL_BUFFER_SIZE,     32 },
+        { EGL_ALPHA_SIZE,       0 },
+        { EGL_BLUE_SIZE,        8 },
+        { EGL_GREEN_SIZE,       8 },
+        { EGL_RED_SIZE,         8 },
+        { EGL_DEPTH_SIZE,       0 },
+        { EGL_CONFIG_ID,        6 },
+        { EGL_SURFACE_TYPE,     EGL_WINDOW_BIT|EGL_PBUFFER_BIT|EGL_PIXMAP_BIT },
+};
+
+static config_pair_t const config_3_attribute_list[] = {
+        { EGL_BUFFER_SIZE,     32 },
+        { EGL_ALPHA_SIZE,       0 },
+        { EGL_BLUE_SIZE,        8 },
+        { EGL_GREEN_SIZE,       8 },
+        { EGL_RED_SIZE,         8 },
+        { EGL_DEPTH_SIZE,      16 },
+        { EGL_CONFIG_ID,        7 },
+        { EGL_SURFACE_TYPE,     EGL_WINDOW_BIT|EGL_PBUFFER_BIT|EGL_PIXMAP_BIT },
+};
+
+// 8888 configs
+static config_pair_t const config_4_attribute_list[] = {
+        { EGL_BUFFER_SIZE,     32 },
         { EGL_ALPHA_SIZE,       8 },
         { EGL_BLUE_SIZE,        8 },
         { EGL_GREEN_SIZE,       8 },
@@ -992,7 +1035,7 @@
         { EGL_SURFACE_TYPE,     EGL_WINDOW_BIT|EGL_PBUFFER_BIT|EGL_PIXMAP_BIT },
 };
 
-static config_pair_t const config_3_attribute_list[] = {
+static config_pair_t const config_5_attribute_list[] = {
         { EGL_BUFFER_SIZE,     32 },
         { EGL_ALPHA_SIZE,       8 },
         { EGL_BLUE_SIZE,        8 },
@@ -1003,7 +1046,8 @@
         { EGL_SURFACE_TYPE,     EGL_WINDOW_BIT|EGL_PBUFFER_BIT|EGL_PIXMAP_BIT },
 };
 
-static config_pair_t const config_4_attribute_list[] = {
+// A8 configs
+static config_pair_t const config_6_attribute_list[] = {
         { EGL_BUFFER_SIZE,      8 },
         { EGL_ALPHA_SIZE,       8 },
         { EGL_BLUE_SIZE,        0 },
@@ -1014,7 +1058,7 @@
         { EGL_SURFACE_TYPE,     EGL_WINDOW_BIT|EGL_PBUFFER_BIT|EGL_PIXMAP_BIT },
 };
 
-static config_pair_t const config_5_attribute_list[] = {
+static config_pair_t const config_7_attribute_list[] = {
         { EGL_BUFFER_SIZE,      8 },
         { EGL_ALPHA_SIZE,       8 },
         { EGL_BLUE_SIZE,        0 },
@@ -1032,6 +1076,8 @@
         { config_3_attribute_list, NELEM(config_3_attribute_list) },
         { config_4_attribute_list, NELEM(config_4_attribute_list) },
         { config_5_attribute_list, NELEM(config_5_attribute_list) },
+        { config_6_attribute_list, NELEM(config_6_attribute_list) },
+        { config_7_attribute_list, NELEM(config_7_attribute_list) },
 };
 
 static config_management_t const gConfigManagement[] = {
@@ -1062,14 +1108,66 @@
         { EGL_BIND_TO_TEXTURE_RGB,        config_management_t::exact   },
         { EGL_MIN_SWAP_INTERVAL,          config_management_t::exact   },
         { EGL_MAX_SWAP_INTERVAL,          config_management_t::exact   },
+        { EGL_LUMINANCE_SIZE,             config_management_t::atLeast },
+        { EGL_ALPHA_MASK_SIZE,            config_management_t::atLeast },
+        { EGL_COLOR_BUFFER_TYPE,          config_management_t::exact   },
+        { EGL_RENDERABLE_TYPE,            config_management_t::mask    },
+        { EGL_CONFORMANT,                 config_management_t::mask    }
 };
 
+
 static config_pair_t const config_defaults[] = {
-        { EGL_SURFACE_TYPE,        EGL_WINDOW_BIT },
+    // attributes that are not specified are simply ignored, if a particular
+    // one needs not be ignored, it must be specified here, eg:
+    // { EGL_SURFACE_TYPE, EGL_WINDOW_BIT },
 };
 
 // ----------------------------------------------------------------------------
 
+static status_t getConfigFormatInfo(EGLint configID,
+        int32_t& pixelFormat, int32_t& depthFormat)
+{
+    switch(configID) {
+    case 0:
+        pixelFormat = GGL_PIXEL_FORMAT_RGB_565;
+        depthFormat = 0;
+        break;
+    case 1:
+        pixelFormat = GGL_PIXEL_FORMAT_RGB_565;
+        depthFormat = GGL_PIXEL_FORMAT_Z_16;
+        break;
+    case 2:
+        pixelFormat = GGL_PIXEL_FORMAT_RGBX_8888;
+        depthFormat = 0;
+        break;
+    case 3:
+        pixelFormat = GGL_PIXEL_FORMAT_RGBX_8888;
+        depthFormat = GGL_PIXEL_FORMAT_Z_16;
+        break;
+    case 4:
+        pixelFormat = GGL_PIXEL_FORMAT_RGBA_8888;
+        depthFormat = 0;
+        break;
+    case 5:
+        pixelFormat = GGL_PIXEL_FORMAT_RGBA_8888;
+        depthFormat = GGL_PIXEL_FORMAT_Z_16;
+        break;
+    case 6:
+        pixelFormat = GGL_PIXEL_FORMAT_A_8;
+        depthFormat = 0;
+        break;
+    case 7:
+        pixelFormat = GGL_PIXEL_FORMAT_A_8;
+        depthFormat = GGL_PIXEL_FORMAT_Z_16;
+        break;
+    default:
+        return NAME_NOT_FOUND;
+    }
+    return NO_ERROR;
+}
+
+// ----------------------------------------------------------------------------
+
 template<typename T>
 static int binarySearch(T const sortedArray[], int first, int last, EGLint key)
 {
@@ -1213,32 +1311,7 @@
 
     int32_t depthFormat;
     int32_t pixelFormat;
-    switch(configID) {
-    case 0:
-        pixelFormat = GGL_PIXEL_FORMAT_RGB_565;
-        depthFormat = 0;
-        break;
-    case 1:
-        pixelFormat = GGL_PIXEL_FORMAT_RGB_565;
-        depthFormat = GGL_PIXEL_FORMAT_Z_16;
-        break;
-    case 2:
-        pixelFormat = GGL_PIXEL_FORMAT_RGBA_8888;
-        depthFormat = 0;
-        break;
-    case 3:
-        pixelFormat = GGL_PIXEL_FORMAT_RGBA_8888;
-        depthFormat = GGL_PIXEL_FORMAT_Z_16;
-        break;
-    case 4:
-        pixelFormat = GGL_PIXEL_FORMAT_A_8;
-        depthFormat = 0;
-        break;
-    case 5:
-        pixelFormat = GGL_PIXEL_FORMAT_A_8;
-        depthFormat = GGL_PIXEL_FORMAT_Z_16;
-        break;
-    default:
+    if (getConfigFormatInfo(configID, pixelFormat, depthFormat) != NO_ERROR) {
         return setError(EGL_BAD_MATCH, EGL_NO_SURFACE);
     }
 
@@ -1287,32 +1360,7 @@
 
     int32_t depthFormat;
     int32_t pixelFormat;
-    switch(configID) {
-    case 0:
-        pixelFormat = GGL_PIXEL_FORMAT_RGB_565;
-        depthFormat = 0;
-        break;
-    case 1:
-        pixelFormat = GGL_PIXEL_FORMAT_RGB_565;
-        depthFormat = GGL_PIXEL_FORMAT_Z_16;
-        break;
-    case 2:
-        pixelFormat = GGL_PIXEL_FORMAT_RGBA_8888;
-        depthFormat = 0;
-        break;
-    case 3:
-        pixelFormat = GGL_PIXEL_FORMAT_RGBA_8888;
-        depthFormat = GGL_PIXEL_FORMAT_Z_16;
-        break;
-    case 4:
-        pixelFormat = GGL_PIXEL_FORMAT_A_8;
-        depthFormat = 0;
-        break;
-    case 5:
-        pixelFormat = GGL_PIXEL_FORMAT_A_8;
-        depthFormat = GGL_PIXEL_FORMAT_Z_16;
-        break;
-    default:
+    if (getConfigFormatInfo(configID, pixelFormat, depthFormat) != NO_ERROR) {
         return setError(EGL_BAD_MATCH, EGL_NO_SURFACE);
     }
 
@@ -1351,32 +1399,7 @@
 
     int32_t depthFormat;
     int32_t pixelFormat;
-    switch(configID) {
-    case 0:
-        pixelFormat = GGL_PIXEL_FORMAT_RGB_565;
-        depthFormat = 0;
-        break;
-    case 1:
-        pixelFormat = GGL_PIXEL_FORMAT_RGB_565;
-        depthFormat = GGL_PIXEL_FORMAT_Z_16;
-        break;
-    case 2:
-        pixelFormat = GGL_PIXEL_FORMAT_RGBA_8888;
-        depthFormat = 0;
-        break;
-    case 3:
-        pixelFormat = GGL_PIXEL_FORMAT_RGBA_8888;
-        depthFormat = GGL_PIXEL_FORMAT_Z_16;
-        break;
-    case 4:
-        pixelFormat = GGL_PIXEL_FORMAT_A_8;
-        depthFormat = 0;
-        break;
-    case 5:
-        pixelFormat = GGL_PIXEL_FORMAT_A_8;
-        depthFormat = GGL_PIXEL_FORMAT_Z_16;
-        break;
-    default:
+    if (getConfigFormatInfo(configID, pixelFormat, depthFormat) != NO_ERROR) {
         return setError(EGL_BAD_MATCH, EGL_NO_SURFACE);
     }
 
@@ -1513,7 +1536,7 @@
         numAttributes++;
         EGLint attr = *attrib_list++;
         EGLint val  = *attrib_list++;
-        for (int i=0 ; i<numConfigs ; i++) {
+        for (int i=0 ; possibleMatch && i<numConfigs ; i++) {
             if (!(possibleMatch & (1<<i)))
                 continue;
             if (isAttributeMatching(i, attr, val) == 0) {
@@ -1523,15 +1546,15 @@
     }
 
     // now, handle the attributes which have a useful default value
-    for (size_t j=0 ; j<NELEM(config_defaults) ; j++) {
-        // see if this attribute was specified, if not apply its
+    for (size_t j=0 ; possibleMatch && j<NELEM(config_defaults) ; j++) {
+        // see if this attribute was specified, if not, apply its
         // default value
         if (binarySearch<config_pair_t>(
                 (config_pair_t const*)attrib_list,
                 0, numAttributes-1,
                 config_defaults[j].key) < 0)
         {
-            for (int i=0 ; i<numConfigs ; i++) {
+            for (int i=0 ; possibleMatch && i<numConfigs ; i++) {
                 if (!(possibleMatch & (1<<i)))
                     continue;
                 if (isAttributeMatching(i,
diff --git a/opengl/libagl/matrix.cpp b/opengl/libagl/matrix.cpp
index 21ef50e..3c50977 100644
--- a/opengl/libagl/matrix.cpp
+++ b/opengl/libagl/matrix.cpp
@@ -741,20 +741,19 @@
 
 void point4__mvui(transform_t const* mx, vec4_t* lhs, vec4_t const* rhs) {
     // this used for transforming light positions back to object space.
-    // Lights have 3 components positions, so w is always 1.
-    // however, it is used as a switch for directional lights, so we need
+    // w is used as a switch for directional lights, so we need
     // to preserve it.
     const GLfixed* const m = mx->matrix.m;
     const GLfixed rx = rhs->x;
     const GLfixed ry = rhs->y;
     const GLfixed rz = rhs->z;
-    lhs->x = mla3a(rx, m[ 0], ry, m[ 4], rz, m[ 8], m[12]); 
-    lhs->y = mla3a(rx, m[ 1], ry, m[ 5], rz, m[ 9], m[13]);
-    lhs->z = mla3a(rx, m[ 2], ry, m[ 6], rz, m[10], m[14]);
-    lhs->w = rhs->w;
+    const GLfixed rw = rhs->w;
+    lhs->x = mla4(rx, m[ 0], ry, m[ 4], rz, m[ 8], rw, m[12]);
+    lhs->y = mla4(rx, m[ 1], ry, m[ 5], rz, m[ 9], rw, m[13]);
+    lhs->z = mla4(rx, m[ 2], ry, m[ 6], rz, m[10], rw, m[14]);
+    lhs->w = rw;
 }
 
-
 void point2__nop(transform_t const*, vec4_t* lhs, vec4_t const* rhs) {
     lhs->z = 0;
     lhs->w = 0x10000;
diff --git a/opengl/libagl/state.cpp b/opengl/libagl/state.cpp
index a59b3b0..0f1f27d 100644
--- a/opengl/libagl/state.cpp
+++ b/opengl/libagl/state.cpp
@@ -37,7 +37,7 @@
 // ----------------------------------------------------------------------------
 
 static char const * const gVendorString     = "Android";
-static char const * const gRendererString   = "Android PixelFlinger 1.1";
+static char const * const gRendererString   = "Android PixelFlinger 1.2";
 static char const * const gVersionString    = "OpenGL ES-CM 1.0";
 static char const * const gExtensionsString =
     "GL_OES_byte_coordinates "              // OK
diff --git a/opengl/libagl/texture.cpp b/opengl/libagl/texture.cpp
index 90e6d29..13d078e 100644
--- a/opengl/libagl/texture.cpp
+++ b/opengl/libagl/texture.cpp
@@ -1252,6 +1252,11 @@
         ogles_error(c, GL_INVALID_OPERATION);
         return;
     }
+
+    if (format != tex->internalformat) {
+        ogles_error(c, GL_INVALID_OPERATION);
+        return;
+    }
     if ((xoffset + width  > GLsizei(surface.width)) ||
         (yoffset + height > GLsizei(surface.height))) {
         ogles_error(c, GL_INVALID_VALUE);
diff --git a/opengl/libs/Android.mk b/opengl/libs/Android.mk
index 9578452..6d20e80 100644
--- a/opengl/libs/Android.mk
+++ b/opengl/libs/Android.mk
@@ -32,6 +32,10 @@
 LOCAL_CFLAGS += -DADRENO130=1
 endif
 
+ifeq ($(ARCH_ARM_HAVE_TLS_REGISTER),true)
+  LOCAL_CFLAGS += -DHAVE_ARM_TLS_REGISTER
+endif
+
 include $(BUILD_SHARED_LIBRARY)
 installed_libEGL := $(LOCAL_INSTALLED_MODULE)
 
@@ -78,6 +82,10 @@
 LOCAL_CFLAGS += -DGL_GLEXT_PROTOTYPES -DEGL_EGLEXT_PROTOTYPES
 LOCAL_CFLAGS += -fvisibility=hidden
 
+ifeq ($(ARCH_ARM_HAVE_TLS_REGISTER),true)
+  LOCAL_CFLAGS += -DHAVE_ARM_TLS_REGISTER
+endif
+
 include $(BUILD_SHARED_LIBRARY)
 
 
@@ -107,4 +115,8 @@
 LOCAL_CFLAGS += -DGL_GLEXT_PROTOTYPES -DEGL_EGLEXT_PROTOTYPES
 LOCAL_CFLAGS += -fvisibility=hidden
 
+ifeq ($(ARCH_ARM_HAVE_TLS_REGISTER),true)
+  LOCAL_CFLAGS += -DHAVE_ARM_TLS_REGISTER
+endif
+
 include $(BUILD_SHARED_LIBRARY)
diff --git a/opengl/libs/EGL/Loader.cpp b/opengl/libs/EGL/Loader.cpp
index 7e7da1b..5d6ac26 100644
--- a/opengl/libs/EGL/Loader.cpp
+++ b/opengl/libs/EGL/Loader.cpp
@@ -128,7 +128,7 @@
     return 0;
 }
 
-void* Loader::open(EGLNativeDisplayType display, int impl, gl_hooks_t* hooks)
+void* Loader::open(EGLNativeDisplayType display, int impl, egl_connection_t* cnx)
 {
     /*
      * TODO: if we don't find display/0, then use 0/0
@@ -144,22 +144,22 @@
     char const* tag = getTag(index, impl);
     if (tag) {
         snprintf(path, PATH_MAX, format, "GLES", tag);
-        dso = load_driver(path, hooks, EGL | GLESv1_CM | GLESv2);
+        dso = load_driver(path, cnx, EGL | GLESv1_CM | GLESv2);
         if (dso) {
             hnd = new driver_t(dso);
         } else {
             // Always load EGL first
             snprintf(path, PATH_MAX, format, "EGL", tag);
-            dso = load_driver(path, hooks, EGL);
+            dso = load_driver(path, cnx, EGL);
             if (dso) {
                 hnd = new driver_t(dso);
 
                 // TODO: make this more automated
                 snprintf(path, PATH_MAX, format, "GLESv1_CM", tag);
-                hnd->set( load_driver(path, hooks, GLESv1_CM), GLESv1_CM );
+                hnd->set( load_driver(path, cnx, GLESv1_CM), GLESv1_CM );
 
                 snprintf(path, PATH_MAX, format, "GLESv2", tag);
-                hnd->set( load_driver(path, hooks, GLESv2), GLESv2 );
+                hnd->set( load_driver(path, cnx, GLESv2), GLESv2 );
             }
         }
     }
@@ -223,7 +223,7 @@
 }
 
 void *Loader::load_driver(const char* driver_absolute_path,
-        gl_hooks_t* hooks, uint32_t mask)
+        egl_connection_t* cnx, uint32_t mask)
 {
     if (access(driver_absolute_path, R_OK)) {
         // this happens often, we don't want to log an error
@@ -245,7 +245,7 @@
         LOGE_IF(!getProcAddress, 
                 "can't find eglGetProcAddress() in %s", driver_absolute_path);
 
-        gl_hooks_t::egl_t* egl = &hooks->egl;
+        egl_t* egl = &cnx->egl;
         __eglMustCastToProperFunctionPointerType* curr =
             (__eglMustCastToProperFunctionPointerType*)egl;
         char const * const * api = egl_names;
@@ -266,14 +266,16 @@
     }
     
     if (mask & GLESv1_CM) {
-        init_api(dso, gl_names,  
-                (__eglMustCastToProperFunctionPointerType*)&hooks->gl, 
-                getProcAddress);
+        init_api(dso, gl_names,
+            (__eglMustCastToProperFunctionPointerType*)
+                &cnx->hooks[GLESv1_INDEX]->gl,
+            getProcAddress);
     }
 
     if (mask & GLESv2) {
-      init_api(dso, gl2_names, 
-            (__eglMustCastToProperFunctionPointerType*)&hooks->gl2, 
+      init_api(dso, gl_names,
+            (__eglMustCastToProperFunctionPointerType*)
+                &cnx->hooks[GLESv2_INDEX]->gl,
             getProcAddress);
     }
     
diff --git a/opengl/libs/EGL/Loader.h b/opengl/libs/EGL/Loader.h
index 69f6dd5..8659b0b 100644
--- a/opengl/libs/EGL/Loader.h
+++ b/opengl/libs/EGL/Loader.h
@@ -32,7 +32,7 @@
 namespace android {
 // ----------------------------------------------------------------------------
 
-struct gl_hooks_t;
+struct egl_connection_t;
 
 class Loader : public Singleton<Loader>
 {
@@ -69,12 +69,12 @@
 public:
     ~Loader();
     
-    void* open(EGLNativeDisplayType display, int impl, gl_hooks_t* hooks);
+    void* open(EGLNativeDisplayType display, int impl, egl_connection_t* cnx);
     status_t close(void* driver);
     
 private:
     Loader();
-    void *load_driver(const char* driver, gl_hooks_t* hooks, uint32_t mask);
+    void *load_driver(const char* driver, egl_connection_t* cnx, uint32_t mask);
 
     static __attribute__((noinline))
     void init_api(void* dso, 
diff --git a/opengl/libs/EGL/egl.cpp b/opengl/libs/EGL/egl.cpp
index d1ddcd3..c22c21b 100644
--- a/opengl/libs/EGL/egl.cpp
+++ b/opengl/libs/EGL/egl.cpp
@@ -164,7 +164,7 @@
     };
 
     uint32_t    magic;
-    DisplayImpl disp[IMPL_NUM_DRIVERS_IMPLEMENTATIONS];
+    DisplayImpl disp[IMPL_NUM_IMPLEMENTATIONS];
     EGLint      numTotalConfigs;
     volatile int32_t refs;
     
@@ -195,8 +195,9 @@
     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)
+            int impl, egl_connection_t const* cnx, int version) 
+    : dpy(dpy), context(context), read(0), draw(0), impl(impl), cnx(cnx),
+      version(version)
     {
     }
     EGLDisplay                  dpy;
@@ -205,6 +206,7 @@
     EGLSurface                  draw;
     int                         impl;
     egl_connection_t const*     cnx;
+    int                         version;
 };
 
 struct egl_image_t : public egl_object_t
@@ -218,7 +220,7 @@
     }
     EGLDisplay dpy;
     EGLConfig context;
-    EGLImageKHR images[IMPL_NUM_DRIVERS_IMPLEMENTATIONS];
+    EGLImageKHR images[IMPL_NUM_IMPLEMENTATIONS];
 };
 
 typedef egl_surface_t::Ref  SurfaceRef;
@@ -236,14 +238,15 @@
 
 // ----------------------------------------------------------------------------
 
-egl_connection_t gEGLImpl[IMPL_NUM_DRIVERS_IMPLEMENTATIONS];
+egl_connection_t gEGLImpl[IMPL_NUM_IMPLEMENTATIONS];
 static egl_display_t gDisplay[NUM_DISPLAYS];
 static pthread_mutex_t gThreadLocalStorageKeyMutex = PTHREAD_MUTEX_INITIALIZER;
 static pthread_key_t gEGLThreadLocalStorageKey = -1;
 
 // ----------------------------------------------------------------------------
 
-EGLAPI gl_hooks_t gHooks[IMPL_NUM_IMPLEMENTATIONS];
+EGLAPI gl_hooks_t gHooks[2][IMPL_NUM_IMPLEMENTATIONS];
+EGLAPI gl_hooks_t gHooksNoContext;
 EGLAPI pthread_key_t gGLWrapperKey = -1;
 
 // ----------------------------------------------------------------------------
@@ -434,10 +437,10 @@
 #endif
     uint32_t addr = (uint32_t)((void*)gl_no_context);
     android_memset32(
-            (uint32_t*)(void*)&gHooks[IMPL_NO_CONTEXT], 
+            (uint32_t*)(void*)&gHooksNoContext, 
             addr, 
-            sizeof(gHooks[IMPL_NO_CONTEXT]));
-    setGlThreadSpecific(&gHooks[IMPL_NO_CONTEXT]);
+            sizeof(gHooksNoContext));
+    setGlThreadSpecific(&gHooksNoContext);
 }
 
 static pthread_once_t once_control = PTHREAD_ONCE_INIT;
@@ -479,7 +482,7 @@
     if (!dp) return setError(EGL_BAD_DISPLAY, (egl_connection_t*)NULL);
 
     impl = uintptr_t(config)>>24;
-    if (uint32_t(impl) >= IMPL_NUM_DRIVERS_IMPLEMENTATIONS) {
+    if (uint32_t(impl) >= IMPL_NUM_IMPLEMENTATIONS) {
         return setError(EGL_BAD_CONFIG, (egl_connection_t*)NULL);
     } 
     index = uintptr_t(config) & 0xFFFFFF;
@@ -559,10 +562,11 @@
 
     cnx = &gEGLImpl[IMPL_SOFTWARE];
     if (cnx->dso == 0) {
-        cnx->hooks = &gHooks[IMPL_SOFTWARE];
-        cnx->dso = loader.open(EGL_DEFAULT_DISPLAY, 0, cnx->hooks);
+        cnx->hooks[GLESv1_INDEX] = &gHooks[GLESv1_INDEX][IMPL_SOFTWARE];
+        cnx->hooks[GLESv2_INDEX] = &gHooks[GLESv2_INDEX][IMPL_SOFTWARE];
+        cnx->dso = loader.open(EGL_DEFAULT_DISPLAY, 0, cnx);
         if (cnx->dso) {
-            EGLDisplay dpy = cnx->hooks->egl.eglGetDisplay(EGL_DEFAULT_DISPLAY);
+            EGLDisplay dpy = cnx->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) {
@@ -577,10 +581,11 @@
         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(EGL_DEFAULT_DISPLAY, 1, cnx->hooks);
+            cnx->hooks[GLESv1_INDEX] = &gHooks[GLESv1_INDEX][IMPL_HARDWARE];
+            cnx->hooks[GLESv2_INDEX] = &gHooks[GLESv2_INDEX][IMPL_HARDWARE];
+            cnx->dso = loader.open(EGL_DEFAULT_DISPLAY, 1, cnx);
             if (cnx->dso) {
-                EGLDisplay dpy = cnx->hooks->egl.eglGetDisplay(EGL_DEFAULT_DISPLAY);
+                EGLDisplay dpy = cnx->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) {
@@ -645,12 +650,12 @@
         return EGL_TRUE;
     }
     
-    setGlThreadSpecific(&gHooks[IMPL_NO_CONTEXT]);
+    setGlThreadSpecific(&gHooksNoContext);
     
     // initialize each EGL and
     // build our own extension string first, based on the extension we know
     // and the extension supported by our client implementation
-    for (int i=0 ; i<IMPL_NUM_DRIVERS_IMPLEMENTATIONS ; i++) {
+    for (int i=0 ; i<IMPL_NUM_IMPLEMENTATIONS ; i++) {
         egl_connection_t* const cnx = &gEGLImpl[i];
         cnx->major = -1;
         cnx->minor = -1;
@@ -668,13 +673,13 @@
          */
         if (i == IMPL_HARDWARE) {
             dp->disp[i].dpy =
-                cnx->hooks->egl.eglGetDisplay(EGL_DEFAULT_DISPLAY);
+                cnx->egl.eglGetDisplay(EGL_DEFAULT_DISPLAY);
         }
 #endif
 
 
         EGLDisplay idpy = dp->disp[i].dpy;
-        if (cnx->hooks->egl.eglInitialize(idpy, &cnx->major, &cnx->minor)) {
+        if (cnx->egl.eglInitialize(idpy, &cnx->major, &cnx->minor)) {
             //LOGD("initialized %d dpy=%p, ver=%d.%d, cnx=%p",
             //        i, idpy, cnx->major, cnx->minor, cnx);
 
@@ -683,29 +688,29 @@
 
             // get the query-strings for this display for each implementation
             dp->disp[i].queryString.vendor =
-                cnx->hooks->egl.eglQueryString(idpy, EGL_VENDOR);
+                cnx->egl.eglQueryString(idpy, EGL_VENDOR);
             dp->disp[i].queryString.version =
-                cnx->hooks->egl.eglQueryString(idpy, EGL_VERSION);
+                cnx->egl.eglQueryString(idpy, EGL_VERSION);
             dp->disp[i].queryString.extensions =
-                    cnx->hooks->egl.eglQueryString(idpy, EGL_EXTENSIONS);
+                    cnx->egl.eglQueryString(idpy, EGL_EXTENSIONS);
             dp->disp[i].queryString.clientApi =
-                cnx->hooks->egl.eglQueryString(idpy, EGL_CLIENT_APIS);
+                cnx->egl.eglQueryString(idpy, EGL_CLIENT_APIS);
 
         } else {
             LOGW("%d: eglInitialize(%p) failed (%s)", i, idpy,
-                    egl_strerror(cnx->hooks->egl.eglGetError()));
+                    egl_strerror(cnx->egl.eglGetError()));
         }
     }
 
     EGLBoolean res = EGL_FALSE;
-    for (int i=0 ; i<IMPL_NUM_DRIVERS_IMPLEMENTATIONS ; i++) {
+    for (int i=0 ; i<IMPL_NUM_IMPLEMENTATIONS ; i++) {
         egl_connection_t* const cnx = &gEGLImpl[i];
         if (cnx->dso && cnx->major>=0 && cnx->minor>=0) {
             EGLint n;
-            if (cnx->hooks->egl.eglGetConfigs(dp->disp[i].dpy, 0, 0, &n)) {
+            if (cnx->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(
+                    if (cnx->egl.eglGetConfigs(
                             dp->disp[i].dpy, dp->disp[i].config, n,
                             &dp->disp[i].numConfigs))
                     {
@@ -742,12 +747,12 @@
         return EGL_TRUE;
 
     EGLBoolean res = EGL_FALSE;
-    for (int i=0 ; i<IMPL_NUM_DRIVERS_IMPLEMENTATIONS ; i++) {
+    for (int i=0 ; i<IMPL_NUM_IMPLEMENTATIONS ; i++) {
         egl_connection_t* const cnx = &gEGLImpl[i];
         if (cnx->dso && dp->disp[i].state == egl_display_t::INITIALIZED) {
-            if (cnx->hooks->egl.eglTerminate(dp->disp[i].dpy) == EGL_FALSE) {
+            if (cnx->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()));
+                        egl_strerror(cnx->egl.eglGetError()));
             }
             // REVISIT: it's unclear what to do if eglTerminate() fails
             free(dp->disp[i].config);
@@ -784,7 +789,7 @@
         return EGL_TRUE;
     }
     GLint n = 0;
-    for (int j=0 ; j<IMPL_NUM_DRIVERS_IMPLEMENTATIONS ; j++) {
+    for (int j=0 ; j<IMPL_NUM_IMPLEMENTATIONS ; j++) {
         for (int i=0 ; i<dp->disp[j].numConfigs && config_size ; i++) {
             *configs++ = MAKE_CONFIG(j, i);
             config_size--;
@@ -841,7 +846,7 @@
         
         egl_connection_t* const cnx = &gEGLImpl[i];
         if (cnx->dso) {
-            cnx->hooks->egl.eglGetConfigAttrib(
+            cnx->egl.eglGetConfigAttrib(
                     dp->disp[i].dpy, dp->disp[i].config[index], 
                     EGL_CONFIG_ID, &configId);
 
@@ -851,12 +856,12 @@
             // At this point, the only configuration that can match is
             // dp->configs[i][index], however, we don't know if it would be
             // rejected because of the other attributes, so we do have to call
-            // cnx->hooks->egl.eglChooseConfig() -- but we don't have to loop
+            // cnx->egl.eglChooseConfig() -- but we don't have to loop
             // through all the EGLimpl[].
             // We also know we can only get a single config back, and we know
             // which one.
 
-            res = cnx->hooks->egl.eglChooseConfig(
+            res = cnx->egl.eglChooseConfig(
                     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
@@ -872,10 +877,10 @@
         return res;
     }
 
-    for (int i=0 ; i<IMPL_NUM_DRIVERS_IMPLEMENTATIONS ; i++) {
+    for (int i=0 ; i<IMPL_NUM_IMPLEMENTATIONS ; i++) {
         egl_connection_t* const cnx = &gEGLImpl[i];
         if (cnx->dso) {
-            if (cnx->hooks->egl.eglChooseConfig(
+            if (cnx->egl.eglChooseConfig(
                     dp->disp[i].dpy, attrib_list, configs, config_size, &n)) {
                 if (configs) {
                     // now we need to convert these client EGLConfig to our
@@ -917,7 +922,7 @@
         *value = configToUniqueId(dp, i, index);
         return EGL_TRUE;
     }
-    return cnx->hooks->egl.eglGetConfigAttrib(
+    return cnx->egl.eglGetConfigAttrib(
             dp->disp[i].dpy, dp->disp[i].config[index], attribute, value);
 }
 
@@ -933,7 +938,7 @@
     int i=0, index=0;
     egl_connection_t* cnx = validate_display_config(dpy, config, dp, i, index);
     if (cnx) {
-        EGLSurface surface = cnx->hooks->egl.eglCreateWindowSurface(
+        EGLSurface surface = cnx->egl.eglCreateWindowSurface(
                 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);
@@ -951,7 +956,7 @@
     int i=0, index=0;
     egl_connection_t* cnx = validate_display_config(dpy, config, dp, i, index);
     if (cnx) {
-        EGLSurface surface = cnx->hooks->egl.eglCreatePixmapSurface(
+        EGLSurface surface = cnx->egl.eglCreatePixmapSurface(
                 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);
@@ -968,7 +973,7 @@
     int i=0, index=0;
     egl_connection_t* cnx = validate_display_config(dpy, config, dp, i, index);
     if (cnx) {
-        EGLSurface surface = cnx->hooks->egl.eglCreatePbufferSurface(
+        EGLSurface surface = cnx->egl.eglCreatePbufferSurface(
                 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);
@@ -988,7 +993,7 @@
     egl_display_t const * const dp = get_display(dpy);
 
     egl_surface_t * const s = get_surface(surface);
-    EGLBoolean result = s->cnx->hooks->egl.eglDestroySurface(
+    EGLBoolean result = s->cnx->egl.eglDestroySurface(
             dp->disp[s->impl].dpy, s->surface);
     if (result == EGL_TRUE) {
         _s.terminate();
@@ -1007,7 +1012,7 @@
     egl_display_t const * const dp = get_display(dpy);
     egl_surface_t const * const s = get_surface(surface);
 
-    return s->cnx->hooks->egl.eglQuerySurface(
+    return s->cnx->egl.eglQuerySurface(
             dp->disp[s->impl].dpy, s->surface, attribute, value);
 }
 
@@ -1022,11 +1027,26 @@
     int i=0, index=0;
     egl_connection_t* cnx = validate_display_config(dpy, config, dp, i, index);
     if (cnx) {
-        EGLContext context = cnx->hooks->egl.eglCreateContext(
+        EGLContext context = cnx->egl.eglCreateContext(
                 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);
+            // figure out if it's a GLESv1 or GLESv2
+            int version = 0;
+            if (attrib_list) {
+                while (*attrib_list != EGL_NONE) {
+                    GLint attr = *attrib_list++;
+                    GLint value = *attrib_list++;
+                    if (attr == EGL_CONTEXT_CLIENT_VERSION) {
+                        if (value == 1) {
+                            version = GLESv1_INDEX;
+                        } else if (value == 2) {
+                            version = GLESv2_INDEX;
+                        }
+                    }
+                };
+            }
+            egl_context_t* c = new egl_context_t(dpy, context, i, cnx, version);
             return c;
         }
     }
@@ -1042,7 +1062,7 @@
         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(
+    EGLBoolean result = c->cnx->egl.eglDestroyContext(
             dp->disp[c->impl].dpy, c->context);
     if (result == EGL_TRUE) {
         _c.terminate();
@@ -1122,10 +1142,10 @@
     EGLBoolean result;
 
     if (c) {
-        result = c->cnx->hooks->egl.eglMakeCurrent(
+        result = c->cnx->egl.eglMakeCurrent(
                 dp->disp[c->impl].dpy, impl_draw, impl_read, impl_ctx);
     } else {
-        result = cur_c->cnx->hooks->egl.eglMakeCurrent(
+        result = cur_c->cnx->egl.eglMakeCurrent(
                 dp->disp[cur_c->impl].dpy, impl_draw, impl_read, impl_ctx);
     }
 
@@ -1138,11 +1158,11 @@
 
         // cur_c has to be valid here (but could be terminated)
         if (ctx != EGL_NO_CONTEXT) {
-            setGlThreadSpecific(c->cnx->hooks);
+            setGlThreadSpecific(c->cnx->hooks[c->version]);
             setContext(ctx);
             _c.acquire();
         } else {
-            setGlThreadSpecific(&gHooks[IMPL_NO_CONTEXT]);
+            setGlThreadSpecific(&gHooksNoContext);
             setContext(EGL_NO_CONTEXT);
         }
         _cur_c.release();
@@ -1171,7 +1191,7 @@
     egl_display_t const * const dp = get_display(dpy);
     egl_context_t * const c = get_context(ctx);
 
-    return c->cnx->hooks->egl.eglQueryContext(
+    return c->cnx->egl.eglQueryContext(
             dp->disp[c->impl].dpy, c->context, attribute, value);
 }
 
@@ -1231,7 +1251,7 @@
         egl_connection_t* const cnx = &gEGLImpl[c->impl];
         if (!cnx->dso) 
             return setError(EGL_BAD_CONTEXT, EGL_FALSE);
-        res = cnx->hooks->egl.eglWaitGL();
+        res = cnx->egl.eglWaitGL();
     }
     return res;
 }
@@ -1251,7 +1271,7 @@
         egl_connection_t* const cnx = &gEGLImpl[c->impl];
         if (!cnx->dso) 
             return setError(EGL_BAD_CONTEXT, EGL_FALSE);
-        res = cnx->hooks->egl.eglWaitNative(engine);
+        res = cnx->egl.eglWaitNative(engine);
     }
     return res;
 }
@@ -1259,11 +1279,11 @@
 EGLint eglGetError(void)
 {
     EGLint result = EGL_SUCCESS;
-    for (int i=0 ; i<IMPL_NUM_DRIVERS_IMPLEMENTATIONS ; i++) {
+    for (int i=0 ; i<IMPL_NUM_IMPLEMENTATIONS ; i++) {
         EGLint err = EGL_SUCCESS;
         egl_connection_t* const cnx = &gEGLImpl[i];
         if (cnx->dso)
-            err = cnx->hooks->egl.eglGetError();
+            err = cnx->egl.eglGetError();
         if (err!=EGL_SUCCESS && result==EGL_SUCCESS)
             result = err;
     }
@@ -1294,11 +1314,11 @@
     
     addr = 0;
     int slot = -1;
-    for (int i=0 ; i<IMPL_NUM_DRIVERS_IMPLEMENTATIONS ; i++) {
+    for (int i=0 ; i<IMPL_NUM_IMPLEMENTATIONS ; i++) {
         egl_connection_t* const cnx = &gEGLImpl[i];
         if (cnx->dso) {
-            if (cnx->hooks->egl.eglGetProcAddress) {
-                addr = cnx->hooks->egl.eglGetProcAddress(procname);
+            if (cnx->egl.eglGetProcAddress) {
+                addr = cnx->egl.eglGetProcAddress(procname);
                 if (addr) {
                     if (slot == -1) {
                         slot = 0; // XXX: find free slot
@@ -1307,7 +1327,7 @@
                             break;
                         }
                     }
-                    cnx->hooks->ext.extensions[slot] = addr;
+                    //cnx->hooks->ext.extensions[slot] = addr;
                 }
             }
         }
@@ -1347,7 +1367,7 @@
         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->disp[s->impl].dpy, s->surface);
+    return s->cnx->egl.eglSwapBuffers(dp->disp[s->impl].dpy, s->surface);
 }
 
 EGLBoolean eglCopyBuffers(  EGLDisplay dpy, EGLSurface surface,
@@ -1360,7 +1380,7 @@
         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(
+    return s->cnx->egl.eglCopyBuffers(
             dp->disp[s->impl].dpy, s->surface, target);
 }
 
@@ -1395,8 +1415,8 @@
         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(
+    if (s->cnx->egl.eglSurfaceAttrib) {
+        return s->cnx->egl.eglSurfaceAttrib(
                 dp->disp[s->impl].dpy, s->surface, attribute, value);
     }
     return setError(EGL_BAD_SURFACE, EGL_FALSE);
@@ -1412,8 +1432,8 @@
         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(
+    if (s->cnx->egl.eglBindTexImage) {
+        return s->cnx->egl.eglBindTexImage(
                 dp->disp[s->impl].dpy, s->surface, buffer);
     }
     return setError(EGL_BAD_SURFACE, EGL_FALSE);
@@ -1429,8 +1449,8 @@
         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(
+    if (s->cnx->egl.eglReleaseTexImage) {
+        return s->cnx->egl.eglReleaseTexImage(
                 dp->disp[s->impl].dpy, s->surface, buffer);
     }
     return setError(EGL_BAD_SURFACE, EGL_FALSE);
@@ -1442,11 +1462,11 @@
     if (!dp) return setError(EGL_BAD_DISPLAY, EGL_FALSE);
 
     EGLBoolean res = EGL_TRUE;
-    for (int i=0 ; i<IMPL_NUM_DRIVERS_IMPLEMENTATIONS ; i++) {
+    for (int i=0 ; i<IMPL_NUM_IMPLEMENTATIONS ; i++) {
         egl_connection_t* const cnx = &gEGLImpl[i];
         if (cnx->dso) {
-            if (cnx->hooks->egl.eglSwapInterval) {
-                if (cnx->hooks->egl.eglSwapInterval(
+            if (cnx->egl.eglSwapInterval) {
+                if (cnx->egl.eglSwapInterval(
                         dp->disp[i].dpy, interval) == EGL_FALSE) {
                     res = EGL_FALSE;
                 }
@@ -1475,10 +1495,10 @@
         egl_connection_t* const cnx = &gEGLImpl[c->impl];
         if (!cnx->dso) 
             return setError(EGL_BAD_CONTEXT, EGL_FALSE);
-        if (cnx->hooks->egl.eglWaitClient) {
-            res = cnx->hooks->egl.eglWaitClient();
+        if (cnx->egl.eglWaitClient) {
+            res = cnx->egl.eglWaitClient();
         } else {
-            res = cnx->hooks->egl.eglWaitGL();
+            res = cnx->egl.eglWaitGL();
         }
     }
     return res;
@@ -1492,11 +1512,11 @@
 
     // bind this API on all EGLs
     EGLBoolean res = EGL_TRUE;
-    for (int i=0 ; i<IMPL_NUM_DRIVERS_IMPLEMENTATIONS ; i++) {
+    for (int i=0 ; i<IMPL_NUM_IMPLEMENTATIONS ; i++) {
         egl_connection_t* const cnx = &gEGLImpl[i];
         if (cnx->dso) {
-            if (cnx->hooks->egl.eglBindAPI) {
-                if (cnx->hooks->egl.eglBindAPI(api) == EGL_FALSE) {
+            if (cnx->egl.eglBindAPI) {
+                if (cnx->egl.eglBindAPI(api) == EGL_FALSE) {
                     res = EGL_FALSE;
                 }
             }
@@ -1511,13 +1531,13 @@
         return setError(EGL_BAD_PARAMETER, EGL_FALSE);
     }
 
-    for (int i=0 ; i<IMPL_NUM_DRIVERS_IMPLEMENTATIONS ; i++) {
+    for (int i=0 ; i<IMPL_NUM_IMPLEMENTATIONS ; i++) {
         egl_connection_t* const cnx = &gEGLImpl[i];
         if (cnx->dso) {
-            if (cnx->hooks->egl.eglQueryAPI) {
+            if (cnx->egl.eglQueryAPI) {
                 // the first one we find is okay, because they all
                 // should be the same
-                return cnx->hooks->egl.eglQueryAPI();
+                return cnx->egl.eglQueryAPI();
             }
         }
     }
@@ -1527,11 +1547,11 @@
 
 EGLBoolean eglReleaseThread(void)
 {
-    for (int i=0 ; i<IMPL_NUM_DRIVERS_IMPLEMENTATIONS ; i++) {
+    for (int i=0 ; i<IMPL_NUM_IMPLEMENTATIONS ; i++) {
         egl_connection_t* const cnx = &gEGLImpl[i];
         if (cnx->dso) {
-            if (cnx->hooks->egl.eglReleaseThread) {
-                cnx->hooks->egl.eglReleaseThread();
+            if (cnx->egl.eglReleaseThread) {
+                cnx->egl.eglReleaseThread();
             }
         }
     }
@@ -1547,8 +1567,8 @@
     int i=0, index=0;
     egl_connection_t* cnx = validate_display_config(dpy, config, dp, i, index);
     if (!cnx) return EGL_FALSE;
-    if (cnx->hooks->egl.eglCreatePbufferFromClientBuffer) {
-        return cnx->hooks->egl.eglCreatePbufferFromClientBuffer(
+    if (cnx->egl.eglCreatePbufferFromClientBuffer) {
+        return cnx->egl.eglCreatePbufferFromClientBuffer(
                 dp->disp[i].dpy, buftype, buffer, 
                 dp->disp[i].config[index], attrib_list);
     }
@@ -1571,8 +1591,8 @@
     egl_display_t const * const dp = get_display(dpy);
     egl_surface_t const * const s = get_surface(surface);
 
-    if (s->cnx->hooks->egl.eglLockSurfaceKHR) {
-        return s->cnx->hooks->egl.eglLockSurfaceKHR(
+    if (s->cnx->egl.eglLockSurfaceKHR) {
+        return s->cnx->egl.eglLockSurfaceKHR(
                 dp->disp[s->impl].dpy, s->surface, attrib_list);
     }
     return setError(EGL_BAD_DISPLAY, EGL_FALSE);
@@ -1589,8 +1609,8 @@
     egl_display_t const * const dp = get_display(dpy);
     egl_surface_t const * const s = get_surface(surface);
 
-    if (s->cnx->hooks->egl.eglUnlockSurfaceKHR) {
-        return s->cnx->hooks->egl.eglUnlockSurfaceKHR(
+    if (s->cnx->egl.eglUnlockSurfaceKHR) {
+        return s->cnx->egl.eglUnlockSurfaceKHR(
                 dp->disp[s->impl].dpy, s->surface);
     }
     return setError(EGL_BAD_DISPLAY, EGL_FALSE);
@@ -1607,7 +1627,7 @@
         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(
+        EGLImageKHR image = c->cnx->egl.eglCreateImageKHR(
                 dp->disp[c->impl].dpy, c->context, target, buffer, attrib_list);
         if (image == EGL_NO_IMAGE_KHR)
             return image;
@@ -1621,17 +1641,22 @@
         if (dp == 0) {
             return setError(EGL_BAD_DISPLAY, EGL_NO_IMAGE_KHR);
         }
-        // since we don't have a way to know which implementation to call,
-        // we're calling all of them
 
-        EGLImageKHR implImages[IMPL_NUM_DRIVERS_IMPLEMENTATIONS];
+        /* Since we don't have a way to know which implementation to call,
+         * we're calling all of them. If at least one of the implementation
+         * succeeded, this is a success.
+         */
+
+        EGLint currentError = eglGetError();
+
+        EGLImageKHR implImages[IMPL_NUM_IMPLEMENTATIONS];
         bool success = false;
-        for (int i=0 ; i<IMPL_NUM_DRIVERS_IMPLEMENTATIONS ; i++) {
+        for (int i=0 ; i<IMPL_NUM_IMPLEMENTATIONS ; i++) {
             egl_connection_t* const cnx = &gEGLImpl[i];
             implImages[i] = EGL_NO_IMAGE_KHR;
             if (cnx->dso) {
-                if (cnx->hooks->egl.eglCreateImageKHR) {
-                    implImages[i] = cnx->hooks->egl.eglCreateImageKHR(
+                if (cnx->egl.eglCreateImageKHR) {
+                    implImages[i] = cnx->egl.eglCreateImageKHR(
                             dp->disp[i].dpy, ctx, target, buffer, attrib_list);
                     if (implImages[i] != EGL_NO_IMAGE_KHR) {
                         success = true;
@@ -1639,9 +1664,24 @@
                 }
             }
         }
-        if (!success)
+
+        if (!success) {
+            // failure, if there was an error when we entered this function,
+            // the error flag must not be updated.
+            // Otherwise, the error is whatever happened in the implementation
+            // that faulted.
+            if (currentError != EGL_SUCCESS) {
+                setError(currentError, EGL_NO_IMAGE_KHR);
+            }
             return EGL_NO_IMAGE_KHR;
-        
+        } else {
+            // In case of success, we need to clear all error flags
+            // (especially those caused by the implementation that didn't
+            // succeed). TODO: we could avoid this if we knew this was
+            // a "full" success (all implementation succeeded).
+            eglGetError();
+        }
+
         egl_image_t* result = new egl_image_t(dpy, ctx);
         memcpy(result->images, implImages, sizeof(implImages));
         return (EGLImageKHR)result;
@@ -1660,12 +1700,12 @@
 
      egl_image_t* image = get_image(img);
      bool success = false;
-     for (int i=0 ; i<IMPL_NUM_DRIVERS_IMPLEMENTATIONS ; i++) {
+     for (int i=0 ; i<IMPL_NUM_IMPLEMENTATIONS ; i++) {
          egl_connection_t* const cnx = &gEGLImpl[i];
          if (image->images[i] != EGL_NO_IMAGE_KHR) {
              if (cnx->dso) {
-                 if (cnx->hooks->egl.eglCreateImageKHR) {
-                     if (cnx->hooks->egl.eglDestroyImageKHR(
+                 if (cnx->egl.eglCreateImageKHR) {
+                     if (cnx->egl.eglDestroyImageKHR(
                              dp->disp[i].dpy, image->images[i])) {
                          success = true;
                      }
@@ -1696,8 +1736,8 @@
         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(
+    if (s->cnx->egl.eglSetSwapRectangleANDROID) {
+        return s->cnx->egl.eglSetSwapRectangleANDROID(
                 dp->disp[s->impl].dpy, s->surface, left, top, width, height);
     }
     return setError(EGL_BAD_DISPLAY, NULL);
@@ -1712,8 +1752,8 @@
         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(
+    if (s->cnx->egl.eglGetRenderBufferANDROID) {
+        return s->cnx->egl.eglGetRenderBufferANDROID(
                 dp->disp[s->impl].dpy, s->surface);
     }
     return setError(EGL_BAD_DISPLAY, (EGLClientBuffer*)0);
diff --git a/opengl/libs/EGL/hooks.cpp b/opengl/libs/EGL/hooks.cpp
index 2246366..72ad6b3 100644
--- a/opengl/libs/EGL/hooks.cpp
+++ b/opengl/libs/EGL/hooks.cpp
@@ -41,14 +41,7 @@
 #define EGL_ENTRY(_r, _api, ...) #_api,
 
 char const * const gl_names[] = {
-    #include "GLES_CM/gl_entries.in"
-    #include "GLES_CM/glext_entries.in"
-    NULL
-};
-
-char const * const gl2_names[] = {
-    #include "GLES2/gl2_entries.in"
-    #include "GLES2/gl2ext_entries.in"
+    #include "entries.in"
     NULL
 };
 
diff --git a/opengl/libs/GLES2/gl2.cpp b/opengl/libs/GLES2/gl2.cpp
index e5358c3..b8e3283 100644
--- a/opengl/libs/GLES2/gl2.cpp
+++ b/opengl/libs/GLES2/gl2.cpp
@@ -41,22 +41,30 @@
 
 #if USE_FAST_TLS_KEY
 
+    #ifdef HAVE_ARM_TLS_REGISTER
+        #define GET_TLS(reg) \
+            "mrc p15, 0, " #reg ", c13, c0, 3 \n"
+    #else
+        #define GET_TLS(reg) \
+            "mov   " #reg ", #0xFFFF0FFF      \n"  \
+            "ldr   " #reg ", [" #reg ", #-15] \n"
+    #endif
+
     #define API_ENTRY(_api) __attribute__((naked)) _api
 
     #define CALL_GL_API(_api, ...)                              \
          asm volatile(                                          \
-            "mov   r12, #0xFFFF0FFF   \n"                       \
-            "ldr   r12, [r12, #-15]   \n"                       \
+            GET_TLS(r12)                                        \
             "ldr   r12, [r12, %[tls]] \n"                       \
             "cmp   r12, #0            \n"                       \
             "ldrne pc,  [r12, %[api]] \n"                       \
             "bx    lr                 \n"                       \
             :                                                   \
             : [tls] "J"(TLS_SLOT_OPENGL_API*4),                 \
-              [api] "J"(__builtin_offsetof(gl_hooks_t, gl2._api))    \
+              [api] "J"(__builtin_offsetof(gl_hooks_t, gl._api))    \
             :                                                   \
             );
-    
+
     #define CALL_GL_API_RETURN(_api, ...) \
         CALL_GL_API(_api, __VA_ARGS__) \
         return 0; // placate gcc's warnings. never reached.
@@ -66,11 +74,11 @@
     #define API_ENTRY(_api) _api
 
     #define CALL_GL_API(_api, ...)                                       \
-        gl_hooks_t::gl2_t const * const _c = &getGlThreadSpecific()->gl2; \
+        gl_hooks_t::gl_t const * const _c = &getGlThreadSpecific()->gl;  \
         _c->_api(__VA_ARGS__)
     
     #define CALL_GL_API_RETURN(_api, ...)                                \
-        gl_hooks_t::gl2_t const * const _c = &getGlThreadSpecific()->gl2; \
+        gl_hooks_t::gl_t const * const _c = &getGlThreadSpecific()->gl;  \
         return _c->_api(__VA_ARGS__)
 
 #endif
diff --git a/opengl/libs/GLES2/gl2_entries.in b/opengl/libs/GLES2/gl2_entries.in
deleted file mode 100644
index 6a41b94..0000000
--- a/opengl/libs/GLES2/gl2_entries.in
+++ /dev/null
@@ -1,142 +0,0 @@
-GL_ENTRY(void, glActiveTexture, GLenum texture)
-GL_ENTRY(void, glAttachShader, GLuint program, GLuint shader)
-GL_ENTRY(void, glBindAttribLocation, GLuint program, GLuint index, const char* name)
-GL_ENTRY(void, glBindBuffer, GLenum target, GLuint buffer)
-GL_ENTRY(void, glBindFramebuffer, GLenum target, GLuint framebuffer)
-GL_ENTRY(void, glBindRenderbuffer, GLenum target, GLuint renderbuffer)
-GL_ENTRY(void, glBindTexture, GLenum target, GLuint texture)
-GL_ENTRY(void, glBlendColor, GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha)
-GL_ENTRY(void, glBlendEquation,  GLenum mode )
-GL_ENTRY(void, glBlendEquationSeparate, GLenum modeRGB, GLenum modeAlpha)
-GL_ENTRY(void, glBlendFunc, GLenum sfactor, GLenum dfactor)
-GL_ENTRY(void, glBlendFuncSeparate, GLenum srcRGB, GLenum dstRGB, GLenum srcAlpha, GLenum dstAlpha)
-GL_ENTRY(void, glBufferData, GLenum target, GLsizeiptr size, const void* data, GLenum usage)
-GL_ENTRY(void, glBufferSubData, GLenum target, GLintptr offset, GLsizeiptr size, const void* data)
-GL_ENTRY(GLenum, glCheckFramebufferStatus, GLenum target)
-GL_ENTRY(void, glClear, GLbitfield mask)
-GL_ENTRY(void, glClearColor, GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha)
-GL_ENTRY(void, glClearDepthf, GLclampf depth)
-GL_ENTRY(void, glClearStencil, GLint s)
-GL_ENTRY(void, glColorMask, GLboolean red, GLboolean green, GLboolean blue, GLboolean alpha)
-GL_ENTRY(void, glCompileShader, GLuint shader)
-GL_ENTRY(void, glCompressedTexImage2D, GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLint border, GLsizei imageSize, const void* data)
-GL_ENTRY(void, glCompressedTexSubImage2D, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const void* data)
-GL_ENTRY(void, glCopyTexImage2D, GLenum target, GLint level, GLenum internalformat, GLint x, GLint y, GLsizei width, GLsizei height, GLint border)
-GL_ENTRY(void, glCopyTexSubImage2D, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height)
-GL_ENTRY(GLuint, glCreateProgram, void)
-GL_ENTRY(GLuint, glCreateShader, GLenum type)
-GL_ENTRY(void, glCullFace, GLenum mode)
-GL_ENTRY(void, glDeleteBuffers, GLsizei n, const GLuint* buffers)
-GL_ENTRY(void, glDeleteFramebuffers, GLsizei n, const GLuint* framebuffers)
-GL_ENTRY(void, glDeleteProgram, GLuint program)
-GL_ENTRY(void, glDeleteRenderbuffers, GLsizei n, const GLuint* renderbuffers)
-GL_ENTRY(void, glDeleteShader, GLuint shader)
-GL_ENTRY(void, glDeleteTextures, GLsizei n, const GLuint* textures)
-GL_ENTRY(void, glDepthFunc, GLenum func)
-GL_ENTRY(void, glDepthMask, GLboolean flag)
-GL_ENTRY(void, glDepthRangef, GLclampf zNear, GLclampf zFar)
-GL_ENTRY(void, glDetachShader, GLuint program, GLuint shader)
-GL_ENTRY(void, glDisable, GLenum cap)
-GL_ENTRY(void, glDisableVertexAttribArray, GLuint index)
-GL_ENTRY(void, glDrawArrays, GLenum mode, GLint first, GLsizei count)
-GL_ENTRY(void, glDrawElements, GLenum mode, GLsizei count, GLenum type, const void* indices)
-GL_ENTRY(void, glEnable, GLenum cap)
-GL_ENTRY(void, glEnableVertexAttribArray, GLuint index)
-GL_ENTRY(void, glFinish, void)
-GL_ENTRY(void, glFlush, void)
-GL_ENTRY(void, glFramebufferRenderbuffer, GLenum target, GLenum attachment, GLenum renderbuffertarget, GLuint renderbuffer)
-GL_ENTRY(void, glFramebufferTexture2D, GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level)
-GL_ENTRY(void, glFrontFace, GLenum mode)
-GL_ENTRY(void, glGenBuffers, GLsizei n, GLuint* buffers)
-GL_ENTRY(void, glGenerateMipmap, GLenum target)
-GL_ENTRY(void, glGenFramebuffers, GLsizei n, GLuint* framebuffers)
-GL_ENTRY(void, glGenRenderbuffers, GLsizei n, GLuint* renderbuffers)
-GL_ENTRY(void, glGenTextures, GLsizei n, GLuint* textures)
-GL_ENTRY(void, glGetActiveAttrib, GLuint program, GLuint index, GLsizei bufsize, GLsizei* length, GLint* size, GLenum* type, char* name)
-GL_ENTRY(void, glGetActiveUniform, GLuint program, GLuint index, GLsizei bufsize, GLsizei* length, GLint* size, GLenum* type, char* name)
-GL_ENTRY(void, glGetAttachedShaders, GLuint program, GLsizei maxcount, GLsizei* count, GLuint* shaders)
-GL_ENTRY(int, glGetAttribLocation, GLuint program, const char* name)
-GL_ENTRY(void, glGetBooleanv, GLenum pname, GLboolean* params)
-GL_ENTRY(void, glGetBufferParameteriv, GLenum target, GLenum pname, GLint* params)
-GL_ENTRY(GLenum, glGetError, void)
-GL_ENTRY(void, glGetFloatv, GLenum pname, GLfloat* params)
-GL_ENTRY(void, glGetFramebufferAttachmentParameteriv, GLenum target, GLenum attachment, GLenum pname, GLint* params)
-GL_ENTRY(void, glGetIntegerv, GLenum pname, GLint* params)
-GL_ENTRY(void, glGetProgramiv, GLuint program, GLenum pname, GLint* params)
-GL_ENTRY(void, glGetProgramInfoLog, GLuint program, GLsizei bufsize, GLsizei* length, char* infolog)
-GL_ENTRY(void, glGetRenderbufferParameteriv, GLenum target, GLenum pname, GLint* params)
-GL_ENTRY(void, glGetShaderiv, GLuint shader, GLenum pname, GLint* params)
-GL_ENTRY(void, glGetShaderInfoLog, GLuint shader, GLsizei bufsize, GLsizei* length, char* infolog)
-GL_ENTRY(void, glGetShaderPrecisionFormat, GLenum shadertype, GLenum precisiontype, GLint* range, GLint* precision)
-GL_ENTRY(void, glGetShaderSource, GLuint shader, GLsizei bufsize, GLsizei* length, char* source)
-GL_ENTRY(const GLubyte*, glGetString, GLenum name)
-GL_ENTRY(void, glGetTexParameterfv, GLenum target, GLenum pname, GLfloat* params)
-GL_ENTRY(void, glGetTexParameteriv, GLenum target, GLenum pname, GLint* params)
-GL_ENTRY(void, glGetUniformfv, GLuint program, GLint location, GLfloat* params)
-GL_ENTRY(void, glGetUniformiv, GLuint program, GLint location, GLint* params)
-GL_ENTRY(int, glGetUniformLocation, GLuint program, const char* name)
-GL_ENTRY(void, glGetVertexAttribfv, GLuint index, GLenum pname, GLfloat* params)
-GL_ENTRY(void, glGetVertexAttribiv, GLuint index, GLenum pname, GLint* params)
-GL_ENTRY(void, glGetVertexAttribPointerv, GLuint index, GLenum pname, void** pointer)
-GL_ENTRY(void, glHint, GLenum target, GLenum mode)
-GL_ENTRY(GLboolean, glIsBuffer, GLuint buffer)
-GL_ENTRY(GLboolean, glIsEnabled, GLenum cap)
-GL_ENTRY(GLboolean, glIsFramebuffer, GLuint framebuffer)
-GL_ENTRY(GLboolean, glIsProgram, GLuint program)
-GL_ENTRY(GLboolean, glIsRenderbuffer, GLuint renderbuffer)
-GL_ENTRY(GLboolean, glIsShader, GLuint shader)
-GL_ENTRY(GLboolean, glIsTexture, GLuint texture)
-GL_ENTRY(void, glLineWidth, GLfloat width)
-GL_ENTRY(void, glLinkProgram, GLuint program)
-GL_ENTRY(void, glPixelStorei, GLenum pname, GLint param)
-GL_ENTRY(void, glPolygonOffset, GLfloat factor, GLfloat units)
-GL_ENTRY(void, glReadPixels, GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, void* pixels)
-GL_ENTRY(void, glReleaseShaderCompiler, void)
-GL_ENTRY(void, glRenderbufferStorage, GLenum target, GLenum internalformat, GLsizei width, GLsizei height)
-GL_ENTRY(void, glSampleCoverage, GLclampf value, GLboolean invert)
-GL_ENTRY(void, glScissor, GLint x, GLint y, GLsizei width, GLsizei height)
-GL_ENTRY(void, glShaderBinary, GLsizei n, const GLuint* shaders, GLenum binaryformat, const void* binary, GLsizei length)
-GL_ENTRY(void, glShaderSource, GLuint shader, GLsizei count, const char** string, const GLint* length)
-GL_ENTRY(void, glStencilFunc, GLenum func, GLint ref, GLuint mask)
-GL_ENTRY(void, glStencilFuncSeparate, GLenum face, GLenum func, GLint ref, GLuint mask)
-GL_ENTRY(void, glStencilMask, GLuint mask)
-GL_ENTRY(void, glStencilMaskSeparate, GLenum face, GLuint mask)
-GL_ENTRY(void, glStencilOp, GLenum fail, GLenum zfail, GLenum zpass)
-GL_ENTRY(void, glStencilOpSeparate, GLenum face, GLenum fail, GLenum zfail, GLenum zpass)
-GL_ENTRY(void, glTexImage2D, GLenum target, GLint level, GLint internalformat,  GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, const GLvoid* pixels)
-GL_ENTRY(void, glTexParameterf, GLenum target, GLenum pname, GLfloat param)
-GL_ENTRY(void, glTexParameterfv, GLenum target, GLenum pname, const GLfloat* params)
-GL_ENTRY(void, glTexParameteri, GLenum target, GLenum pname, GLint param)
-GL_ENTRY(void, glTexParameteriv, GLenum target, GLenum pname, const GLint* params)
-GL_ENTRY(void, glTexSubImage2D, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const void* pixels)
-GL_ENTRY(void, glUniform1f, GLint location, GLfloat x)
-GL_ENTRY(void, glUniform1fv, GLint location, GLsizei count, const GLfloat* v)
-GL_ENTRY(void, glUniform1i, GLint location, GLint x)
-GL_ENTRY(void, glUniform1iv, GLint location, GLsizei count, const GLint* v)
-GL_ENTRY(void, glUniform2f, GLint location, GLfloat x, GLfloat y)
-GL_ENTRY(void, glUniform2fv, GLint location, GLsizei count, const GLfloat* v)
-GL_ENTRY(void, glUniform2i, GLint location, GLint x, GLint y)
-GL_ENTRY(void, glUniform2iv, GLint location, GLsizei count, const GLint* v)
-GL_ENTRY(void, glUniform3f, GLint location, GLfloat x, GLfloat y, GLfloat z)
-GL_ENTRY(void, glUniform3fv, GLint location, GLsizei count, const GLfloat* v)
-GL_ENTRY(void, glUniform3i, GLint location, GLint x, GLint y, GLint z)
-GL_ENTRY(void, glUniform3iv, GLint location, GLsizei count, const GLint* v)
-GL_ENTRY(void, glUniform4f, GLint location, GLfloat x, GLfloat y, GLfloat z, GLfloat w)
-GL_ENTRY(void, glUniform4fv, GLint location, GLsizei count, const GLfloat* v)
-GL_ENTRY(void, glUniform4i, GLint location, GLint x, GLint y, GLint z, GLint w)
-GL_ENTRY(void, glUniform4iv, GLint location, GLsizei count, const GLint* v)
-GL_ENTRY(void, glUniformMatrix2fv, GLint location, GLsizei count, GLboolean transpose, const GLfloat* value)
-GL_ENTRY(void, glUniformMatrix3fv, GLint location, GLsizei count, GLboolean transpose, const GLfloat* value)
-GL_ENTRY(void, glUniformMatrix4fv, GLint location, GLsizei count, GLboolean transpose, const GLfloat* value)
-GL_ENTRY(void, glUseProgram, GLuint program)
-GL_ENTRY(void, glValidateProgram, GLuint program)
-GL_ENTRY(void, glVertexAttrib1f, GLuint indx, GLfloat x)
-GL_ENTRY(void, glVertexAttrib1fv, GLuint indx, const GLfloat* values)
-GL_ENTRY(void, glVertexAttrib2f, GLuint indx, GLfloat x, GLfloat y)
-GL_ENTRY(void, glVertexAttrib2fv, GLuint indx, const GLfloat* values)
-GL_ENTRY(void, glVertexAttrib3f, GLuint indx, GLfloat x, GLfloat y, GLfloat z)
-GL_ENTRY(void, glVertexAttrib3fv, GLuint indx, const GLfloat* values)
-GL_ENTRY(void, glVertexAttrib4f, GLuint indx, GLfloat x, GLfloat y, GLfloat z, GLfloat w)
-GL_ENTRY(void, glVertexAttrib4fv, GLuint indx, const GLfloat* values)
-GL_ENTRY(void, glVertexAttribPointer, GLuint indx, GLint size, GLenum type, GLboolean normalized, GLsizei stride, const void* ptr)
-GL_ENTRY(void, glViewport, GLint x, GLint y, GLsizei width, GLsizei height)
diff --git a/opengl/libs/GLES2/gl2ext_entries.in b/opengl/libs/GLES2/gl2ext_entries.in
deleted file mode 100644
index e608f5d..0000000
--- a/opengl/libs/GLES2/gl2ext_entries.in
+++ /dev/null
@@ -1,35 +0,0 @@
-GL_ENTRY(void, glEGLImageTargetTexture2DOES, GLenum target, GLeglImageOES image)
-GL_ENTRY(void, glEGLImageTargetRenderbufferStorageOES, GLenum target, GLeglImageOES image)
-GL_ENTRY(void, glGetProgramBinaryOES, GLuint program, GLsizei bufSize, GLsizei *length, GLenum *binaryFormat, void *binary)
-GL_ENTRY(void, glProgramBinaryOES, GLuint program, GLenum binaryFormat, const void *binary, GLint length)
-GL_ENTRY(void*, glMapBufferOES, GLenum target, GLenum access)
-GL_ENTRY(GLboolean, glUnmapBufferOES, GLenum target)
-GL_ENTRY(void, glGetBufferPointervOES, GLenum target, GLenum pname, void** params)
-GL_ENTRY(void, glTexImage3DOES, GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLenum format, GLenum type, const void* pixels)
-GL_ENTRY(void, glTexSubImage3DOES, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, const void* pixels)
-GL_ENTRY(void, glCopyTexSubImage3DOES, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLint x, GLint y, GLsizei width, GLsizei height)
-GL_ENTRY(void, glCompressedTexImage3DOES, GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLsizei imageSize, const void* data)
-GL_ENTRY(void, glCompressedTexSubImage3DOES, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLsizei imageSize, const void* data)
-GL_ENTRY(void, glFramebufferTexture3DOES, GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level, GLint zoffset)
-GL_ENTRY(void, glGetPerfMonitorGroupsAMD, GLint *numGroups, GLsizei groupsSize, GLuint *groups)
-GL_ENTRY(void, glGetPerfMonitorCountersAMD, GLuint group, GLint *numCounters, GLint *maxActiveCounters, GLsizei counterSize, GLuint *counters)
-GL_ENTRY(void, glGetPerfMonitorGroupStringAMD, GLuint group, GLsizei bufSize, GLsizei *length, char *groupString)
-GL_ENTRY(void, glGetPerfMonitorCounterStringAMD, GLuint group, GLuint counter, GLsizei bufSize, GLsizei *length, char *counterString)
-GL_ENTRY(void, glGetPerfMonitorCounterInfoAMD, GLuint group, GLuint counter, GLenum pname, void *data)
-GL_ENTRY(void, glGenPerfMonitorsAMD, GLsizei n, GLuint *monitors)
-GL_ENTRY(void, glDeletePerfMonitorsAMD, GLsizei n, GLuint *monitors)
-GL_ENTRY(void, glSelectPerfMonitorCountersAMD, GLuint monitor, GLboolean enable, GLuint group, GLint numCounters, GLuint *countersList)
-GL_ENTRY(void, glBeginPerfMonitorAMD, GLuint monitor)
-GL_ENTRY(void, glEndPerfMonitorAMD, GLuint monitor)
-GL_ENTRY(void, glGetPerfMonitorCounterDataAMD, GLuint monitor, GLenum pname, GLsizei dataSize, GLuint *data, GLint *bytesWritten)
-GL_ENTRY(void, glDeleteFencesNV, GLsizei n, const GLuint *fences)
-GL_ENTRY(void, glGenFencesNV, GLsizei n, GLuint *fences)
-GL_ENTRY(GLboolean, glIsFenceNV, GLuint fence)
-GL_ENTRY(GLboolean, glTestFenceNV, GLuint fence)
-GL_ENTRY(void, glGetFenceivNV, GLuint fence, GLenum pname, GLint *params)
-GL_ENTRY(void, glFinishFenceNV, GLuint fence)
-GL_ENTRY(void, glSetFenceNV, GLuint fence, GLenum condition)
-GL_ENTRY(void, glGetDriverControlsQCOM, GLint *num, GLsizei size, GLuint *driverControls)
-GL_ENTRY(void, glGetDriverControlStringQCOM, GLuint driverControl, GLsizei bufSize, GLsizei *length, char *driverControlString)
-GL_ENTRY(void, glEnableDriverControlQCOM, GLuint driverControl)
-GL_ENTRY(void, glDisableDriverControlQCOM, GLuint driverControl)
diff --git a/opengl/libs/GLES_CM/gl.cpp b/opengl/libs/GLES_CM/gl.cpp
index 1e4c136..0c9352e 100644
--- a/opengl/libs/GLES_CM/gl.cpp
+++ b/opengl/libs/GLES_CM/gl.cpp
@@ -76,12 +76,20 @@
 
 #if USE_FAST_TLS_KEY && !CHECK_FOR_GL_ERRORS
 
+    #ifdef HAVE_ARM_TLS_REGISTER
+        #define GET_TLS(reg) \
+            "mrc p15, 0, " #reg ", c13, c0, 3 \n"
+    #else
+        #define GET_TLS(reg) \
+            "mov   " #reg ", #0xFFFF0FFF      \n"  \
+            "ldr   " #reg ", [" #reg ", #-15] \n"
+    #endif
+
     #define API_ENTRY(_api) __attribute__((naked)) _api
 
     #define CALL_GL_API(_api, ...)                              \
          asm volatile(                                          \
-            "mov   r12, #0xFFFF0FFF   \n"                       \
-            "ldr   r12, [r12, #-15]   \n"                       \
+            GET_TLS(r12)                                        \
             "ldr   r12, [r12, %[tls]] \n"                       \
             "cmp   r12, #0            \n"                       \
             "ldrne pc,  [r12, %[api]] \n"                       \
@@ -91,7 +99,7 @@
               [api] "J"(__builtin_offsetof(gl_hooks_t, gl._api))    \
             :                                                   \
             );
-    
+
     #define CALL_GL_API_RETURN(_api, ...) \
         CALL_GL_API(_api, __VA_ARGS__) \
         return 0; // placate gcc's warnings. never reached.
diff --git a/opengl/libs/GLES_CM/gl_entries.in b/opengl/libs/GLES_CM/gl_entries.in
deleted file mode 100644
index d7cc5da..0000000
--- a/opengl/libs/GLES_CM/gl_entries.in
+++ /dev/null
@@ -1,145 +0,0 @@
-GL_ENTRY(void, glAlphaFunc, GLenum func, GLclampf ref)
-GL_ENTRY(void, glClearColor, GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha)
-GL_ENTRY(void, glClearDepthf, GLclampf depth)
-GL_ENTRY(void, glClipPlanef, GLenum plane, const GLfloat *equation)
-GL_ENTRY(void, glColor4f, GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha)
-GL_ENTRY(void, glDepthRangef, GLclampf zNear, GLclampf zFar)
-GL_ENTRY(void, glFogf, GLenum pname, GLfloat param)
-GL_ENTRY(void, glFogfv, GLenum pname, const GLfloat *params)
-GL_ENTRY(void, glFrustumf, GLfloat left, GLfloat right, GLfloat bottom, GLfloat top, GLfloat zNear, GLfloat zFar)
-GL_ENTRY(void, glGetClipPlanef, GLenum pname, GLfloat eqn[4])
-GL_ENTRY(void, glGetFloatv, GLenum pname, GLfloat *params)
-GL_ENTRY(void, glGetLightfv, GLenum light, GLenum pname, GLfloat *params)
-GL_ENTRY(void, glGetMaterialfv, GLenum face, GLenum pname, GLfloat *params)
-GL_ENTRY(void, glGetTexEnvfv, GLenum env, GLenum pname, GLfloat *params)
-GL_ENTRY(void, glGetTexParameterfv, GLenum target, GLenum pname, GLfloat *params)
-GL_ENTRY(void, glLightModelf, GLenum pname, GLfloat param)
-GL_ENTRY(void, glLightModelfv, GLenum pname, const GLfloat *params)
-GL_ENTRY(void, glLightf, GLenum light, GLenum pname, GLfloat param)
-GL_ENTRY(void, glLightfv, GLenum light, GLenum pname, const GLfloat *params)
-GL_ENTRY(void, glLineWidth, GLfloat width)
-GL_ENTRY(void, glLoadMatrixf, const GLfloat *m)
-GL_ENTRY(void, glMaterialf, GLenum face, GLenum pname, GLfloat param)
-GL_ENTRY(void, glMaterialfv, GLenum face, GLenum pname, const GLfloat *params)
-GL_ENTRY(void, glMultMatrixf, const GLfloat *m)
-GL_ENTRY(void, glMultiTexCoord4f, GLenum target, GLfloat s, GLfloat t, GLfloat r, GLfloat q)
-GL_ENTRY(void, glNormal3f, GLfloat nx, GLfloat ny, GLfloat nz)
-GL_ENTRY(void, glOrthof, GLfloat left, GLfloat right, GLfloat bottom, GLfloat top, GLfloat zNear, GLfloat zFar)
-GL_ENTRY(void, glPointParameterf, GLenum pname, GLfloat param)
-GL_ENTRY(void, glPointParameterfv, GLenum pname, const GLfloat *params)
-GL_ENTRY(void, glPointSize, GLfloat size)
-GL_ENTRY(void, glPolygonOffset, GLfloat factor, GLfloat units)
-GL_ENTRY(void, glRotatef, GLfloat angle, GLfloat x, GLfloat y, GLfloat z)
-GL_ENTRY(void, glScalef, GLfloat x, GLfloat y, GLfloat z)
-GL_ENTRY(void, glTexEnvf, GLenum target, GLenum pname, GLfloat param)
-GL_ENTRY(void, glTexEnvfv, GLenum target, GLenum pname, const GLfloat *params)
-GL_ENTRY(void, glTexParameterf, GLenum target, GLenum pname, GLfloat param)
-GL_ENTRY(void, glTexParameterfv, GLenum target, GLenum pname, const GLfloat *params)
-GL_ENTRY(void, glTranslatef, GLfloat x, GLfloat y, GLfloat z)
-GL_ENTRY(void, glActiveTexture, GLenum texture)
-GL_ENTRY(void, glAlphaFuncx, GLenum func, GLclampx ref)
-GL_ENTRY(void, glBindBuffer, GLenum target, GLuint buffer)
-GL_ENTRY(void, glBindTexture, GLenum target, GLuint texture)
-GL_ENTRY(void, glBlendFunc, GLenum sfactor, GLenum dfactor)
-GL_ENTRY(void, glBufferData, GLenum target, GLsizeiptr size, const GLvoid *data, GLenum usage)
-GL_ENTRY(void, glBufferSubData, GLenum target, GLintptr offset, GLsizeiptr size, const GLvoid *data)
-GL_ENTRY(void, glClear, GLbitfield mask)
-GL_ENTRY(void, glClearColorx, GLclampx red, GLclampx green, GLclampx blue, GLclampx alpha)
-GL_ENTRY(void, glClearDepthx, GLclampx depth)
-GL_ENTRY(void, glClearStencil, GLint s)
-GL_ENTRY(void, glClientActiveTexture, GLenum texture)
-GL_ENTRY(void, glClipPlanex, GLenum plane, const GLfixed *equation)
-GL_ENTRY(void, glColor4ub, GLubyte red, GLubyte green, GLubyte blue, GLubyte alpha)
-GL_ENTRY(void, glColor4x, GLfixed red, GLfixed green, GLfixed blue, GLfixed alpha)
-GL_ENTRY(void, glColorMask, GLboolean red, GLboolean green, GLboolean blue, GLboolean alpha)
-GL_ENTRY(void, glColorPointer, GLint size, GLenum type, GLsizei stride, const GLvoid *pointer)
-GL_ENTRY(void, glCompressedTexImage2D, GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLint border, GLsizei imageSize, const GLvoid *data)
-GL_ENTRY(void, glCompressedTexSubImage2D, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const GLvoid *data)
-GL_ENTRY(void, glCopyTexImage2D, GLenum target, GLint level, GLenum internalformat, GLint x, GLint y, GLsizei width, GLsizei height, GLint border)
-GL_ENTRY(void, glCopyTexSubImage2D, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height)
-GL_ENTRY(void, glCullFace, GLenum mode)
-GL_ENTRY(void, glDeleteBuffers, GLsizei n, const GLuint *buffers)
-GL_ENTRY(void, glDeleteTextures, GLsizei n, const GLuint *textures)
-GL_ENTRY(void, glDepthFunc, GLenum func)
-GL_ENTRY(void, glDepthMask, GLboolean flag)
-GL_ENTRY(void, glDepthRangex, GLclampx zNear, GLclampx zFar)
-GL_ENTRY(void, glDisable, GLenum cap)
-GL_ENTRY(void, glDisableClientState, GLenum array)
-GL_ENTRY(void, glDrawArrays, GLenum mode, GLint first, GLsizei count)
-GL_ENTRY(void, glDrawElements, GLenum mode, GLsizei count, GLenum type, const GLvoid *indices)
-GL_ENTRY(void, glEnable, GLenum cap)
-GL_ENTRY(void, glEnableClientState, GLenum array)
-GL_ENTRY(void, glFinish, void)
-GL_ENTRY(void, glFlush, void)
-GL_ENTRY(void, glFogx, GLenum pname, GLfixed param)
-GL_ENTRY(void, glFogxv, GLenum pname, const GLfixed *params)
-GL_ENTRY(void, glFrontFace, GLenum mode)
-GL_ENTRY(void, glFrustumx, GLfixed left, GLfixed right, GLfixed bottom, GLfixed top, GLfixed zNear, GLfixed zFar)
-GL_ENTRY(void, glGetBooleanv, GLenum pname, GLboolean *params)
-GL_ENTRY(void, glGetBufferParameteriv, GLenum target, GLenum pname, GLint *params)
-GL_ENTRY(void, glGetClipPlanex, GLenum pname, GLfixed eqn[4])
-GL_ENTRY(void, glGenBuffers, GLsizei n, GLuint *buffers)
-GL_ENTRY(void, glGenTextures, GLsizei n, GLuint *textures)
-GL_ENTRY(GLenum, glGetError, void)
-GL_ENTRY(void, glGetFixedv, GLenum pname, GLfixed *params)
-GL_ENTRY(void, glGetIntegerv, GLenum pname, GLint *params)
-GL_ENTRY(void, glGetLightxv, GLenum light, GLenum pname, GLfixed *params)
-GL_ENTRY(void, glGetMaterialxv, GLenum face, GLenum pname, GLfixed *params)
-GL_ENTRY(void, glGetPointerv, GLenum pname, void **params)
-GL_ENTRY(const GLubyte *, glGetString, GLenum name)
-GL_ENTRY(void, glGetTexEnviv, GLenum env, GLenum pname, GLint *params)
-GL_ENTRY(void, glGetTexEnvxv, GLenum env, GLenum pname, GLfixed *params)
-GL_ENTRY(void, glGetTexParameteriv, GLenum target, GLenum pname, GLint *params)
-GL_ENTRY(void, glGetTexParameterxv, GLenum target, GLenum pname, GLfixed *params)
-GL_ENTRY(void, glHint, GLenum target, GLenum mode)
-GL_ENTRY(GLboolean, glIsBuffer, GLuint buffer)
-GL_ENTRY(GLboolean, glIsEnabled, GLenum cap)
-GL_ENTRY(GLboolean, glIsTexture, GLuint texture)
-GL_ENTRY(void, glLightModelx, GLenum pname, GLfixed param)
-GL_ENTRY(void, glLightModelxv, GLenum pname, const GLfixed *params)
-GL_ENTRY(void, glLightx, GLenum light, GLenum pname, GLfixed param)
-GL_ENTRY(void, glLightxv, GLenum light, GLenum pname, const GLfixed *params)
-GL_ENTRY(void, glLineWidthx, GLfixed width)
-GL_ENTRY(void, glLoadIdentity, void)
-GL_ENTRY(void, glLoadMatrixx, const GLfixed *m)
-GL_ENTRY(void, glLogicOp, GLenum opcode)
-GL_ENTRY(void, glMaterialx, GLenum face, GLenum pname, GLfixed param)
-GL_ENTRY(void, glMaterialxv, GLenum face, GLenum pname, const GLfixed *params)
-GL_ENTRY(void, glMatrixMode, GLenum mode)
-GL_ENTRY(void, glMultMatrixx, const GLfixed *m)
-GL_ENTRY(void, glMultiTexCoord4x, GLenum target, GLfixed s, GLfixed t, GLfixed r, GLfixed q)
-GL_ENTRY(void, glNormal3x, GLfixed nx, GLfixed ny, GLfixed nz)
-GL_ENTRY(void, glNormalPointer, GLenum type, GLsizei stride, const GLvoid *pointer)
-GL_ENTRY(void, glOrthox, GLfixed left, GLfixed right, GLfixed bottom, GLfixed top, GLfixed zNear, GLfixed zFar)
-GL_ENTRY(void, glPixelStorei, GLenum pname, GLint param)
-GL_ENTRY(void, glPointParameterx, GLenum pname, GLfixed param)
-GL_ENTRY(void, glPointParameterxv, GLenum pname, const GLfixed *params)
-GL_ENTRY(void, glPointSizex, GLfixed size)
-GL_ENTRY(void, glPolygonOffsetx, GLfixed factor, GLfixed units)
-GL_ENTRY(void, glPopMatrix, void)
-GL_ENTRY(void, glPushMatrix, void)
-GL_ENTRY(void, glReadPixels, GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, GLvoid *pixels)
-GL_ENTRY(void, glRotatex, GLfixed angle, GLfixed x, GLfixed y, GLfixed z)
-GL_ENTRY(void, glSampleCoverage, GLclampf value, GLboolean invert)
-GL_ENTRY(void, glSampleCoveragex, GLclampx value, GLboolean invert)
-GL_ENTRY(void, glScalex, GLfixed x, GLfixed y, GLfixed z)
-GL_ENTRY(void, glScissor, GLint x, GLint y, GLsizei width, GLsizei height)
-GL_ENTRY(void, glShadeModel, GLenum mode)
-GL_ENTRY(void, glStencilFunc, GLenum func, GLint ref, GLuint mask)
-GL_ENTRY(void, glStencilMask, GLuint mask)
-GL_ENTRY(void, glStencilOp, GLenum fail, GLenum zfail, GLenum zpass)
-GL_ENTRY(void, glTexCoordPointer, GLint size, GLenum type, GLsizei stride, const GLvoid *pointer)
-GL_ENTRY(void, glTexEnvi, GLenum target, GLenum pname, GLint param)
-GL_ENTRY(void, glTexEnvx, GLenum target, GLenum pname, GLfixed param)
-GL_ENTRY(void, glTexEnviv, GLenum target, GLenum pname, const GLint *params)
-GL_ENTRY(void, glTexEnvxv, GLenum target, GLenum pname, const GLfixed *params)
-GL_ENTRY(void, glTexImage2D, GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, const GLvoid *pixels)
-GL_ENTRY(void, glTexParameteri, GLenum target, GLenum pname, GLint param)
-GL_ENTRY(void, glTexParameterx, GLenum target, GLenum pname, GLfixed param)
-GL_ENTRY(void, glTexParameteriv, GLenum target, GLenum pname, const GLint *params)
-GL_ENTRY(void, glTexParameterxv, GLenum target, GLenum pname, const GLfixed *params)
-GL_ENTRY(void, glTexSubImage2D, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const GLvoid *pixels)
-GL_ENTRY(void, glTranslatex, GLfixed x, GLfixed y, GLfixed z)
-GL_ENTRY(void, glVertexPointer, GLint size, GLenum type, GLsizei stride, const GLvoid *pointer)
-GL_ENTRY(void, glViewport, GLint x, GLint y, GLsizei width, GLsizei height)
-GL_ENTRY(void, glPointSizePointerOES, GLenum type, GLsizei stride, const GLvoid *pointer)
diff --git a/opengl/libs/GLES_CM/glext_entries.in b/opengl/libs/GLES_CM/glext_entries.in
deleted file mode 100644
index dd09c71..0000000
--- a/opengl/libs/GLES_CM/glext_entries.in
+++ /dev/null
@@ -1,90 +0,0 @@
-GL_ENTRY(void, glBlendEquationSeparateOES, GLenum modeRGB, GLenum modeAlpha)
-GL_ENTRY(void, glBlendFuncSeparateOES, GLenum srcRGB, GLenum dstRGB, GLenum srcAlpha, GLenum dstAlpha)
-GL_ENTRY(void, glBlendEquationOES, GLenum mode)
-GL_ENTRY(void, glDrawTexsOES, GLshort x, GLshort y, GLshort z, GLshort width, GLshort height)
-GL_ENTRY(void, glDrawTexiOES, GLint x, GLint y, GLint z, GLint width, GLint height)
-GL_ENTRY(void, glDrawTexxOES, GLfixed x, GLfixed y, GLfixed z, GLfixed width, GLfixed height)
-GL_ENTRY(void, glDrawTexsvOES, const GLshort *coords)
-GL_ENTRY(void, glDrawTexivOES, const GLint *coords)
-GL_ENTRY(void, glDrawTexxvOES, const GLfixed *coords)
-GL_ENTRY(void, glDrawTexfOES, GLfloat x, GLfloat y, GLfloat z, GLfloat width, GLfloat height)
-GL_ENTRY(void, glDrawTexfvOES, const GLfloat *coords)
-GL_ENTRY(void, glEGLImageTargetTexture2DOES, GLenum target, GLeglImageOES image)
-GL_ENTRY(void, glEGLImageTargetRenderbufferStorageOES, GLenum target, GLeglImageOES image)
-GL_ENTRY(void, glAlphaFuncxOES, GLenum func, GLclampx ref)
-GL_ENTRY(void, glClearColorxOES, GLclampx red, GLclampx green, GLclampx blue, GLclampx alpha)
-GL_ENTRY(void, glClearDepthxOES, GLclampx depth)
-GL_ENTRY(void, glClipPlanexOES, GLenum plane, const GLfixed *equation)
-GL_ENTRY(void, glColor4xOES, GLfixed red, GLfixed green, GLfixed blue, GLfixed alpha)
-GL_ENTRY(void, glDepthRangexOES, GLclampx zNear, GLclampx zFar)
-GL_ENTRY(void, glFogxOES, GLenum pname, GLfixed param)
-GL_ENTRY(void, glFogxvOES, GLenum pname, const GLfixed *params)
-GL_ENTRY(void, glFrustumxOES, GLfixed left, GLfixed right, GLfixed bottom, GLfixed top, GLfixed zNear, GLfixed zFar)
-GL_ENTRY(void, glGetClipPlanexOES, GLenum pname, GLfixed eqn[4])
-GL_ENTRY(void, glGetFixedvOES, GLenum pname, GLfixed *params)
-GL_ENTRY(void, glGetLightxvOES, GLenum light, GLenum pname, GLfixed *params)
-GL_ENTRY(void, glGetMaterialxvOES, GLenum face, GLenum pname, GLfixed *params)
-GL_ENTRY(void, glGetTexEnvxvOES, GLenum env, GLenum pname, GLfixed *params)
-GL_ENTRY(void, glGetTexParameterxvOES, GLenum target, GLenum pname, GLfixed *params)
-GL_ENTRY(void, glLightModelxOES, GLenum pname, GLfixed param)
-GL_ENTRY(void, glLightModelxvOES, GLenum pname, const GLfixed *params)
-GL_ENTRY(void, glLightxOES, GLenum light, GLenum pname, GLfixed param)
-GL_ENTRY(void, glLightxvOES, GLenum light, GLenum pname, const GLfixed *params)
-GL_ENTRY(void, glLineWidthxOES, GLfixed width)
-GL_ENTRY(void, glLoadMatrixxOES, const GLfixed *m)
-GL_ENTRY(void, glMaterialxOES, GLenum face, GLenum pname, GLfixed param)
-GL_ENTRY(void, glMaterialxvOES, GLenum face, GLenum pname, const GLfixed *params)
-GL_ENTRY(void, glMultMatrixxOES, const GLfixed *m)
-GL_ENTRY(void, glMultiTexCoord4xOES, GLenum target, GLfixed s, GLfixed t, GLfixed r, GLfixed q)
-GL_ENTRY(void, glNormal3xOES, GLfixed nx, GLfixed ny, GLfixed nz)
-GL_ENTRY(void, glOrthoxOES, GLfixed left, GLfixed right, GLfixed bottom, GLfixed top, GLfixed zNear, GLfixed zFar)
-GL_ENTRY(void, glPointParameterxOES, GLenum pname, GLfixed param)
-GL_ENTRY(void, glPointParameterxvOES, GLenum pname, const GLfixed *params)
-GL_ENTRY(void, glPointSizexOES, GLfixed size)
-GL_ENTRY(void, glPolygonOffsetxOES, GLfixed factor, GLfixed units)
-GL_ENTRY(void, glRotatexOES, GLfixed angle, GLfixed x, GLfixed y, GLfixed z)
-GL_ENTRY(void, glSampleCoveragexOES, GLclampx value, GLboolean invert)
-GL_ENTRY(void, glScalexOES, GLfixed x, GLfixed y, GLfixed z)
-GL_ENTRY(void, glTexEnvxOES, GLenum target, GLenum pname, GLfixed param)
-GL_ENTRY(void, glTexEnvxvOES, GLenum target, GLenum pname, const GLfixed *params)
-GL_ENTRY(void, glTexParameterxOES, GLenum target, GLenum pname, GLfixed param)
-GL_ENTRY(void, glTexParameterxvOES, GLenum target, GLenum pname, const GLfixed *params)
-GL_ENTRY(void, glTranslatexOES, GLfixed x, GLfixed y, GLfixed z)
-GL_ENTRY(GLboolean, glIsRenderbufferOES, GLuint renderbuffer)
-GL_ENTRY(void, glBindRenderbufferOES, GLenum target, GLuint renderbuffer)
-GL_ENTRY(void, glDeleteRenderbuffersOES, GLsizei n, const GLuint* renderbuffers)
-GL_ENTRY(void, glGenRenderbuffersOES, GLsizei n, GLuint* renderbuffers)
-GL_ENTRY(void, glRenderbufferStorageOES, GLenum target, GLenum internalformat, GLsizei width, GLsizei height)
-GL_ENTRY(void, glGetRenderbufferParameterivOES, GLenum target, GLenum pname, GLint* params)
-GL_ENTRY(GLboolean, glIsFramebufferOES, GLuint framebuffer)
-GL_ENTRY(void, glBindFramebufferOES, GLenum target, GLuint framebuffer)
-GL_ENTRY(void, glDeleteFramebuffersOES, GLsizei n, const GLuint* framebuffers)
-GL_ENTRY(void, glGenFramebuffersOES, GLsizei n, GLuint* framebuffers)
-GL_ENTRY(GLenum, glCheckFramebufferStatusOES, GLenum target)
-GL_ENTRY(void, glFramebufferRenderbufferOES, GLenum target, GLenum attachment, GLenum renderbuffertarget, GLuint renderbuffer)
-GL_ENTRY(void, glFramebufferTexture2DOES, GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level)
-GL_ENTRY(void, glGetFramebufferAttachmentParameterivOES, GLenum target, GLenum attachment, GLenum pname, GLint* params)
-GL_ENTRY(void, glGenerateMipmapOES, GLenum target)
-GL_ENTRY(void*, glMapBufferOES, GLenum target, GLenum access)
-GL_ENTRY(GLboolean, glUnmapBufferOES, GLenum target)
-GL_ENTRY(void, glGetBufferPointervOES, GLenum target, GLenum pname, void** params)
-GL_ENTRY(void, glCurrentPaletteMatrixOES, GLuint matrixpaletteindex)
-GL_ENTRY(void, glLoadPaletteFromModelViewMatrixOES, void)
-GL_ENTRY(void, glMatrixIndexPointerOES, GLint size, GLenum type, GLsizei stride, const GLvoid *pointer)
-GL_ENTRY(void, glWeightPointerOES, GLint size, GLenum type, GLsizei stride, const GLvoid *pointer)
-GL_ENTRY(GLbitfield, glQueryMatrixxOES, GLfixed mantissa[16], GLint exponent[16])
-GL_ENTRY(void, glDepthRangefOES, GLclampf zNear, GLclampf zFar)
-GL_ENTRY(void, glFrustumfOES, GLfloat left, GLfloat right, GLfloat bottom, GLfloat top, GLfloat zNear, GLfloat zFar)
-GL_ENTRY(void, glOrthofOES, GLfloat left, GLfloat right, GLfloat bottom, GLfloat top, GLfloat zNear, GLfloat zFar)
-GL_ENTRY(void, glClipPlanefOES, GLenum plane, const GLfloat *equation)
-GL_ENTRY(void, glGetClipPlanefOES, GLenum pname, GLfloat eqn[4])
-GL_ENTRY(void, glClearDepthfOES, GLclampf depth)
-GL_ENTRY(void, glTexGenfOES, GLenum coord, GLenum pname, GLfloat param)
-GL_ENTRY(void, glTexGenfvOES, GLenum coord, GLenum pname, const GLfloat *params)
-GL_ENTRY(void, glTexGeniOES, GLenum coord, GLenum pname, GLint param)
-GL_ENTRY(void, glTexGenivOES, GLenum coord, GLenum pname, const GLint *params)
-GL_ENTRY(void, glTexGenxOES, GLenum coord, GLenum pname, GLfixed param)
-GL_ENTRY(void, glTexGenxvOES, GLenum coord, GLenum pname, const GLfixed *params)
-GL_ENTRY(void, glGetTexGenfvOES, GLenum coord, GLenum pname, GLfloat *params)
-GL_ENTRY(void, glGetTexGenivOES, GLenum coord, GLenum pname, GLint *params)
-GL_ENTRY(void, glGetTexGenxvOES, GLenum coord, GLenum pname, GLfixed *params)
diff --git a/opengl/libs/egl_impl.h b/opengl/libs/egl_impl.h
index ac286cb..1fba209 100644
--- a/opengl/libs/egl_impl.h
+++ b/opengl/libs/egl_impl.h
@@ -23,18 +23,19 @@
 #include <EGL/eglext.h>
 #include <EGL/eglplatform.h>
 
+#include "hooks.h"
+
 // ----------------------------------------------------------------------------
 namespace android {
 // ----------------------------------------------------------------------------
 
-struct gl_hooks_t;
-
 struct egl_connection_t
 {
     void *              dso;
-    gl_hooks_t *        hooks;
+    gl_hooks_t *        hooks[2];
     EGLint              major;
     EGLint              minor;
+    egl_t               egl;
 };
 
 EGLAPI EGLImageKHR egl_get_image_for_current_context(EGLImageKHR image);
diff --git a/opengl/libs/entries.in b/opengl/libs/entries.in
new file mode 100644
index 0000000..bbe3e23
--- /dev/null
+++ b/opengl/libs/entries.in
@@ -0,0 +1,349 @@
+GL_ENTRY(void, glActiveTexture, GLenum texture)
+GL_ENTRY(void, glAlphaFunc, GLenum func, GLclampf ref)
+GL_ENTRY(void, glAlphaFuncx, GLenum func, GLclampx ref)
+GL_ENTRY(void, glAlphaFuncxOES, GLenum func, GLclampx ref)
+GL_ENTRY(void, glAttachShader, GLuint program, GLuint shader)
+GL_ENTRY(void, glBeginPerfMonitorAMD, GLuint monitor)
+GL_ENTRY(void, glBindAttribLocation, GLuint program, GLuint index, const char* name)
+GL_ENTRY(void, glBindBuffer, GLenum target, GLuint buffer)
+GL_ENTRY(void, glBindFramebuffer, GLenum target, GLuint framebuffer)
+GL_ENTRY(void, glBindFramebufferOES, GLenum target, GLuint framebuffer)
+GL_ENTRY(void, glBindRenderbuffer, GLenum target, GLuint renderbuffer)
+GL_ENTRY(void, glBindRenderbufferOES, GLenum target, GLuint renderbuffer)
+GL_ENTRY(void, glBindTexture, GLenum target, GLuint texture)
+GL_ENTRY(void, glBlendColor, GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha)
+GL_ENTRY(void, glBlendEquation,  GLenum mode )
+GL_ENTRY(void, glBlendEquationOES, GLenum mode)
+GL_ENTRY(void, glBlendEquationSeparate, GLenum modeRGB, GLenum modeAlpha)
+GL_ENTRY(void, glBlendEquationSeparateOES, GLenum modeRGB, GLenum modeAlpha)
+GL_ENTRY(void, glBlendFunc, GLenum sfactor, GLenum dfactor)
+GL_ENTRY(void, glBlendFuncSeparate, GLenum srcRGB, GLenum dstRGB, GLenum srcAlpha, GLenum dstAlpha)
+GL_ENTRY(void, glBlendFuncSeparateOES, GLenum srcRGB, GLenum dstRGB, GLenum srcAlpha, GLenum dstAlpha)
+GL_ENTRY(void, glBufferData, GLenum target, GLsizeiptr size, const GLvoid *data, GLenum usage)
+GL_ENTRY(void, glBufferSubData, GLenum target, GLintptr offset, GLsizeiptr size, const GLvoid *data)
+GL_ENTRY(GLenum, glCheckFramebufferStatus, GLenum target)
+GL_ENTRY(GLenum, glCheckFramebufferStatusOES, GLenum target)
+GL_ENTRY(void, glClear, GLbitfield mask)
+GL_ENTRY(void, glClearColor, GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha)
+GL_ENTRY(void, glClearColorx, GLclampx red, GLclampx green, GLclampx blue, GLclampx alpha)
+GL_ENTRY(void, glClearColorxOES, GLclampx red, GLclampx green, GLclampx blue, GLclampx alpha)
+GL_ENTRY(void, glClearDepthf, GLclampf depth)
+GL_ENTRY(void, glClearDepthfOES, GLclampf depth)
+GL_ENTRY(void, glClearDepthx, GLclampx depth)
+GL_ENTRY(void, glClearDepthxOES, GLclampx depth)
+GL_ENTRY(void, glClearStencil, GLint s)
+GL_ENTRY(void, glClientActiveTexture, GLenum texture)
+GL_ENTRY(void, glClipPlanef, GLenum plane, const GLfloat *equation)
+GL_ENTRY(void, glClipPlanefOES, GLenum plane, const GLfloat *equation)
+GL_ENTRY(void, glClipPlanex, GLenum plane, const GLfixed *equation)
+GL_ENTRY(void, glClipPlanexOES, GLenum plane, const GLfixed *equation)
+GL_ENTRY(void, glColor4f, GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha)
+GL_ENTRY(void, glColor4ub, GLubyte red, GLubyte green, GLubyte blue, GLubyte alpha)
+GL_ENTRY(void, glColor4x, GLfixed red, GLfixed green, GLfixed blue, GLfixed alpha)
+GL_ENTRY(void, glColor4xOES, GLfixed red, GLfixed green, GLfixed blue, GLfixed alpha)
+GL_ENTRY(void, glColorMask, GLboolean red, GLboolean green, GLboolean blue, GLboolean alpha)
+GL_ENTRY(void, glColorPointer, GLint size, GLenum type, GLsizei stride, const GLvoid *pointer)
+GL_ENTRY(void, glCompileShader, GLuint shader)
+GL_ENTRY(void, glCompressedTexImage2D, GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLint border, GLsizei imageSize, const GLvoid *data)
+GL_ENTRY(void, glCompressedTexImage3DOES, GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLsizei imageSize, const void* data)
+GL_ENTRY(void, glCompressedTexSubImage2D, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const GLvoid *data)
+GL_ENTRY(void, glCompressedTexSubImage3DOES, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLsizei imageSize, const void* data)
+GL_ENTRY(void, glCopyTexImage2D, GLenum target, GLint level, GLenum internalformat, GLint x, GLint y, GLsizei width, GLsizei height, GLint border)
+GL_ENTRY(void, glCopyTexSubImage2D, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height)
+GL_ENTRY(void, glCopyTexSubImage3DOES, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLint x, GLint y, GLsizei width, GLsizei height)
+GL_ENTRY(GLuint, glCreateProgram, void)
+GL_ENTRY(GLuint, glCreateShader, GLenum type)
+GL_ENTRY(void, glCullFace, GLenum mode)
+GL_ENTRY(void, glCurrentPaletteMatrixOES, GLuint matrixpaletteindex)
+GL_ENTRY(void, glDeleteBuffers, GLsizei n, const GLuint *buffers)
+GL_ENTRY(void, glDeleteFencesNV, GLsizei n, const GLuint *fences)
+GL_ENTRY(void, glDeleteFramebuffers, GLsizei n, const GLuint* framebuffers)
+GL_ENTRY(void, glDeleteFramebuffersOES, GLsizei n, const GLuint* framebuffers)
+GL_ENTRY(void, glDeletePerfMonitorsAMD, GLsizei n, GLuint *monitors)
+GL_ENTRY(void, glDeleteProgram, GLuint program)
+GL_ENTRY(void, glDeleteRenderbuffers, GLsizei n, const GLuint* renderbuffers)
+GL_ENTRY(void, glDeleteRenderbuffersOES, GLsizei n, const GLuint* renderbuffers)
+GL_ENTRY(void, glDeleteShader, GLuint shader)
+GL_ENTRY(void, glDeleteTextures, GLsizei n, const GLuint *textures)
+GL_ENTRY(void, glDepthFunc, GLenum func)
+GL_ENTRY(void, glDepthMask, GLboolean flag)
+GL_ENTRY(void, glDepthRangef, GLclampf zNear, GLclampf zFar)
+GL_ENTRY(void, glDepthRangefOES, GLclampf zNear, GLclampf zFar)
+GL_ENTRY(void, glDepthRangex, GLclampx zNear, GLclampx zFar)
+GL_ENTRY(void, glDepthRangexOES, GLclampx zNear, GLclampx zFar)
+GL_ENTRY(void, glDetachShader, GLuint program, GLuint shader)
+GL_ENTRY(void, glDisable, GLenum cap)
+GL_ENTRY(void, glDisableClientState, GLenum array)
+GL_ENTRY(void, glDisableDriverControlQCOM, GLuint driverControl)
+GL_ENTRY(void, glDisableVertexAttribArray, GLuint index)
+GL_ENTRY(void, glDrawArrays, GLenum mode, GLint first, GLsizei count)
+GL_ENTRY(void, glDrawElements, GLenum mode, GLsizei count, GLenum type, const GLvoid *indices)
+GL_ENTRY(void, glDrawTexfOES, GLfloat x, GLfloat y, GLfloat z, GLfloat width, GLfloat height)
+GL_ENTRY(void, glDrawTexfvOES, const GLfloat *coords)
+GL_ENTRY(void, glDrawTexiOES, GLint x, GLint y, GLint z, GLint width, GLint height)
+GL_ENTRY(void, glDrawTexivOES, const GLint *coords)
+GL_ENTRY(void, glDrawTexsOES, GLshort x, GLshort y, GLshort z, GLshort width, GLshort height)
+GL_ENTRY(void, glDrawTexsvOES, const GLshort *coords)
+GL_ENTRY(void, glDrawTexxOES, GLfixed x, GLfixed y, GLfixed z, GLfixed width, GLfixed height)
+GL_ENTRY(void, glDrawTexxvOES, const GLfixed *coords)
+GL_ENTRY(void, glEGLImageTargetRenderbufferStorageOES, GLenum target, GLeglImageOES image)
+GL_ENTRY(void, glEGLImageTargetTexture2DOES, GLenum target, GLeglImageOES image)
+GL_ENTRY(void, glEnable, GLenum cap)
+GL_ENTRY(void, glEnableClientState, GLenum array)
+GL_ENTRY(void, glEnableDriverControlQCOM, GLuint driverControl)
+GL_ENTRY(void, glEnableVertexAttribArray, GLuint index)
+GL_ENTRY(void, glEndPerfMonitorAMD, GLuint monitor)
+GL_ENTRY(void, glFinish, void)
+GL_ENTRY(void, glFinishFenceNV, GLuint fence)
+GL_ENTRY(void, glFlush, void)
+GL_ENTRY(void, glFogf, GLenum pname, GLfloat param)
+GL_ENTRY(void, glFogfv, GLenum pname, const GLfloat *params)
+GL_ENTRY(void, glFogx, GLenum pname, GLfixed param)
+GL_ENTRY(void, glFogxOES, GLenum pname, GLfixed param)
+GL_ENTRY(void, glFogxv, GLenum pname, const GLfixed *params)
+GL_ENTRY(void, glFogxvOES, GLenum pname, const GLfixed *params)
+GL_ENTRY(void, glFramebufferRenderbuffer, GLenum target, GLenum attachment, GLenum renderbuffertarget, GLuint renderbuffer)
+GL_ENTRY(void, glFramebufferRenderbufferOES, GLenum target, GLenum attachment, GLenum renderbuffertarget, GLuint renderbuffer)
+GL_ENTRY(void, glFramebufferTexture2D, GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level)
+GL_ENTRY(void, glFramebufferTexture2DOES, GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level)
+GL_ENTRY(void, glFramebufferTexture3DOES, GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level, GLint zoffset)
+GL_ENTRY(void, glFrontFace, GLenum mode)
+GL_ENTRY(void, glFrustumf, GLfloat left, GLfloat right, GLfloat bottom, GLfloat top, GLfloat zNear, GLfloat zFar)
+GL_ENTRY(void, glFrustumfOES, GLfloat left, GLfloat right, GLfloat bottom, GLfloat top, GLfloat zNear, GLfloat zFar)
+GL_ENTRY(void, glFrustumx, GLfixed left, GLfixed right, GLfixed bottom, GLfixed top, GLfixed zNear, GLfixed zFar)
+GL_ENTRY(void, glFrustumxOES, GLfixed left, GLfixed right, GLfixed bottom, GLfixed top, GLfixed zNear, GLfixed zFar)
+GL_ENTRY(void, glGenBuffers, GLsizei n, GLuint *buffers)
+GL_ENTRY(void, glGenFencesNV, GLsizei n, GLuint *fences)
+GL_ENTRY(void, glGenFramebuffers, GLsizei n, GLuint* framebuffers)
+GL_ENTRY(void, glGenFramebuffersOES, GLsizei n, GLuint* framebuffers)
+GL_ENTRY(void, glGenPerfMonitorsAMD, GLsizei n, GLuint *monitors)
+GL_ENTRY(void, glGenRenderbuffers, GLsizei n, GLuint* renderbuffers)
+GL_ENTRY(void, glGenRenderbuffersOES, GLsizei n, GLuint* renderbuffers)
+GL_ENTRY(void, glGenTextures, GLsizei n, GLuint *textures)
+GL_ENTRY(void, glGenerateMipmap, GLenum target)
+GL_ENTRY(void, glGenerateMipmapOES, GLenum target)
+GL_ENTRY(void, glGetActiveAttrib, GLuint program, GLuint index, GLsizei bufsize, GLsizei* length, GLint* size, GLenum* type, char* name)
+GL_ENTRY(void, glGetActiveUniform, GLuint program, GLuint index, GLsizei bufsize, GLsizei* length, GLint* size, GLenum* type, char* name)
+GL_ENTRY(void, glGetAttachedShaders, GLuint program, GLsizei maxcount, GLsizei* count, GLuint* shaders)
+GL_ENTRY(int, glGetAttribLocation, GLuint program, const char* name)
+GL_ENTRY(void, glGetBooleanv, GLenum pname, GLboolean *params)
+GL_ENTRY(void, glGetBufferParameteriv, GLenum target, GLenum pname, GLint *params)
+GL_ENTRY(void, glGetBufferPointervOES, GLenum target, GLenum pname, void** params)
+GL_ENTRY(void, glGetClipPlanef, GLenum pname, GLfloat eqn[4])
+GL_ENTRY(void, glGetClipPlanefOES, GLenum pname, GLfloat eqn[4])
+GL_ENTRY(void, glGetClipPlanex, GLenum pname, GLfixed eqn[4])
+GL_ENTRY(void, glGetClipPlanexOES, GLenum pname, GLfixed eqn[4])
+GL_ENTRY(void, glGetDriverControlStringQCOM, GLuint driverControl, GLsizei bufSize, GLsizei *length, char *driverControlString)
+GL_ENTRY(void, glGetDriverControlsQCOM, GLint *num, GLsizei size, GLuint *driverControls)
+GL_ENTRY(GLenum, glGetError, void)
+GL_ENTRY(void, glGetFenceivNV, GLuint fence, GLenum pname, GLint *params)
+GL_ENTRY(void, glGetFixedv, GLenum pname, GLfixed *params)
+GL_ENTRY(void, glGetFixedvOES, GLenum pname, GLfixed *params)
+GL_ENTRY(void, glGetFloatv, GLenum pname, GLfloat *params)
+GL_ENTRY(void, glGetFramebufferAttachmentParameteriv, GLenum target, GLenum attachment, GLenum pname, GLint* params)
+GL_ENTRY(void, glGetFramebufferAttachmentParameterivOES, GLenum target, GLenum attachment, GLenum pname, GLint* params)
+GL_ENTRY(void, glGetIntegerv, GLenum pname, GLint *params)
+GL_ENTRY(void, glGetLightfv, GLenum light, GLenum pname, GLfloat *params)
+GL_ENTRY(void, glGetLightxv, GLenum light, GLenum pname, GLfixed *params)
+GL_ENTRY(void, glGetLightxvOES, GLenum light, GLenum pname, GLfixed *params)
+GL_ENTRY(void, glGetMaterialfv, GLenum face, GLenum pname, GLfloat *params)
+GL_ENTRY(void, glGetMaterialxv, GLenum face, GLenum pname, GLfixed *params)
+GL_ENTRY(void, glGetMaterialxvOES, GLenum face, GLenum pname, GLfixed *params)
+GL_ENTRY(void, glGetPerfMonitorCounterDataAMD, GLuint monitor, GLenum pname, GLsizei dataSize, GLuint *data, GLint *bytesWritten)
+GL_ENTRY(void, glGetPerfMonitorCounterInfoAMD, GLuint group, GLuint counter, GLenum pname, void *data)
+GL_ENTRY(void, glGetPerfMonitorCounterStringAMD, GLuint group, GLuint counter, GLsizei bufSize, GLsizei *length, char *counterString)
+GL_ENTRY(void, glGetPerfMonitorCountersAMD, GLuint group, GLint *numCounters, GLint *maxActiveCounters, GLsizei counterSize, GLuint *counters)
+GL_ENTRY(void, glGetPerfMonitorGroupStringAMD, GLuint group, GLsizei bufSize, GLsizei *length, char *groupString)
+GL_ENTRY(void, glGetPerfMonitorGroupsAMD, GLint *numGroups, GLsizei groupsSize, GLuint *groups)
+GL_ENTRY(void, glGetPointerv, GLenum pname, void **params)
+GL_ENTRY(void, glGetProgramBinaryOES, GLuint program, GLsizei bufSize, GLsizei *length, GLenum *binaryFormat, void *binary)
+GL_ENTRY(void, glGetProgramInfoLog, GLuint program, GLsizei bufsize, GLsizei* length, char* infolog)
+GL_ENTRY(void, glGetProgramiv, GLuint program, GLenum pname, GLint* params)
+GL_ENTRY(void, glGetRenderbufferParameteriv, GLenum target, GLenum pname, GLint* params)
+GL_ENTRY(void, glGetRenderbufferParameterivOES, GLenum target, GLenum pname, GLint* params)
+GL_ENTRY(void, glGetShaderInfoLog, GLuint shader, GLsizei bufsize, GLsizei* length, char* infolog)
+GL_ENTRY(void, glGetShaderPrecisionFormat, GLenum shadertype, GLenum precisiontype, GLint* range, GLint* precision)
+GL_ENTRY(void, glGetShaderSource, GLuint shader, GLsizei bufsize, GLsizei* length, char* source)
+GL_ENTRY(void, glGetShaderiv, GLuint shader, GLenum pname, GLint* params)
+GL_ENTRY(const GLubyte *, glGetString, GLenum name)
+GL_ENTRY(void, glGetTexEnvfv, GLenum env, GLenum pname, GLfloat *params)
+GL_ENTRY(void, glGetTexEnviv, GLenum env, GLenum pname, GLint *params)
+GL_ENTRY(void, glGetTexEnvxv, GLenum env, GLenum pname, GLfixed *params)
+GL_ENTRY(void, glGetTexEnvxvOES, GLenum env, GLenum pname, GLfixed *params)
+GL_ENTRY(void, glGetTexGenfvOES, GLenum coord, GLenum pname, GLfloat *params)
+GL_ENTRY(void, glGetTexGenivOES, GLenum coord, GLenum pname, GLint *params)
+GL_ENTRY(void, glGetTexGenxvOES, GLenum coord, GLenum pname, GLfixed *params)
+GL_ENTRY(void, glGetTexParameterfv, GLenum target, GLenum pname, GLfloat *params)
+GL_ENTRY(void, glGetTexParameteriv, GLenum target, GLenum pname, GLint *params)
+GL_ENTRY(void, glGetTexParameterxv, GLenum target, GLenum pname, GLfixed *params)
+GL_ENTRY(void, glGetTexParameterxvOES, GLenum target, GLenum pname, GLfixed *params)
+GL_ENTRY(int, glGetUniformLocation, GLuint program, const char* name)
+GL_ENTRY(void, glGetUniformfv, GLuint program, GLint location, GLfloat* params)
+GL_ENTRY(void, glGetUniformiv, GLuint program, GLint location, GLint* params)
+GL_ENTRY(void, glGetVertexAttribPointerv, GLuint index, GLenum pname, void** pointer)
+GL_ENTRY(void, glGetVertexAttribfv, GLuint index, GLenum pname, GLfloat* params)
+GL_ENTRY(void, glGetVertexAttribiv, GLuint index, GLenum pname, GLint* params)
+GL_ENTRY(void, glHint, GLenum target, GLenum mode)
+GL_ENTRY(GLboolean, glIsBuffer, GLuint buffer)
+GL_ENTRY(GLboolean, glIsEnabled, GLenum cap)
+GL_ENTRY(GLboolean, glIsFenceNV, GLuint fence)
+GL_ENTRY(GLboolean, glIsFramebuffer, GLuint framebuffer)
+GL_ENTRY(GLboolean, glIsFramebufferOES, GLuint framebuffer)
+GL_ENTRY(GLboolean, glIsProgram, GLuint program)
+GL_ENTRY(GLboolean, glIsRenderbuffer, GLuint renderbuffer)
+GL_ENTRY(GLboolean, glIsRenderbufferOES, GLuint renderbuffer)
+GL_ENTRY(GLboolean, glIsShader, GLuint shader)
+GL_ENTRY(GLboolean, glIsTexture, GLuint texture)
+GL_ENTRY(void, glLightModelf, GLenum pname, GLfloat param)
+GL_ENTRY(void, glLightModelfv, GLenum pname, const GLfloat *params)
+GL_ENTRY(void, glLightModelx, GLenum pname, GLfixed param)
+GL_ENTRY(void, glLightModelxOES, GLenum pname, GLfixed param)
+GL_ENTRY(void, glLightModelxv, GLenum pname, const GLfixed *params)
+GL_ENTRY(void, glLightModelxvOES, GLenum pname, const GLfixed *params)
+GL_ENTRY(void, glLightf, GLenum light, GLenum pname, GLfloat param)
+GL_ENTRY(void, glLightfv, GLenum light, GLenum pname, const GLfloat *params)
+GL_ENTRY(void, glLightx, GLenum light, GLenum pname, GLfixed param)
+GL_ENTRY(void, glLightxOES, GLenum light, GLenum pname, GLfixed param)
+GL_ENTRY(void, glLightxv, GLenum light, GLenum pname, const GLfixed *params)
+GL_ENTRY(void, glLightxvOES, GLenum light, GLenum pname, const GLfixed *params)
+GL_ENTRY(void, glLineWidth, GLfloat width)
+GL_ENTRY(void, glLineWidthx, GLfixed width)
+GL_ENTRY(void, glLineWidthxOES, GLfixed width)
+GL_ENTRY(void, glLinkProgram, GLuint program)
+GL_ENTRY(void, glLoadIdentity, void)
+GL_ENTRY(void, glLoadMatrixf, const GLfloat *m)
+GL_ENTRY(void, glLoadMatrixx, const GLfixed *m)
+GL_ENTRY(void, glLoadMatrixxOES, const GLfixed *m)
+GL_ENTRY(void, glLoadPaletteFromModelViewMatrixOES, void)
+GL_ENTRY(void, glLogicOp, GLenum opcode)
+GL_ENTRY(void*, glMapBufferOES, GLenum target, GLenum access)
+GL_ENTRY(void, glMaterialf, GLenum face, GLenum pname, GLfloat param)
+GL_ENTRY(void, glMaterialfv, GLenum face, GLenum pname, const GLfloat *params)
+GL_ENTRY(void, glMaterialx, GLenum face, GLenum pname, GLfixed param)
+GL_ENTRY(void, glMaterialxOES, GLenum face, GLenum pname, GLfixed param)
+GL_ENTRY(void, glMaterialxv, GLenum face, GLenum pname, const GLfixed *params)
+GL_ENTRY(void, glMaterialxvOES, GLenum face, GLenum pname, const GLfixed *params)
+GL_ENTRY(void, glMatrixIndexPointerOES, GLint size, GLenum type, GLsizei stride, const GLvoid *pointer)
+GL_ENTRY(void, glMatrixMode, GLenum mode)
+GL_ENTRY(void, glMultMatrixf, const GLfloat *m)
+GL_ENTRY(void, glMultMatrixx, const GLfixed *m)
+GL_ENTRY(void, glMultMatrixxOES, const GLfixed *m)
+GL_ENTRY(void, glMultiTexCoord4f, GLenum target, GLfloat s, GLfloat t, GLfloat r, GLfloat q)
+GL_ENTRY(void, glMultiTexCoord4x, GLenum target, GLfixed s, GLfixed t, GLfixed r, GLfixed q)
+GL_ENTRY(void, glMultiTexCoord4xOES, GLenum target, GLfixed s, GLfixed t, GLfixed r, GLfixed q)
+GL_ENTRY(void, glNormal3f, GLfloat nx, GLfloat ny, GLfloat nz)
+GL_ENTRY(void, glNormal3x, GLfixed nx, GLfixed ny, GLfixed nz)
+GL_ENTRY(void, glNormal3xOES, GLfixed nx, GLfixed ny, GLfixed nz)
+GL_ENTRY(void, glNormalPointer, GLenum type, GLsizei stride, const GLvoid *pointer)
+GL_ENTRY(void, glOrthof, GLfloat left, GLfloat right, GLfloat bottom, GLfloat top, GLfloat zNear, GLfloat zFar)
+GL_ENTRY(void, glOrthofOES, GLfloat left, GLfloat right, GLfloat bottom, GLfloat top, GLfloat zNear, GLfloat zFar)
+GL_ENTRY(void, glOrthox, GLfixed left, GLfixed right, GLfixed bottom, GLfixed top, GLfixed zNear, GLfixed zFar)
+GL_ENTRY(void, glOrthoxOES, GLfixed left, GLfixed right, GLfixed bottom, GLfixed top, GLfixed zNear, GLfixed zFar)
+GL_ENTRY(void, glPixelStorei, GLenum pname, GLint param)
+GL_ENTRY(void, glPointParameterf, GLenum pname, GLfloat param)
+GL_ENTRY(void, glPointParameterfv, GLenum pname, const GLfloat *params)
+GL_ENTRY(void, glPointParameterx, GLenum pname, GLfixed param)
+GL_ENTRY(void, glPointParameterxOES, GLenum pname, GLfixed param)
+GL_ENTRY(void, glPointParameterxv, GLenum pname, const GLfixed *params)
+GL_ENTRY(void, glPointParameterxvOES, GLenum pname, const GLfixed *params)
+GL_ENTRY(void, glPointSize, GLfloat size)
+GL_ENTRY(void, glPointSizePointerOES, GLenum type, GLsizei stride, const GLvoid *pointer)
+GL_ENTRY(void, glPointSizex, GLfixed size)
+GL_ENTRY(void, glPointSizexOES, GLfixed size)
+GL_ENTRY(void, glPolygonOffset, GLfloat factor, GLfloat units)
+GL_ENTRY(void, glPolygonOffsetx, GLfixed factor, GLfixed units)
+GL_ENTRY(void, glPolygonOffsetxOES, GLfixed factor, GLfixed units)
+GL_ENTRY(void, glPopMatrix, void)
+GL_ENTRY(void, glProgramBinaryOES, GLuint program, GLenum binaryFormat, const void *binary, GLint length)
+GL_ENTRY(void, glPushMatrix, void)
+GL_ENTRY(GLbitfield, glQueryMatrixxOES, GLfixed mantissa[16], GLint exponent[16])
+GL_ENTRY(void, glReadPixels, GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, GLvoid *pixels)
+GL_ENTRY(void, glReleaseShaderCompiler, void)
+GL_ENTRY(void, glRenderbufferStorage, GLenum target, GLenum internalformat, GLsizei width, GLsizei height)
+GL_ENTRY(void, glRenderbufferStorageOES, GLenum target, GLenum internalformat, GLsizei width, GLsizei height)
+GL_ENTRY(void, glRotatef, GLfloat angle, GLfloat x, GLfloat y, GLfloat z)
+GL_ENTRY(void, glRotatex, GLfixed angle, GLfixed x, GLfixed y, GLfixed z)
+GL_ENTRY(void, glRotatexOES, GLfixed angle, GLfixed x, GLfixed y, GLfixed z)
+GL_ENTRY(void, glSampleCoverage, GLclampf value, GLboolean invert)
+GL_ENTRY(void, glSampleCoveragex, GLclampx value, GLboolean invert)
+GL_ENTRY(void, glSampleCoveragexOES, GLclampx value, GLboolean invert)
+GL_ENTRY(void, glScalef, GLfloat x, GLfloat y, GLfloat z)
+GL_ENTRY(void, glScalex, GLfixed x, GLfixed y, GLfixed z)
+GL_ENTRY(void, glScalexOES, GLfixed x, GLfixed y, GLfixed z)
+GL_ENTRY(void, glScissor, GLint x, GLint y, GLsizei width, GLsizei height)
+GL_ENTRY(void, glSelectPerfMonitorCountersAMD, GLuint monitor, GLboolean enable, GLuint group, GLint numCounters, GLuint *countersList)
+GL_ENTRY(void, glSetFenceNV, GLuint fence, GLenum condition)
+GL_ENTRY(void, glShadeModel, GLenum mode)
+GL_ENTRY(void, glShaderBinary, GLsizei n, const GLuint* shaders, GLenum binaryformat, const void* binary, GLsizei length)
+GL_ENTRY(void, glShaderSource, GLuint shader, GLsizei count, const char** string, const GLint* length)
+GL_ENTRY(void, glStencilFunc, GLenum func, GLint ref, GLuint mask)
+GL_ENTRY(void, glStencilFuncSeparate, GLenum face, GLenum func, GLint ref, GLuint mask)
+GL_ENTRY(void, glStencilMask, GLuint mask)
+GL_ENTRY(void, glStencilMaskSeparate, GLenum face, GLuint mask)
+GL_ENTRY(void, glStencilOp, GLenum fail, GLenum zfail, GLenum zpass)
+GL_ENTRY(void, glStencilOpSeparate, GLenum face, GLenum fail, GLenum zfail, GLenum zpass)
+GL_ENTRY(GLboolean, glTestFenceNV, GLuint fence)
+GL_ENTRY(void, glTexCoordPointer, GLint size, GLenum type, GLsizei stride, const GLvoid *pointer)
+GL_ENTRY(void, glTexEnvf, GLenum target, GLenum pname, GLfloat param)
+GL_ENTRY(void, glTexEnvfv, GLenum target, GLenum pname, const GLfloat *params)
+GL_ENTRY(void, glTexEnvi, GLenum target, GLenum pname, GLint param)
+GL_ENTRY(void, glTexEnviv, GLenum target, GLenum pname, const GLint *params)
+GL_ENTRY(void, glTexEnvx, GLenum target, GLenum pname, GLfixed param)
+GL_ENTRY(void, glTexEnvxOES, GLenum target, GLenum pname, GLfixed param)
+GL_ENTRY(void, glTexEnvxv, GLenum target, GLenum pname, const GLfixed *params)
+GL_ENTRY(void, glTexEnvxvOES, GLenum target, GLenum pname, const GLfixed *params)
+GL_ENTRY(void, glTexGenfOES, GLenum coord, GLenum pname, GLfloat param)
+GL_ENTRY(void, glTexGenfvOES, GLenum coord, GLenum pname, const GLfloat *params)
+GL_ENTRY(void, glTexGeniOES, GLenum coord, GLenum pname, GLint param)
+GL_ENTRY(void, glTexGenivOES, GLenum coord, GLenum pname, const GLint *params)
+GL_ENTRY(void, glTexGenxOES, GLenum coord, GLenum pname, GLfixed param)
+GL_ENTRY(void, glTexGenxvOES, GLenum coord, GLenum pname, const GLfixed *params)
+GL_ENTRY(void, glTexImage2D, GLenum target, GLint level, GLint internalformat,  GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, const GLvoid* pixels)
+GL_ENTRY(void, glTexImage3DOES, GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLenum format, GLenum type, const void* pixels)
+GL_ENTRY(void, glTexParameterf, GLenum target, GLenum pname, GLfloat param)
+GL_ENTRY(void, glTexParameterfv, GLenum target, GLenum pname, const GLfloat *params)
+GL_ENTRY(void, glTexParameteri, GLenum target, GLenum pname, GLint param)
+GL_ENTRY(void, glTexParameteriv, GLenum target, GLenum pname, const GLint *params)
+GL_ENTRY(void, glTexParameterx, GLenum target, GLenum pname, GLfixed param)
+GL_ENTRY(void, glTexParameterxOES, GLenum target, GLenum pname, GLfixed param)
+GL_ENTRY(void, glTexParameterxv, GLenum target, GLenum pname, const GLfixed *params)
+GL_ENTRY(void, glTexParameterxvOES, GLenum target, GLenum pname, const GLfixed *params)
+GL_ENTRY(void, glTexSubImage2D, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const GLvoid *pixels)
+GL_ENTRY(void, glTexSubImage3DOES, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, const void* pixels)
+GL_ENTRY(void, glTranslatef, GLfloat x, GLfloat y, GLfloat z)
+GL_ENTRY(void, glTranslatex, GLfixed x, GLfixed y, GLfixed z)
+GL_ENTRY(void, glTranslatexOES, GLfixed x, GLfixed y, GLfixed z)
+GL_ENTRY(void, glUniform1f, GLint location, GLfloat x)
+GL_ENTRY(void, glUniform1fv, GLint location, GLsizei count, const GLfloat* v)
+GL_ENTRY(void, glUniform1i, GLint location, GLint x)
+GL_ENTRY(void, glUniform1iv, GLint location, GLsizei count, const GLint* v)
+GL_ENTRY(void, glUniform2f, GLint location, GLfloat x, GLfloat y)
+GL_ENTRY(void, glUniform2fv, GLint location, GLsizei count, const GLfloat* v)
+GL_ENTRY(void, glUniform2i, GLint location, GLint x, GLint y)
+GL_ENTRY(void, glUniform2iv, GLint location, GLsizei count, const GLint* v)
+GL_ENTRY(void, glUniform3f, GLint location, GLfloat x, GLfloat y, GLfloat z)
+GL_ENTRY(void, glUniform3fv, GLint location, GLsizei count, const GLfloat* v)
+GL_ENTRY(void, glUniform3i, GLint location, GLint x, GLint y, GLint z)
+GL_ENTRY(void, glUniform3iv, GLint location, GLsizei count, const GLint* v)
+GL_ENTRY(void, glUniform4f, GLint location, GLfloat x, GLfloat y, GLfloat z, GLfloat w)
+GL_ENTRY(void, glUniform4fv, GLint location, GLsizei count, const GLfloat* v)
+GL_ENTRY(void, glUniform4i, GLint location, GLint x, GLint y, GLint z, GLint w)
+GL_ENTRY(void, glUniform4iv, GLint location, GLsizei count, const GLint* v)
+GL_ENTRY(void, glUniformMatrix2fv, GLint location, GLsizei count, GLboolean transpose, const GLfloat* value)
+GL_ENTRY(void, glUniformMatrix3fv, GLint location, GLsizei count, GLboolean transpose, const GLfloat* value)
+GL_ENTRY(void, glUniformMatrix4fv, GLint location, GLsizei count, GLboolean transpose, const GLfloat* value)
+GL_ENTRY(GLboolean, glUnmapBufferOES, GLenum target)
+GL_ENTRY(void, glUseProgram, GLuint program)
+GL_ENTRY(void, glValidateProgram, GLuint program)
+GL_ENTRY(void, glVertexAttrib1f, GLuint indx, GLfloat x)
+GL_ENTRY(void, glVertexAttrib1fv, GLuint indx, const GLfloat* values)
+GL_ENTRY(void, glVertexAttrib2f, GLuint indx, GLfloat x, GLfloat y)
+GL_ENTRY(void, glVertexAttrib2fv, GLuint indx, const GLfloat* values)
+GL_ENTRY(void, glVertexAttrib3f, GLuint indx, GLfloat x, GLfloat y, GLfloat z)
+GL_ENTRY(void, glVertexAttrib3fv, GLuint indx, const GLfloat* values)
+GL_ENTRY(void, glVertexAttrib4f, GLuint indx, GLfloat x, GLfloat y, GLfloat z, GLfloat w)
+GL_ENTRY(void, glVertexAttrib4fv, GLuint indx, const GLfloat* values)
+GL_ENTRY(void, glVertexAttribPointer, GLuint indx, GLint size, GLenum type, GLboolean normalized, GLsizei stride, const void* ptr)
+GL_ENTRY(void, glVertexPointer, GLint size, GLenum type, GLsizei stride, const GLvoid *pointer)
+GL_ENTRY(void, glViewport, GLint x, GLint y, GLsizei width, GLsizei height)
+GL_ENTRY(void, glWeightPointerOES, GLint size, GLenum type, GLsizei stride, const GLvoid *pointer)
diff --git a/opengl/libs/hooks.h b/opengl/libs/hooks.h
index 8c0357e..f47f093 100644
--- a/opengl/libs/hooks.h
+++ b/opengl/libs/hooks.h
@@ -60,11 +60,14 @@
 enum {
     IMPL_HARDWARE = 0,
     IMPL_SOFTWARE,
-    IMPL_NUM_DRIVERS_IMPLEMENTATIONS,
-    IMPL_NO_CONTEXT = IMPL_NUM_DRIVERS_IMPLEMENTATIONS,
     IMPL_NUM_IMPLEMENTATIONS
 };
 
+enum {
+    GLESv1_INDEX = 0,
+    GLESv2_INDEX = 1,
+};
+
 // ----------------------------------------------------------------------------
 
 // GL / EGL hooks
@@ -74,18 +77,14 @@
 #define GL_ENTRY(_r, _api, ...) _r (*_api)(__VA_ARGS__);
 #define EGL_ENTRY(_r, _api, ...) _r (*_api)(__VA_ARGS__);
 
+struct egl_t {
+    #include "EGL/egl_entries.in"
+};
+
 struct gl_hooks_t {
     struct gl_t {
-        #include "GLES_CM/gl_entries.in"
-        #include "GLES_CM/glext_entries.in"
+        #include "entries.in"
     } gl;
-    struct gl2_t {
-        #include "GLES2/gl2_entries.in"
-        #include "GLES2/gl2ext_entries.in"
-    } gl2;
-    struct egl_t {
-        #include "EGL/egl_entries.in"
-    } egl;
     struct gl_ext_t {
         void (*extensions[MAX_NUMBER_OF_GL_EXTENSIONS])(void);
     } ext;
@@ -96,12 +95,12 @@
 
 // ----------------------------------------------------------------------------
 
-extern gl_hooks_t gHooks[IMPL_NUM_IMPLEMENTATIONS];
+extern gl_hooks_t gHooks[2][IMPL_NUM_IMPLEMENTATIONS];
+extern gl_hooks_t gHooksNoContext;
 extern pthread_key_t gGLWrapperKey;
 extern "C" void gl_unimplemented();
 
 extern char const * const gl_names[];
-extern char const * const gl2_names[];
 extern char const * const egl_names[];
 
 // ----------------------------------------------------------------------------
@@ -125,7 +124,7 @@
     gl_hooks_t const * volatile * tls_hooks = get_tls_hooks();
     gl_hooks_t const* hooks = tls_hooks[TLS_SLOT_OPENGL_API];
     if (hooks) return hooks;
-    return &gHooks[IMPL_NO_CONTEXT];
+    return &gHooksNoContext;
 }
 
 #else
@@ -137,7 +136,7 @@
 static gl_hooks_t const* getGlThreadSpecific() {
     gl_hooks_t const* hooks =  static_cast<gl_hooks_t*>(pthread_getspecific(gGLWrapperKey));
     if (hooks) return hooks;
-    return &gHooks[IMPL_NO_CONTEXT];
+    return &gHooksNoContext;
 }
 
 #endif
diff --git a/opengl/libs/tools/genfiles b/opengl/libs/tools/genfiles
index 4f8eda4..120cb4b 100755
--- a/opengl/libs/tools/genfiles
+++ b/opengl/libs/tools/genfiles
@@ -14,14 +14,20 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
-./glapigen ../../include/GLES/gl.h > ../GLES_CM/gl_api.in 
-./glentrygen ../../include/GLES/gl.h > ../GLES_CM/gl_entries.in 
+./glapigen ../../include/GLES/gl.h      > ../GLES_CM/gl_api.in
+./glapigen ../../include/GLES/glext.h   > ../GLES_CM/glext_api.in
+./glapigen ../../include/GLES2/gl2.h    > ../GLES2/gl2_api.in
+./glapigen ../../include/GLES2/gl2ext.h > ../GLES2/gl2ext_api.in
 
-./glapigen ../../include/GLES/glext.h > ../GLES_CM/glext_api.in 
-./glentrygen ../../include/GLES/glext.h > ../GLES_CM/glext_entries.in 
+./glentrygen ../../include/GLES/gl.h      > /tmp/gl_entries.in
+./glentrygen ../../include/GLES/glext.h   > /tmp/glext_entries.in
+./glentrygen ../../include/GLES2/gl2.h    > /tmp/gl2_entries.in
+./glentrygen ../../include/GLES2/gl2ext.h > /tmp/gl2ext_entries.in
 
-./glapigen ../../include/GLES2/gl2.h > ../GLES2/gl2_api.in 
-./glentrygen ../../include/GLES2/gl2.h > ../GLES2/gl2_entries.in 
-
-./glapigen ../../include/GLES2/gl2ext.h > ../GLES2/gl2ext_api.in 
-./glentrygen ../../include/GLES2/gl2ext.h > ../GLES2/gl2ext_entries.in 
+cat /tmp/gl_entries.in \
+    /tmp/glext_entries.in \
+    /tmp/gl2_entries.in \
+    /tmp/gl2ext_entries.in \
+        | sort -t, -k2 \
+        | awk -F, '!_[$2]++' \
+            > ../entries.in
diff --git a/opengl/tests/linetex/Android.mk b/opengl/tests/linetex/Android.mk
new file mode 100644
index 0000000..6ff248d
--- /dev/null
+++ b/opengl/tests/linetex/Android.mk
@@ -0,0 +1,17 @@
+LOCAL_PATH:= $(call my-dir)
+include $(CLEAR_VARS)
+
+LOCAL_SRC_FILES:= \
+	linetex.cpp
+
+LOCAL_SHARED_LIBRARIES := \
+	libcutils \
+    libEGL \
+    libGLESv1_CM \
+    libui
+
+LOCAL_MODULE:= test-opengl-linetex
+
+LOCAL_MODULE_TAGS := optional
+
+include $(BUILD_EXECUTABLE)
diff --git a/opengl/tests/linetex/linetex.cpp b/opengl/tests/linetex/linetex.cpp
new file mode 100644
index 0000000..6842940
--- /dev/null
+++ b/opengl/tests/linetex/linetex.cpp
@@ -0,0 +1,116 @@
+/*
+**
+** Copyright 2006, 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.
+*/
+
+#define LOG_TAG "fillrate"
+
+#include <unistd.h>
+#include <stdlib.h>
+#include <stdio.h>
+
+#include <EGL/egl.h>
+#include <GLES/gl.h>
+#include <GLES/glext.h>
+
+#include <utils/StopWatch.h>
+#include <ui/FramebufferNativeWindow.h>
+#include <ui/EGLUtils.h>
+
+using namespace android;
+
+int main(int argc, char** argv)
+{
+    EGLint configAttribs[] = {
+         EGL_DEPTH_SIZE, 0,
+         EGL_NONE
+     };
+     
+     EGLint majorVersion;
+     EGLint minorVersion;
+     EGLContext context;
+     EGLConfig config;
+     EGLSurface surface;
+     EGLint w, h;
+     EGLDisplay dpy;
+
+     EGLNativeWindowType window = android_createDisplaySurface();
+     
+     dpy = eglGetDisplay(EGL_DEFAULT_DISPLAY);
+     eglInitialize(dpy, &majorVersion, &minorVersion);
+          
+     status_t err = EGLUtils::selectConfigForNativeWindow(
+             dpy, configAttribs, window, &config);
+     if (err) {
+         fprintf(stderr, "couldn't find an EGLConfig matching the screen format\n");
+         return 0;
+     }
+
+     surface = eglCreateWindowSurface(dpy, config, window, NULL);
+     context = eglCreateContext(dpy, config, NULL, NULL);
+     eglMakeCurrent(dpy, surface, surface, context);   
+     eglQuerySurface(dpy, surface, EGL_WIDTH, &w);
+     eglQuerySurface(dpy, surface, EGL_HEIGHT, &h);
+     
+     printf("w=%d, h=%d\n", w, h);
+     
+     glBindTexture(GL_TEXTURE_2D, 0);
+     glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+     glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+     glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
+     glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
+     glTexEnvx(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
+     glDisable(GL_DITHER);
+     glDisable(GL_BLEND);
+     glEnable(GL_TEXTURE_2D);
+     glColor4f(1,1,1,1);
+
+
+     // default pack-alignment is 4
+     const uint16_t t16[64] = { 0xFFFF, 0, 0xF800, 0, 0x07E0, 0, 0x001F, 0 };
+
+     const GLfloat vertices[4][2] = {
+             { w/2,  0 },
+             { w/2,  h }
+     };
+
+     const GLfloat texCoords[4][2] = {
+             { 0,  0 },
+             { 1,  1 }
+     };
+
+     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, 1, 4, 0, GL_RGB, GL_UNSIGNED_SHORT_5_6_5, t16);
+
+     glViewport(0, 0, w, h);
+     glMatrixMode(GL_PROJECTION);
+     glLoadIdentity();
+     glOrthof(0, w, 0, h, 0, 1);
+
+     glEnableClientState(GL_VERTEX_ARRAY);
+     glEnableClientState(GL_TEXTURE_COORD_ARRAY);
+     glVertexPointer(2, GL_FLOAT, 0, vertices);
+     glTexCoordPointer(2, GL_FLOAT, 0, texCoords);
+
+     glClearColor(0,0,0,0);
+     glClear(GL_COLOR_BUFFER_BIT);
+     glDrawArrays(GL_LINES, 0, 2);
+     eglSwapBuffers(dpy, surface);
+
+     usleep(5*1000000);
+
+     eglTerminate(dpy);
+     
+     return 0;
+}
diff --git a/opengl/tools/glgen/specs/gles11/checks.spec b/opengl/tools/glgen/specs/gles11/checks.spec
index e31a2ce..1468ab9 100644
--- a/opengl/tools/glgen/specs/gles11/checks.spec
+++ b/opengl/tools/glgen/specs/gles11/checks.spec
@@ -1,61 +1,62 @@
-glClipPlanef check eqn 4

-glClipPlanex check eqn 4

-glGetClipPlanefOES check eqn 4

-glGetClipPlanexOES check eqn 4

-glDeleteBuffers check buffers n 

-glDeleteTextures check textures n

-glDrawElements check_AIOOBE indices count

-glFog ifcheck params 1 pname GL_FOG_MODE,GL_FOG_DENSITY,GL_FOG_START,GL_FOG_END ifcheck params 4 pname GL_FOG_COLOR

-glGenBuffers check buffers n

-glGenTextures check textures n

-glGetClipPlane check eqn 4

-glGetIntegerv ifcheck params 1 pname GL_ALPHA_BITS,GL_ALPHA_TEST_FUNC,GL_ALPHA_TEST_REF,GL_BLEND_DST,GL_BLUE_BITS,GL_COLOR_ARRAY_BUFFER_BINDING,GL_COLOR_ARRAY_SIZE,GL_COLOR_ARRAY_STRIDE,GL_COLOR_ARRAY_TYPE,GL_CULL_FACE,GL_DEPTH_BITS,GL_DEPTH_CLEAR_VALUE,GL_DEPTH_FUNC,GL_DEPTH_WRITEMASK,GL_FOG_DENSITY,GL_FOG_END,GL_FOG_MODE,GL_FOG_START,GL_FRONT_FACE,GL_GREEN_BITS,GL_IMPLEMENTATION_COLOR_READ_FORMAT_OES,GL_IMPLEMENTATION_COLOR_READ_TYPE_OES,GL_LIGHT_MODEL_COLOR_CONTROL,GL_LIGHT_MODEL_LOCAL_VIEWER,GL_LIGHT_MODEL_TWO_SIDE,GL_LINE_SMOOTH_HINT,GL_LINE_WIDTH,GL_LOGIC_OP_MODE,GL_MATRIX_INDEX_ARRAY_BUFFER_BINDING_OES,GL_MATRIX_INDEX_ARRAY_SIZE_OES,GL_MATRIX_INDEX_ARRAY_STRIDE_OES,GL_MATRIX_INDEX_ARRAY_TYPE_OES,GL_MATRIX_MODE,GL_MAX_CLIP_PLANES,GL_MAX_ELEMENTS_INDICES,GL_MAX_ELEMENTS_VERTICES,GL_MAX_LIGHTS,GL_MAX_MODELVIEW_STACK_DEPTH,GL_MAX_PALETTE_MATRICES_OES,GL_MAX_PROJECTION_STACK_DEPTH,GL_MAX_TEXTURE_SIZE,GL_MAX_TEXTURE_STACK_DEPTH,GL_MAX_TEXTURE_UNITS,GL_MAX_VERTEX_UNITS_OES,GL_MODELVIEW_STACK_DEPTH,GL_NORMAL_ARRAY_BUFFER_BINDING,GL_NORMAL_ARRAY_STRIDE,GL_NORMAL_ARRAY_TYPE,GL_NUM_COMPRESSED_TEXTURE_FORMATS,GL_PACK_ALIGNMENT,GL_PERSPECTIVE_CORRECTION_HINT,GL_POINT_SIZE,GL_POINT_SIZE_ARRAY_BUFFER_BINDING_OES,GL_POINT_SIZE_ARRAY_STRIDE_OES,GL_POINT_SIZE_ARRAY_TYPE_OES,GL_POINT_SMOOTH_HINT,GL_POLYGON_OFFSET_FACTOR,GL_POLYGON_OFFSET_UNITS,GL_PROJECTION_STACK_DEPTH,GL_RED_BITS,GL_SHADE_MODEL,GL_STENCIL_BITS,GL_STENCIL_CLEAR_VALUE,GL_STENCIL_FAIL,GL_STENCIL_FUNC,GL_STENCIL_PASS_DEPTH_FAIL,GL_STENCIL_PASS_DEPTH_PASS,GL_STENCIL_REF,GL_STENCIL_VALUE_MASK,GL_STENCIL_WRITEMASK,GL_SUBPIXEL_BITS,GL_TEXTURE_BINDING_2D,GL_TEXTURE_COORD_ARRAY_BUFFER_BINDING,GL_TEXTURE_COORD_ARRAY_SIZE,GL_TEXTURE_COORD_ARRAY_STRIDE,GL_TEXTURE_COORD_ARRAY_TYPE,GL_TEXTURE_STACK_DEPTH,GL_UNPACK_ALIGNMENT,GL_VERTEX_ARRAY_BUFFER_BINDING,GL_VERTEX_ARRAY_SIZE,GL_VERTEX_ARRAY_STRIDE,GL_VERTEX_ARRAY_TYPE,GL_WEIGHT_ARRAY_BUFFER_BINDING_OES,GL_WEIGHT_ARRAY_SIZE_OES,GL_WEIGHT_ARRAY_STRIDE_OES,GL_WEIGHT_ARRAY_TYPE_OES ifcheck params 2 pname GL_ALIASED_POINT_SIZE_RANGE,GL_ALIASED_LINE_WIDTH_RANGE,GL_DEPTH_RANGE,GL_MAX_VIEWPORT_DIMS,GL_SMOOTH_LINE_WIDTH_RANGE,GL_SMOOTH_POINT_SIZE_RANGE ifcheck params 4 pname GL_COLOR_CLEAR_VALUE,GL_COLOR_WRITEMASK,GL_FOG_COLOR,GL_LIGHT_MODEL_AMBIENT,GL_SCISSOR_BOX,GL_VIEWPORT ifcheck params 16 pname GL_MODELVIEW_MATRIX,GL_MODELVIEW_MATRIX_FLOAT_AS_INT_BITS_OES,GL_PROJECTION_MATRIX,GL_PROJECTION_MATRIX_FLOAT_AS_INT_BITS_OES,GL_TEXTURE_MATRIX,GL_TEXTURE_MATRIX_FLOAT_AS_INT_BITS_OES ifcheck params getNumCompressedTextureFormats() pname GL_COMPRESSED_TEXTURE_FORMATS

-glGetLight ifcheck params 1 pname GL_SPOT_EXPONENT,GL_SPOT_CUTOFF,GL_CONSTANT_ATTENUATION,GL_LINEAR_ATTENUATION,GL_QUADRATIC_ATTENUATION ifcheck params 3 pname GL_SPOT_DIRECTION ifcheck params 4 pname GL_AMBIENT,GL_DIFFUSE,GL_SPECULAR,GL_EMISSION

-glGetMaterial ifcheck params 1 pname GL_SHININESS ifcheck params 4 pname GL_AMBIENT,GL_DIFFUSE,GL_SPECULAR,GL_EMISSION,GL_AMBIENT_AND_DIFFUSE

-glGetTexEnv ifcheck params 1 pname GL_TEXTURE_ENV_MODE,GL_COMBINE_RGB,GL_COMBINE_ALPHA ifcheck params 4 pname GL_TEXTURE_ENV_COLOR

-glGetTexParameter check params 1

-glLightModel ifcheck params 1 pname GL_LIGHT_MODEL_TWO_SIDE ifcheck params 4 pname GL_LIGHT_MODEL_AMBIENT

-glLight ifcheck params 1 pname GL_SPOT_EXPONENT,GL_SPOT_CUTOFF,GL_CONSTANT_ATTENUATION,GL_LINEAR_ATTENUATION,GL_QUADRATIC_ATTENUATION ifcheck params 3 pname GL_SPOT_DIRECTION ifcheck params 4 pname GL_AMBIENT,GL_DIFFUSE,GL_SPECULAR,GL_EMISSION

-glLoadMatrix check m 16

-glMaterial ifcheck params 1 pname GL_SHININESS ifcheck params 4 pname GL_AMBIENT,GL_DIFFUSE,GL_SPECULAR,GL_EMISSION,GL_AMBIENT_AND_DIFFUSE

-glMultMatrix check m 16

-glPointParameter check params 1

-glTexEnv ifcheck params 1 pname GL_TEXTURE_ENV_MODE,GL_COMBINE_RGB,GL_COMBINE_ALPHA ifcheck params 4 pname GL_TEXTURE_ENV_COLOR

-glTexImage2D nullAllowed

-glTexSubImage2D nullAllowed

-glBufferData nullAllowed

-glTexParameter check params 1

-glQueryMatrixxOES check mantissa 16 check exponent 16 return -1

-glDrawTexfvOES check coords 5

-glDrawTexivOES check coords 5

-glDrawTexsvOES check coords 5

-glDrawTexxvOES check coords 5

-glBindFramebufferOES unsupported

-glBindRenderbufferOES unsupported

-glBlendEquation unsupported

-glBlendEquationSeparate unsupported

-glBlendFuncSeparate unsupported

-glCheckFramebufferStatusOES unsupported return 0

-glCurrentPaletteMatrixOES unsupported

-glDeleteFramebuffersOES unsupported

-glDeleteRenderbuffersOES unsupported

-glFramebufferRenderbufferOES unsupported

-glFramebufferStorageOES unsupported

-glFramebufferTexture2DOES unsupported

-glGenFramebuffersOES unsupported

-glGenRenderbuffersOES unsupported

-glGenerateMipmapOES unsupported

-glGetBufferParameter unsupported

-glGetFramebufferAttachmentParameterivOES unsupported

-glGetRenderbufferParameterivOES unsupported

-glGetTexGen unsupported

-glIsFramebufferOES unsupported return JNI_FALSE

-glIsRenderbufferOES unsupported return JNI_FALSE

-glLoadPaletteFromModelViewMatrixOES unsupported

-glMatrixIndexPointerOES unsupported

-glRenderbufferStorageOES unsupported return false

-glTexGen unsupported

-glTexGenf unsupported

-glTexGeni unsupported

-glTexGenx unsupported

-glWeightPointerOES unsupported

+glClipPlanef check eqn 4
+glClipPlanex check eqn 4
+glGetClipPlanefOES check eqn 4
+glGetClipPlanexOES check eqn 4
+glDeleteBuffers check buffers n
+glDeleteTextures check textures n
+glDrawElements check_AIOOBE indices count
+glFog ifcheck params 1 pname GL_FOG_MODE,GL_FOG_DENSITY,GL_FOG_START,GL_FOG_END ifcheck params 4 pname GL_FOG_COLOR
+glGenBuffers check buffers n
+glGenTextures check textures n
+glGetClipPlane check eqn 4
+glGetIntegerv ifcheck params 1 pname GL_ALPHA_BITS,GL_ALPHA_TEST_FUNC,GL_ALPHA_TEST_REF,GL_BLEND_DST,GL_BLUE_BITS,GL_COLOR_ARRAY_BUFFER_BINDING,GL_COLOR_ARRAY_SIZE,GL_COLOR_ARRAY_STRIDE,GL_COLOR_ARRAY_TYPE,GL_CULL_FACE,GL_DEPTH_BITS,GL_DEPTH_CLEAR_VALUE,GL_DEPTH_FUNC,GL_DEPTH_WRITEMASK,GL_FOG_DENSITY,GL_FOG_END,GL_FOG_MODE,GL_FOG_START,GL_FRONT_FACE,GL_GREEN_BITS,GL_IMPLEMENTATION_COLOR_READ_FORMAT_OES,GL_IMPLEMENTATION_COLOR_READ_TYPE_OES,GL_LIGHT_MODEL_COLOR_CONTROL,GL_LIGHT_MODEL_LOCAL_VIEWER,GL_LIGHT_MODEL_TWO_SIDE,GL_LINE_SMOOTH_HINT,GL_LINE_WIDTH,GL_LOGIC_OP_MODE,GL_MATRIX_INDEX_ARRAY_BUFFER_BINDING_OES,GL_MATRIX_INDEX_ARRAY_SIZE_OES,GL_MATRIX_INDEX_ARRAY_STRIDE_OES,GL_MATRIX_INDEX_ARRAY_TYPE_OES,GL_MATRIX_MODE,GL_MAX_CLIP_PLANES,GL_MAX_ELEMENTS_INDICES,GL_MAX_ELEMENTS_VERTICES,GL_MAX_LIGHTS,GL_MAX_MODELVIEW_STACK_DEPTH,GL_MAX_PALETTE_MATRICES_OES,GL_MAX_PROJECTION_STACK_DEPTH,GL_MAX_TEXTURE_SIZE,GL_MAX_TEXTURE_STACK_DEPTH,GL_MAX_TEXTURE_UNITS,GL_MAX_VERTEX_UNITS_OES,GL_MODELVIEW_STACK_DEPTH,GL_NORMAL_ARRAY_BUFFER_BINDING,GL_NORMAL_ARRAY_STRIDE,GL_NORMAL_ARRAY_TYPE,GL_NUM_COMPRESSED_TEXTURE_FORMATS,GL_PACK_ALIGNMENT,GL_PERSPECTIVE_CORRECTION_HINT,GL_POINT_SIZE,GL_POINT_SIZE_ARRAY_BUFFER_BINDING_OES,GL_POINT_SIZE_ARRAY_STRIDE_OES,GL_POINT_SIZE_ARRAY_TYPE_OES,GL_POINT_SMOOTH_HINT,GL_POLYGON_OFFSET_FACTOR,GL_POLYGON_OFFSET_UNITS,GL_PROJECTION_STACK_DEPTH,GL_RED_BITS,GL_SHADE_MODEL,GL_STENCIL_BITS,GL_STENCIL_CLEAR_VALUE,GL_STENCIL_FAIL,GL_STENCIL_FUNC,GL_STENCIL_PASS_DEPTH_FAIL,GL_STENCIL_PASS_DEPTH_PASS,GL_STENCIL_REF,GL_STENCIL_VALUE_MASK,GL_STENCIL_WRITEMASK,GL_SUBPIXEL_BITS,GL_TEXTURE_BINDING_2D,GL_TEXTURE_COORD_ARRAY_BUFFER_BINDING,GL_TEXTURE_COORD_ARRAY_SIZE,GL_TEXTURE_COORD_ARRAY_STRIDE,GL_TEXTURE_COORD_ARRAY_TYPE,GL_TEXTURE_STACK_DEPTH,GL_UNPACK_ALIGNMENT,GL_VERTEX_ARRAY_BUFFER_BINDING,GL_VERTEX_ARRAY_SIZE,GL_VERTEX_ARRAY_STRIDE,GL_VERTEX_ARRAY_TYPE,GL_WEIGHT_ARRAY_BUFFER_BINDING_OES,GL_WEIGHT_ARRAY_SIZE_OES,GL_WEIGHT_ARRAY_STRIDE_OES,GL_WEIGHT_ARRAY_TYPE_OES ifcheck params 2 pname GL_ALIASED_POINT_SIZE_RANGE,GL_ALIASED_LINE_WIDTH_RANGE,GL_DEPTH_RANGE,GL_MAX_VIEWPORT_DIMS,GL_SMOOTH_LINE_WIDTH_RANGE,GL_SMOOTH_POINT_SIZE_RANGE ifcheck params 4 pname GL_COLOR_CLEAR_VALUE,GL_COLOR_WRITEMASK,GL_FOG_COLOR,GL_LIGHT_MODEL_AMBIENT,GL_SCISSOR_BOX,GL_VIEWPORT ifcheck params 16 pname GL_MODELVIEW_MATRIX,GL_MODELVIEW_MATRIX_FLOAT_AS_INT_BITS_OES,GL_PROJECTION_MATRIX,GL_PROJECTION_MATRIX_FLOAT_AS_INT_BITS_OES,GL_TEXTURE_MATRIX,GL_TEXTURE_MATRIX_FLOAT_AS_INT_BITS_OES ifcheck params getNumCompressedTextureFormats() pname GL_COMPRESSED_TEXTURE_FORMATS
+glGetLight ifcheck params 1 pname GL_SPOT_EXPONENT,GL_SPOT_CUTOFF,GL_CONSTANT_ATTENUATION,GL_LINEAR_ATTENUATION,GL_QUADRATIC_ATTENUATION ifcheck params 3 pname GL_SPOT_DIRECTION ifcheck params 4 pname GL_AMBIENT,GL_DIFFUSE,GL_SPECULAR,GL_EMISSION
+glGetMaterial ifcheck params 1 pname GL_SHININESS ifcheck params 4 pname GL_AMBIENT,GL_DIFFUSE,GL_SPECULAR,GL_EMISSION,GL_AMBIENT_AND_DIFFUSE
+glGetTexEnv ifcheck params 1 pname GL_TEXTURE_ENV_MODE,GL_COMBINE_RGB,GL_COMBINE_ALPHA ifcheck params 4 pname GL_TEXTURE_ENV_COLOR
+glGetTexParameter check params 1
+glLightModel ifcheck params 1 pname GL_LIGHT_MODEL_TWO_SIDE ifcheck params 4 pname GL_LIGHT_MODEL_AMBIENT
+glLight ifcheck params 1 pname GL_SPOT_EXPONENT,GL_SPOT_CUTOFF,GL_CONSTANT_ATTENUATION,GL_LINEAR_ATTENUATION,GL_QUADRATIC_ATTENUATION ifcheck params 3 pname GL_SPOT_DIRECTION ifcheck params 4 pname GL_AMBIENT,GL_DIFFUSE,GL_SPECULAR,GL_EMISSION
+glLoadMatrix check m 16
+glMaterial ifcheck params 1 pname GL_SHININESS ifcheck params 4 pname GL_AMBIENT,GL_DIFFUSE,GL_SPECULAR,GL_EMISSION,GL_AMBIENT_AND_DIFFUSE
+glMultMatrix check m 16
+glPointParameter check params 1
+glTexEnv ifcheck params 1 pname GL_TEXTURE_ENV_MODE,GL_COMBINE_RGB,GL_COMBINE_ALPHA ifcheck params 4 pname GL_TEXTURE_ENV_COLOR
+glTexImage2D nullAllowed
+glTexSubImage2D nullAllowed
+glBufferData nullAllowed check data size
+glBufferSubData check data size
+glTexParameter check params 1
+glQueryMatrixxOES check mantissa 16 check exponent 16 return -1
+glDrawTexfvOES check coords 5
+glDrawTexivOES check coords 5
+glDrawTexsvOES check coords 5
+glDrawTexxvOES check coords 5
+glBindFramebufferOES unsupported
+glBindRenderbufferOES unsupported
+glBlendEquation unsupported
+glBlendEquationSeparate unsupported
+glBlendFuncSeparate unsupported
+glCheckFramebufferStatusOES unsupported return 0
+glCurrentPaletteMatrixOES unsupported
+glDeleteFramebuffersOES unsupported
+glDeleteRenderbuffersOES unsupported
+glFramebufferRenderbufferOES unsupported
+glFramebufferStorageOES unsupported
+glFramebufferTexture2DOES unsupported
+glGenFramebuffersOES unsupported
+glGenRenderbuffersOES unsupported
+glGenerateMipmapOES unsupported
+glGetBufferParameter unsupported
+glGetFramebufferAttachmentParameterivOES unsupported
+glGetRenderbufferParameterivOES unsupported
+glGetTexGen unsupported
+glIsFramebufferOES unsupported return JNI_FALSE
+glIsRenderbufferOES unsupported return JNI_FALSE
+glLoadPaletteFromModelViewMatrixOES unsupported
+glMatrixIndexPointerOES unsupported
+glRenderbufferStorageOES unsupported return false
+glTexGen unsupported
+glTexGenf unsupported
+glTexGeni unsupported
+glTexGenx unsupported
+glWeightPointerOES unsupported
diff --git a/opengl/tools/glgen/specs/jsr239/glspec-checks b/opengl/tools/glgen/specs/jsr239/glspec-checks
index 55840fa..063cdc7 100644
--- a/opengl/tools/glgen/specs/jsr239/glspec-checks
+++ b/opengl/tools/glgen/specs/jsr239/glspec-checks
@@ -1,59 +1,60 @@
-glClipPlanef check equation 4

-glClipPlanex check equation 4

-glDeleteBuffers check buffers n 

-glDeleteTextures check textures n

-glDrawElements check_AIOOBE indices count

-glFog ifcheck params 1 pname GL_FOG_MODE,GL_FOG_DENSITY,GL_FOG_START,GL_FOG_END ifcheck params 4 pname GL_FOG_COLOR

-glGenBuffers check buffers n

-glGenTextures check textures n

-glGetClipPlane check eqn 4

-glGetIntegerv ifcheck params 1 pname GL_ALPHA_BITS,GL_ALPHA_TEST_FUNC,GL_ALPHA_TEST_REF,GL_BLEND_DST,GL_BLUE_BITS,GL_COLOR_ARRAY_BUFFER_BINDING,GL_COLOR_ARRAY_SIZE,GL_COLOR_ARRAY_STRIDE,GL_COLOR_ARRAY_TYPE,GL_CULL_FACE,GL_DEPTH_BITS,GL_DEPTH_CLEAR_VALUE,GL_DEPTH_FUNC,GL_DEPTH_WRITEMASK,GL_FOG_DENSITY,GL_FOG_END,GL_FOG_MODE,GL_FOG_START,GL_FRONT_FACE,GL_GREEN_BITS,GL_IMPLEMENTATION_COLOR_READ_FORMAT_OES,GL_IMPLEMENTATION_COLOR_READ_TYPE_OES,GL_LIGHT_MODEL_COLOR_CONTROL,GL_LIGHT_MODEL_LOCAL_VIEWER,GL_LIGHT_MODEL_TWO_SIDE,GL_LINE_SMOOTH_HINT,GL_LINE_WIDTH,GL_LOGIC_OP_MODE,GL_MATRIX_INDEX_ARRAY_BUFFER_BINDING_OES,GL_MATRIX_INDEX_ARRAY_SIZE_OES,GL_MATRIX_INDEX_ARRAY_STRIDE_OES,GL_MATRIX_INDEX_ARRAY_TYPE_OES,GL_MATRIX_MODE,GL_MAX_CLIP_PLANES,GL_MAX_ELEMENTS_INDICES,GL_MAX_ELEMENTS_VERTICES,GL_MAX_LIGHTS,GL_MAX_MODELVIEW_STACK_DEPTH,GL_MAX_PALETTE_MATRICES_OES,GL_MAX_PROJECTION_STACK_DEPTH,GL_MAX_TEXTURE_SIZE,GL_MAX_TEXTURE_STACK_DEPTH,GL_MAX_TEXTURE_UNITS,GL_MAX_VERTEX_UNITS_OES,GL_MODELVIEW_STACK_DEPTH,GL_NORMAL_ARRAY_BUFFER_BINDING,GL_NORMAL_ARRAY_STRIDE,GL_NORMAL_ARRAY_TYPE,GL_NUM_COMPRESSED_TEXTURE_FORMATS,GL_PACK_ALIGNMENT,GL_PERSPECTIVE_CORRECTION_HINT,GL_POINT_SIZE,GL_POINT_SIZE_ARRAY_BUFFER_BINDING_OES,GL_POINT_SIZE_ARRAY_STRIDE_OES,GL_POINT_SIZE_ARRAY_TYPE_OES,GL_POINT_SMOOTH_HINT,GL_POLYGON_OFFSET_FACTOR,GL_POLYGON_OFFSET_UNITS,GL_PROJECTION_STACK_DEPTH,GL_RED_BITS,GL_SHADE_MODEL,GL_STENCIL_BITS,GL_STENCIL_CLEAR_VALUE,GL_STENCIL_FAIL,GL_STENCIL_FUNC,GL_STENCIL_PASS_DEPTH_FAIL,GL_STENCIL_PASS_DEPTH_PASS,GL_STENCIL_REF,GL_STENCIL_VALUE_MASK,GL_STENCIL_WRITEMASK,GL_SUBPIXEL_BITS,GL_TEXTURE_BINDING_2D,GL_TEXTURE_COORD_ARRAY_BUFFER_BINDING,GL_TEXTURE_COORD_ARRAY_SIZE,GL_TEXTURE_COORD_ARRAY_STRIDE,GL_TEXTURE_COORD_ARRAY_TYPE,GL_TEXTURE_STACK_DEPTH,GL_UNPACK_ALIGNMENT,GL_VERTEX_ARRAY_BUFFER_BINDING,GL_VERTEX_ARRAY_SIZE,GL_VERTEX_ARRAY_STRIDE,GL_VERTEX_ARRAY_TYPE,GL_WEIGHT_ARRAY_BUFFER_BINDING_OES,GL_WEIGHT_ARRAY_SIZE_OES,GL_WEIGHT_ARRAY_STRIDE_OES,GL_WEIGHT_ARRAY_TYPE_OES ifcheck params 2 pname GL_ALIASED_POINT_SIZE_RANGE,GL_ALIASED_LINE_WIDTH_RANGE,GL_DEPTH_RANGE,GL_MAX_VIEWPORT_DIMS,GL_SMOOTH_LINE_WIDTH_RANGE,GL_SMOOTH_POINT_SIZE_RANGE ifcheck params 4 pname GL_COLOR_CLEAR_VALUE,GL_COLOR_WRITEMASK,GL_FOG_COLOR,GL_LIGHT_MODEL_AMBIENT,GL_SCISSOR_BOX,GL_VIEWPORT ifcheck params 16 pname GL_MODELVIEW_MATRIX,GL_MODELVIEW_MATRIX_FLOAT_AS_INT_BITS_OES,GL_PROJECTION_MATRIX,GL_PROJECTION_MATRIX_FLOAT_AS_INT_BITS_OES,GL_TEXTURE_MATRIX,GL_TEXTURE_MATRIX_FLOAT_AS_INT_BITS_OES ifcheck params getNumCompressedTextureFormats() pname GL_COMPRESSED_TEXTURE_FORMATS

-glGetLight ifcheck params 1 pname GL_SPOT_EXPONENT,GL_SPOT_CUTOFF,GL_CONSTANT_ATTENUATION,GL_LINEAR_ATTENUATION,GL_QUADRATIC_ATTENUATION ifcheck params 3 pname GL_SPOT_DIRECTION ifcheck params 4 pname GL_AMBIENT,GL_DIFFUSE,GL_SPECULAR,GL_EMISSION

-glGetMaterial ifcheck params 1 pname GL_SHININESS ifcheck params 4 pname GL_AMBIENT,GL_DIFFUSE,GL_SPECULAR,GL_EMISSION,GL_AMBIENT_AND_DIFFUSE

-glGetTexEnv ifcheck params 1 pname GL_TEXTURE_ENV_MODE,GL_COMBINE_RGB,GL_COMBINE_ALPHA ifcheck params 4 pname GL_TEXTURE_ENV_COLOR

-glGetTexParameter check params 1

-glLightModel ifcheck params 1 pname GL_LIGHT_MODEL_TWO_SIDE ifcheck params 4 pname GL_LIGHT_MODEL_AMBIENT

-glLight ifcheck params 1 pname GL_SPOT_EXPONENT,GL_SPOT_CUTOFF,GL_CONSTANT_ATTENUATION,GL_LINEAR_ATTENUATION,GL_QUADRATIC_ATTENUATION ifcheck params 3 pname GL_SPOT_DIRECTION ifcheck params 4 pname GL_AMBIENT,GL_DIFFUSE,GL_SPECULAR,GL_EMISSION

-glLoadMatrix check m 16

-glMaterial ifcheck params 1 pname GL_SHININESS ifcheck params 4 pname GL_AMBIENT,GL_DIFFUSE,GL_SPECULAR,GL_EMISSION,GL_AMBIENT_AND_DIFFUSE

-glMultMatrix check m 16

-glPointParameter check params 1

-glTexEnv ifcheck params 1 pname GL_TEXTURE_ENV_MODE,GL_COMBINE_RGB,GL_COMBINE_ALPHA ifcheck params 4 pname GL_TEXTURE_ENV_COLOR

-glTexImage2D nullAllowed

-glTexSubImage2D nullAllowed

-glBufferData nullAllowed

-glTexParameter check params 1

-glQueryMatrixxOES check mantissa 16 check exponent 16 return -1

-glDrawTexfvOES check coords 5

-glDrawTexivOES check coords 5

-glDrawTexsvOES check coords 5

-glDrawTexxvOES check coords 5

-glBindFramebufferOES unsupported

-glBindRenderbufferOES unsupported

-glBlendEquation unsupported

-glBlendEquationSeparate unsupported

-glBlendFuncSeparate unsupported

-glCheckFramebufferStatusOES unsupported return 0

-glCurrentPaletteMatrixOES unsupported

-glDeleteFramebuffersOES unsupported

-glDeleteRenderbuffersOES unsupported

-glFramebufferRenderbufferOES unsupported

-glFramebufferStorageOES unsupported

-glFramebufferTexture2DOES unsupported

-glGenFramebuffersOES unsupported

-glGenRenderbuffersOES unsupported

-glGenerateMipmapOES unsupported

-glGetBufferParameter unsupported

-glGetFramebufferAttachmentParameterivOES unsupported

-glGetRenderbufferParameterivOES unsupported

-glGetTexGen unsupported

-glIsFramebufferOES unsupported return JNI_FALSE

-glIsRenderbufferOES unsupported return JNI_FALSE

-glLoadPaletteFromModelViewMatrixOES unsupported

-glMatrixIndexPointerOES unsupported

-glRenderbufferStorageOES unsupported return false

-glTexGen unsupported

-glTexGenf unsupported

-glTexGeni unsupported

-glTexGenx unsupported

-glWeightPointerOES unsupported

+glClipPlanef check equation 4
+glClipPlanex check equation 4
+glDeleteBuffers check buffers n
+glDeleteTextures check textures n
+glDrawElements check_AIOOBE indices count
+glFog ifcheck params 1 pname GL_FOG_MODE,GL_FOG_DENSITY,GL_FOG_START,GL_FOG_END ifcheck params 4 pname GL_FOG_COLOR
+glGenBuffers check buffers n
+glGenTextures check textures n
+glGetClipPlane check eqn 4
+glGetIntegerv ifcheck params 1 pname GL_ALPHA_BITS,GL_ALPHA_TEST_FUNC,GL_ALPHA_TEST_REF,GL_BLEND_DST,GL_BLUE_BITS,GL_COLOR_ARRAY_BUFFER_BINDING,GL_COLOR_ARRAY_SIZE,GL_COLOR_ARRAY_STRIDE,GL_COLOR_ARRAY_TYPE,GL_CULL_FACE,GL_DEPTH_BITS,GL_DEPTH_CLEAR_VALUE,GL_DEPTH_FUNC,GL_DEPTH_WRITEMASK,GL_FOG_DENSITY,GL_FOG_END,GL_FOG_MODE,GL_FOG_START,GL_FRONT_FACE,GL_GREEN_BITS,GL_IMPLEMENTATION_COLOR_READ_FORMAT_OES,GL_IMPLEMENTATION_COLOR_READ_TYPE_OES,GL_LIGHT_MODEL_COLOR_CONTROL,GL_LIGHT_MODEL_LOCAL_VIEWER,GL_LIGHT_MODEL_TWO_SIDE,GL_LINE_SMOOTH_HINT,GL_LINE_WIDTH,GL_LOGIC_OP_MODE,GL_MATRIX_INDEX_ARRAY_BUFFER_BINDING_OES,GL_MATRIX_INDEX_ARRAY_SIZE_OES,GL_MATRIX_INDEX_ARRAY_STRIDE_OES,GL_MATRIX_INDEX_ARRAY_TYPE_OES,GL_MATRIX_MODE,GL_MAX_CLIP_PLANES,GL_MAX_ELEMENTS_INDICES,GL_MAX_ELEMENTS_VERTICES,GL_MAX_LIGHTS,GL_MAX_MODELVIEW_STACK_DEPTH,GL_MAX_PALETTE_MATRICES_OES,GL_MAX_PROJECTION_STACK_DEPTH,GL_MAX_TEXTURE_SIZE,GL_MAX_TEXTURE_STACK_DEPTH,GL_MAX_TEXTURE_UNITS,GL_MAX_VERTEX_UNITS_OES,GL_MODELVIEW_STACK_DEPTH,GL_NORMAL_ARRAY_BUFFER_BINDING,GL_NORMAL_ARRAY_STRIDE,GL_NORMAL_ARRAY_TYPE,GL_NUM_COMPRESSED_TEXTURE_FORMATS,GL_PACK_ALIGNMENT,GL_PERSPECTIVE_CORRECTION_HINT,GL_POINT_SIZE,GL_POINT_SIZE_ARRAY_BUFFER_BINDING_OES,GL_POINT_SIZE_ARRAY_STRIDE_OES,GL_POINT_SIZE_ARRAY_TYPE_OES,GL_POINT_SMOOTH_HINT,GL_POLYGON_OFFSET_FACTOR,GL_POLYGON_OFFSET_UNITS,GL_PROJECTION_STACK_DEPTH,GL_RED_BITS,GL_SHADE_MODEL,GL_STENCIL_BITS,GL_STENCIL_CLEAR_VALUE,GL_STENCIL_FAIL,GL_STENCIL_FUNC,GL_STENCIL_PASS_DEPTH_FAIL,GL_STENCIL_PASS_DEPTH_PASS,GL_STENCIL_REF,GL_STENCIL_VALUE_MASK,GL_STENCIL_WRITEMASK,GL_SUBPIXEL_BITS,GL_TEXTURE_BINDING_2D,GL_TEXTURE_COORD_ARRAY_BUFFER_BINDING,GL_TEXTURE_COORD_ARRAY_SIZE,GL_TEXTURE_COORD_ARRAY_STRIDE,GL_TEXTURE_COORD_ARRAY_TYPE,GL_TEXTURE_STACK_DEPTH,GL_UNPACK_ALIGNMENT,GL_VERTEX_ARRAY_BUFFER_BINDING,GL_VERTEX_ARRAY_SIZE,GL_VERTEX_ARRAY_STRIDE,GL_VERTEX_ARRAY_TYPE,GL_WEIGHT_ARRAY_BUFFER_BINDING_OES,GL_WEIGHT_ARRAY_SIZE_OES,GL_WEIGHT_ARRAY_STRIDE_OES,GL_WEIGHT_ARRAY_TYPE_OES ifcheck params 2 pname GL_ALIASED_POINT_SIZE_RANGE,GL_ALIASED_LINE_WIDTH_RANGE,GL_DEPTH_RANGE,GL_MAX_VIEWPORT_DIMS,GL_SMOOTH_LINE_WIDTH_RANGE,GL_SMOOTH_POINT_SIZE_RANGE ifcheck params 4 pname GL_COLOR_CLEAR_VALUE,GL_COLOR_WRITEMASK,GL_FOG_COLOR,GL_LIGHT_MODEL_AMBIENT,GL_SCISSOR_BOX,GL_VIEWPORT ifcheck params 16 pname GL_MODELVIEW_MATRIX,GL_MODELVIEW_MATRIX_FLOAT_AS_INT_BITS_OES,GL_PROJECTION_MATRIX,GL_PROJECTION_MATRIX_FLOAT_AS_INT_BITS_OES,GL_TEXTURE_MATRIX,GL_TEXTURE_MATRIX_FLOAT_AS_INT_BITS_OES ifcheck params getNumCompressedTextureFormats() pname GL_COMPRESSED_TEXTURE_FORMATS
+glGetLight ifcheck params 1 pname GL_SPOT_EXPONENT,GL_SPOT_CUTOFF,GL_CONSTANT_ATTENUATION,GL_LINEAR_ATTENUATION,GL_QUADRATIC_ATTENUATION ifcheck params 3 pname GL_SPOT_DIRECTION ifcheck params 4 pname GL_AMBIENT,GL_DIFFUSE,GL_SPECULAR,GL_EMISSION
+glGetMaterial ifcheck params 1 pname GL_SHININESS ifcheck params 4 pname GL_AMBIENT,GL_DIFFUSE,GL_SPECULAR,GL_EMISSION,GL_AMBIENT_AND_DIFFUSE
+glGetTexEnv ifcheck params 1 pname GL_TEXTURE_ENV_MODE,GL_COMBINE_RGB,GL_COMBINE_ALPHA ifcheck params 4 pname GL_TEXTURE_ENV_COLOR
+glGetTexParameter check params 1
+glLightModel ifcheck params 1 pname GL_LIGHT_MODEL_TWO_SIDE ifcheck params 4 pname GL_LIGHT_MODEL_AMBIENT
+glLight ifcheck params 1 pname GL_SPOT_EXPONENT,GL_SPOT_CUTOFF,GL_CONSTANT_ATTENUATION,GL_LINEAR_ATTENUATION,GL_QUADRATIC_ATTENUATION ifcheck params 3 pname GL_SPOT_DIRECTION ifcheck params 4 pname GL_AMBIENT,GL_DIFFUSE,GL_SPECULAR,GL_EMISSION
+glLoadMatrix check m 16
+glMaterial ifcheck params 1 pname GL_SHININESS ifcheck params 4 pname GL_AMBIENT,GL_DIFFUSE,GL_SPECULAR,GL_EMISSION,GL_AMBIENT_AND_DIFFUSE
+glMultMatrix check m 16
+glPointParameter check params 1
+glTexEnv ifcheck params 1 pname GL_TEXTURE_ENV_MODE,GL_COMBINE_RGB,GL_COMBINE_ALPHA ifcheck params 4 pname GL_TEXTURE_ENV_COLOR
+glTexImage2D nullAllowed
+glTexSubImage2D nullAllowed
+glBufferData nullAllowed check data size
+glBufferSubData check data size
+glTexParameter check params 1
+glQueryMatrixxOES check mantissa 16 check exponent 16 return -1
+glDrawTexfvOES check coords 5
+glDrawTexivOES check coords 5
+glDrawTexsvOES check coords 5
+glDrawTexxvOES check coords 5
+glBindFramebufferOES unsupported
+glBindRenderbufferOES unsupported
+glBlendEquation unsupported
+glBlendEquationSeparate unsupported
+glBlendFuncSeparate unsupported
+glCheckFramebufferStatusOES unsupported return 0
+glCurrentPaletteMatrixOES unsupported
+glDeleteFramebuffersOES unsupported
+glDeleteRenderbuffersOES unsupported
+glFramebufferRenderbufferOES unsupported
+glFramebufferStorageOES unsupported
+glFramebufferTexture2DOES unsupported
+glGenFramebuffersOES unsupported
+glGenRenderbuffersOES unsupported
+glGenerateMipmapOES unsupported
+glGetBufferParameter unsupported
+glGetFramebufferAttachmentParameterivOES unsupported
+glGetRenderbufferParameterivOES unsupported
+glGetTexGen unsupported
+glIsFramebufferOES unsupported return JNI_FALSE
+glIsRenderbufferOES unsupported return JNI_FALSE
+glLoadPaletteFromModelViewMatrixOES unsupported
+glMatrixIndexPointerOES unsupported
+glRenderbufferStorageOES unsupported return false
+glTexGen unsupported
+glTexGenf unsupported
+glTexGeni unsupported
+glTexGenx unsupported
+glWeightPointerOES unsupported
diff --git a/opengl/tools/glgen/src/JniCodeEmitter.java b/opengl/tools/glgen/src/JniCodeEmitter.java
index 7340357..2cdb244 100644
--- a/opengl/tools/glgen/src/JniCodeEmitter.java
+++ b/opengl/tools/glgen/src/JniCodeEmitter.java
@@ -893,7 +893,7 @@
                                 ") getDirectBufferPointer(_env, " +
                                 cname + "_buf);");
                         String iii = "    ";
-                        out.println(iii + indent + "if ( ! " + cname + " ) {");	
+                        out.println(iii + indent + "if ( ! " + cname + " ) {");
                         out.println(iii + iii + indent + "return;");
                         out.println(iii + indent + "}");
                     } else {
@@ -907,13 +907,13 @@
                                     ");");
                     }
 
+                    emitNativeBoundsChecks(cfunc, cname, out, true,
+                                           emitExceptionCheck,
+                                           offset, remaining, nullAllowed ? "        " : "    ");
+
                     if (nullAllowed) {
                         out.println(indent + "}");
                     }
-
-                    emitNativeBoundsChecks(cfunc, cname, out, true,
-                                           emitExceptionCheck,
-                                           offset, remaining, "    ");
                 }
             }
         }