Merge "Fixing a bug when installing VoiceSearch cause error"
diff --git a/libs/surfaceflinger/LayerBuffer.cpp b/libs/surfaceflinger/LayerBuffer.cpp
index 2735aa2..bd3113b 100644
--- a/libs/surfaceflinger/LayerBuffer.cpp
+++ b/libs/surfaceflinger/LayerBuffer.cpp
@@ -328,7 +328,8 @@
 
 LayerBuffer::BufferSource::BufferSource(LayerBuffer& layer,
         const ISurface::BufferHeap& buffers)
-    : Source(layer), mStatus(NO_ERROR), mBufferSize(0)
+    : Source(layer), mStatus(NO_ERROR), mBufferSize(0),
+      mUseEGLImageDirectly(true)
 {
     if (buffers.heap == NULL) {
         // this is allowed, but in this case, it is illegal to receive
@@ -466,25 +467,38 @@
 
 #if defined(EGL_ANDROID_image_native_buffer)
     if (mLayer.mFlags & DisplayHardware::DIRECT_TEXTURE) {
-        copybit_device_t* copybit = mLayer.mBlitEngine;
-        if (copybit && ourBuffer->supportsCopybit()) {
-            // create our EGLImageKHR the first time
-            err = initTempBuffer();
-            if (err == NO_ERROR) {
+        err = INVALID_OPERATION;
+        if (ourBuffer->supportsCopybit()) {
+            // First, try to use the buffer as an EGLImage directly
+            if (mUseEGLImageDirectly) {
                 // 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);
+                sp<GraphicBuffer> buffer = new  GraphicBuffer(
+                        src.img.w, src.img.h, src.img.format,
+                        GraphicBuffer::USAGE_HW_TEXTURE,
+                        src.img.w, src.img.handle, false);
+                err = mLayer.initializeEglImage(buffer, &mTexture);
                 if (err != NO_ERROR) {
-                    clearTempBufferImage();
+                    mUseEGLImageDirectly = false;
                 }
             }
-        } else {
-            err = INVALID_OPERATION;
+            copybit_device_t* copybit = mLayer.mBlitEngine;
+            if (copybit && err != NO_ERROR) {
+                // create our EGLImageKHR the first time
+                err = initTempBuffer();
+                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);
+                    if (err != NO_ERROR) {
+                        clearTempBufferImage();
+                    }
+                }
+            }
         }
     }
 #endif
diff --git a/libs/surfaceflinger/LayerBuffer.h b/libs/surfaceflinger/LayerBuffer.h
index e03f92c..3257b76 100644
--- a/libs/surfaceflinger/LayerBuffer.h
+++ b/libs/surfaceflinger/LayerBuffer.h
@@ -145,6 +145,7 @@
         mutable LayerBase::Texture      mTexture;
         mutable NativeBuffer            mTempBuffer;
         mutable sp<GraphicBuffer>       mTempGraphicBuffer;
+        mutable bool                    mUseEGLImageDirectly;
     };
     
     class OverlaySource : public Source {
diff --git a/opengl/libagl/egl.cpp b/opengl/libagl/egl.cpp
index 81864bd..b6e0aae 100644
--- a/opengl/libagl/egl.cpp
+++ b/opengl/libagl/egl.cpp
@@ -2092,7 +2092,20 @@
 
     if (native_buffer->common.version != sizeof(android_native_buffer_t))
         return setError(EGL_BAD_PARAMETER, EGL_NO_IMAGE_KHR);
-    
+
+    switch (native_buffer->format) {
+        case HAL_PIXEL_FORMAT_RGBA_8888:
+        case HAL_PIXEL_FORMAT_RGBX_8888:
+        case HAL_PIXEL_FORMAT_RGB_888:
+        case HAL_PIXEL_FORMAT_RGB_565:
+        case HAL_PIXEL_FORMAT_BGRA_8888:
+        case HAL_PIXEL_FORMAT_RGBA_5551:
+        case HAL_PIXEL_FORMAT_RGBA_4444:
+            break;
+        default:
+            return setError(EGL_BAD_PARAMETER, EGL_NO_IMAGE_KHR);
+    }
+
     native_buffer->common.incRef(&native_buffer->common);
     return (EGLImageKHR)native_buffer;
 }
diff --git a/opengl/libagl/texture.cpp b/opengl/libagl/texture.cpp
index a1a776f..fa25fa9 100644
--- a/opengl/libagl/texture.cpp
+++ b/opengl/libagl/texture.cpp
@@ -1628,6 +1628,11 @@
         return;
     }
 
