Adds private EGL extension to create an EGLClientBuffer from a gralloc'd buffer.  This lets you create a color EGLimage backed by gralloc, which is needed to support protected textures.

Bug: 22775237
Bug: 22855417

Change-Id: I8e03061d74a74a8fdd6524ffa97a6c75a6ced89c
diff --git a/opengl/include/EGL/eglext.h b/opengl/include/EGL/eglext.h
index b2abdb1..267f8af 100644
--- a/opengl/include/EGL/eglext.h
+++ b/opengl/include/EGL/eglext.h
@@ -598,6 +598,19 @@
 #endif
 #endif
 
+#ifndef EGL_ANDROID_create_native_client_buffer
+#define EGL_ANDROID_create_native_client_buffer 1
+#define EGL_NATIVE_BUFFER_USAGE_ANDROID   0x3143
+#define EGL_NATIVE_BUFFER_USAGE_PROTECTED_BIT_ANDROID   0x00000001
+#define EGL_NATIVE_BUFFER_USAGE_RENDERBUFFER_ANDROID   0x00000002
+#define EGL_NATIVE_BUFFER_USAGE_TEXTURE_ANDROID   0x00000004
+#ifdef EGL_EGLEXT_PROTOTYPES
+EGLAPI EGLClientBuffer eglCreateNativeClientBufferANDROID (const EGLint *attrib_list);
+#else
+typedef EGLAPI EGLClientBuffer (EGLAPIENTRYP PFNEGLCREATENATIVECLIENTBUFFERANDROID) (const EGLint *attrib_list);
+#endif
+#endif
+
 #ifdef __cplusplus
 }
 #endif
diff --git a/opengl/libs/Android.mk b/opengl/libs/Android.mk
index 3f9e332..eb86860 100644
--- a/opengl/libs/Android.mk
+++ b/opengl/libs/Android.mk
@@ -31,7 +31,7 @@
 	EGL/Loader.cpp 	       \
 #
 
-LOCAL_SHARED_LIBRARIES += libcutils libutils liblog
+LOCAL_SHARED_LIBRARIES += libcutils libutils liblog libui
 LOCAL_MODULE:= libEGL
 LOCAL_LDFLAGS += -Wl,--exclude-libs=ALL
 LOCAL_SHARED_LIBRARIES += libdl
diff --git a/opengl/libs/EGL/eglApi.cpp b/opengl/libs/EGL/eglApi.cpp
index 5bd7464..c7e2afb 100644
--- a/opengl/libs/EGL/eglApi.cpp
+++ b/opengl/libs/EGL/eglApi.cpp
@@ -33,6 +33,8 @@
 #include <cutils/properties.h>
 #include <cutils/memory.h>
 
+#include <ui/GraphicBuffer.h>
+
 #include <utils/KeyedVector.h>
 #include <utils/SortedVector.h>
 #include <utils/String8.h>
@@ -80,6 +82,7 @@
         "EGL_KHR_get_all_proc_addresses "
         "EGL_ANDROID_presentation_time "
         "EGL_KHR_swap_buffers_with_damage "
+        "EGL_ANDROID_create_native_client_buffer "
         ;
 extern char const * const gExtensionString  =
         "EGL_KHR_image "                        // mandatory
@@ -168,6 +171,10 @@
     { "eglSwapBuffersWithDamageKHR",
             (__eglMustCastToProperFunctionPointerType)&eglSwapBuffersWithDamageKHR },
 
+    // EGL_ANDROID_native_client_buffer
+    { "eglCreateNativeClientBufferANDROID",
+            (__eglMustCastToProperFunctionPointerType)&eglCreateNativeClientBufferANDROID },
+
     // EGL_KHR_partial_update
     { "eglSetDamageRegionKHR",
             (__eglMustCastToProperFunctionPointerType)&eglSetDamageRegionKHR },
@@ -1770,6 +1777,97 @@
     return EGL_TRUE;
 }
 