+    if (image == EGL_NO_IMAGE_KHR) {
+        ogles_error(c, GL_INVALID_VALUE);
+        return;
+    }
+
     android_native_buffer_t* native_buffer = (android_native_buffer_t*)image;
     if (native_buffer->common.magic != ANDROID_NATIVE_BUFFER_MAGIC) {
         ogles_error(c, GL_INVALID_VALUE);
@@ -1652,4 +1657,26 @@
 
 void glEGLImageTargetRenderbufferStorageOES(GLenum target, GLeglImageOES image)
 {
+    ogles_context_t* c = ogles_context_t::get();
+    if (target != GL_RENDERBUFFER_OES) {
+        ogles_error(c, GL_INVALID_ENUM);
+        return;
+    }
+
+    if (image == EGL_NO_IMAGE_KHR) {
+        ogles_error(c, GL_INVALID_VALUE);
+        return;
+    }
+
+    android_native_buffer_t* native_buffer = (android_native_buffer_t*)image;
+    if (native_buffer->common.magic != ANDROID_NATIVE_BUFFER_MAGIC) {
+        ogles_error(c, GL_INVALID_VALUE);
+        return;
+    }
+    if (native_buffer->common.version != sizeof(android_native_buffer_t)) {
+        ogles_error(c, GL_INVALID_VALUE);
+        return;
+    }
+
+    // well, we're not supporting this extension anyways
 }
diff --git a/opengl/libs/EGL/egl.cpp b/opengl/libs/EGL/egl.cpp
index d2f8ced..145e25e 100644
--- a/opengl/libs/EGL/egl.cpp
+++ b/opengl/libs/EGL/egl.cpp
@@ -166,7 +166,8 @@
     uint32_t    magic;
     DisplayImpl disp[IMPL_NUM_IMPLEMENTATIONS];
     EGLint      numTotalConfigs;
-    volatile int32_t refs;
+    uint32_t    refs;
+    Mutex       lock;
     
     egl_display_t() : magic('_dpy'), numTotalConfigs(0) { }
     ~egl_display_t() { magic = 0; }
@@ -644,7 +645,9 @@
     egl_display_t * const dp = get_display(dpy);
     if (!dp) return setError(EGL_BAD_DISPLAY, EGL_FALSE);
 
-    if (android_atomic_inc(&dp->refs) > 0) {
+    Mutex::Autolock _l(dp->lock);
+
+    if (dp->refs > 0) {
         if (major != NULL) *major = VERSION_MAJOR;
         if (minor != NULL) *minor = VERSION_MINOR;
         return EGL_TRUE;
@@ -728,6 +731,7 @@
     }
 
     if (res == EGL_TRUE) {
+        dp->refs++;
         if (major != NULL) *major = VERSION_MAJOR;
         if (minor != NULL) *minor = VERSION_MINOR;
         return EGL_TRUE;
@@ -743,7 +747,15 @@
 
     egl_display_t* const dp = get_display(dpy);
     if (!dp) return setError(EGL_BAD_DISPLAY, EGL_FALSE);
-    if (android_atomic_dec(&dp->refs) != 1)
+
+    Mutex::Autolock _l(dp->lock);
+
+    if (dp->refs == 0) {
+        return setError(EGL_NOT_INITIALIZED, EGL_FALSE);
+    }
+
+    // this is specific to Android, display termination is ref-counted.
+    if (dp->refs > 1)
         return EGL_TRUE;
 
     EGLBoolean res = EGL_FALSE;
@@ -767,6 +779,7 @@
     
     // TODO: all egl_object_t should be marked for termination
     
+    dp->refs--;
     dp->numTotalConfigs = 0;
     clearTLS();
     return res;