+EGLClientBuffer eglCreateNativeClientBufferANDROID(const EGLint *attrib_list)
+{
+    clearError();
+
+    int usage = 0;
+    uint32_t width = 0;
+    uint32_t height = 0;
+    uint32_t format = 0;
+    uint32_t red_size = 0;
+    uint32_t green_size = 0;
+    uint32_t blue_size = 0;
+    uint32_t alpha_size = 0;
+
+#define GET_POSITIVE_VALUE(case_name, target) \
+    case case_name: \
+        if (value > 0) { \
+            target = value; \
+        } else { \
+            return setError(EGL_BAD_PARAMETER, (EGLClientBuffer)0); \
+        } \
+        break
+
+    if (attrib_list) {
+        while (*attrib_list != EGL_NONE) {
+            GLint attr = *attrib_list++;
+            GLint value = *attrib_list++;
+            switch (attr) {
+                GET_POSITIVE_VALUE(EGL_WIDTH, width);
+                GET_POSITIVE_VALUE(EGL_HEIGHT, height);
+                GET_POSITIVE_VALUE(EGL_RED_SIZE, red_size);
+                GET_POSITIVE_VALUE(EGL_GREEN_SIZE, green_size);
+                GET_POSITIVE_VALUE(EGL_BLUE_SIZE, blue_size);
+                GET_POSITIVE_VALUE(EGL_ALPHA_SIZE, alpha_size);
+                case EGL_NATIVE_BUFFER_USAGE_ANDROID:
+                    if (value & EGL_NATIVE_BUFFER_USAGE_PROTECTED_BIT_ANDROID) {
+                        usage |= GRALLOC_USAGE_PROTECTED;
+                        // If we are using QCOM then add in extra bits.  This
+                        // should be removed before launch. These correspond to:
+                        // USAGE_PRIVATE_MM_HEAP | USAGE_PRIVATE_UNCACHED
+                        usage |= 0x82000000;
+                    }
+                    if (value & EGL_NATIVE_BUFFER_USAGE_RENDERBUFFER_ANDROID) {
+                        usage |= GRALLOC_USAGE_HW_RENDER;
+                    }
+                    if (value & EGL_NATIVE_BUFFER_USAGE_TEXTURE_ANDROID) {
+                        usage |= GRALLOC_USAGE_HW_TEXTURE;
+                    }
+                    // The buffer must be used for either a texture or a
+                    // renderbuffer.
+                    if ((value & EGL_NATIVE_BUFFER_USAGE_RENDERBUFFER_ANDROID) &&
+                        (value & EGL_NATIVE_BUFFER_USAGE_TEXTURE_ANDROID)) {
+                        return setError(EGL_BAD_PARAMETER, (EGLClientBuffer)0);
+                    }
+                    break;
+                default:
+                    return setError(EGL_BAD_PARAMETER, (EGLClientBuffer)0);
+            }
+        }
+    }
+#undef GET_POSITIVE_VALUE
+
+    // Validate format.
+    if (red_size == 8 && green_size == 8 && blue_size == 8) {
+        if (alpha_size == 8) {
+            format = HAL_PIXEL_FORMAT_RGBA_8888;
+        } else {
+            format = HAL_PIXEL_FORMAT_RGB_888;
+        }
+    } else if (red_size == 5 && green_size == 6 && blue_size == 5 &&
+               alpha_size == 0) {
+        format == HAL_PIXEL_FORMAT_RGB_565;
+    } else {
+        ALOGE("Invalid native pixel format { r=%d, g=%d, b=%d, a=%d }",
+                red_size, green_size, blue_size, alpha_size);
+        return setError(EGL_BAD_PARAMETER, (EGLClientBuffer)0);
+    }
+
+    GraphicBuffer* gBuffer = new GraphicBuffer(width, height, format, usage);
+    const status_t err = gBuffer->initCheck();
+    if (err != NO_ERROR) {
+        ALOGE("Unable to create native buffer { w=%d, h=%d, f=%d, u=%#x }: %#x",
+                width, height, format, usage, err);
+        // Destroy the buffer.
+        sp<GraphicBuffer> holder(gBuffer);
+        return setError(EGL_BAD_ALLOC, (EGLClientBuffer)0);
+    }
+    ALOGD("Created new native buffer %p { w=%d, h=%d, f=%d, u=%#x }",
+            gBuffer, width, height, format, usage);
+    return static_cast<EGLClientBuffer>(gBuffer->getNativeBuffer());
+}
+
 // ----------------------------------------------------------------------------
 // NVIDIA extensions
 // ----------------------------------------------------------------------------
diff --git a/opengl/libs/EGL/egl_entries.in b/opengl/libs/EGL/egl_entries.in
index 498b2fc..2b56718 100644
--- a/opengl/libs/EGL/egl_entries.in
+++ b/opengl/libs/EGL/egl_entries.in
@@ -80,6 +80,7 @@
 EGL_ENTRY(EGLBoolean, eglSetSwapRectangleANDROID, EGLDisplay, EGLSurface, EGLint, EGLint, EGLint, EGLint)
 EGL_ENTRY(EGLClientBuffer, eglGetRenderBufferANDROID, EGLDisplay, EGLSurface)
 EGL_ENTRY(EGLint, eglDupNativeFenceFDANDROID, EGLDisplay, EGLSyncKHR)
+EGL_ENTRY(EGLClientBuffer, eglCreateNativeClientBufferANDROID, const EGLint *)
 
 /* NVIDIA extensions */