Added support for the GL_TEXTURE_EXTERNAL target

This will allow us to support YUV surfaces.

Change-Id: I2d4da75f1006a5285bdc552695d4caeecccf2183
diff --git a/libs/surfaceflinger/Layer.cpp b/libs/surfaceflinger/Layer.cpp
index e7247bd..bfd6dcc 100644
--- a/libs/surfaceflinger/Layer.cpp
+++ b/libs/surfaceflinger/Layer.cpp
@@ -232,7 +232,7 @@
         // if not everything below us is covered, we plug the holes!
         Region holes(clip.subtract(under));
         if (!holes.isEmpty()) {
-            clearWithOpenGL(holes);
+            clearWithOpenGL(holes, 0, 0, 0, 1);
         }
         return;
     }
diff --git a/libs/surfaceflinger/LayerBase.cpp b/libs/surfaceflinger/LayerBase.cpp
index 1f66fd0..d5aa53f 100644
--- a/libs/surfaceflinger/LayerBase.cpp
+++ b/libs/surfaceflinger/LayerBase.cpp
@@ -324,16 +324,6 @@
     glEnable(GL_SCISSOR_TEST);
 
     onDraw(clip);
-
-    /*
-    glDisable(GL_TEXTURE_2D);
-    glDisable(GL_DITHER);
-    glEnable(GL_BLEND);
-    glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
-    glColor4x(0, 0x8000, 0, 0x10000);
-    drawRegion(transparentRegionScreen);
-    glDisable(GL_BLEND);
-    */
 }
 
 void LayerBase::clearWithOpenGL(const Region& clip, GLclampf red,
@@ -343,7 +333,9 @@
     const DisplayHardware& hw(graphicPlane(0).displayHardware());
     const uint32_t fbHeight = hw.getHeight();
     glColor4f(red,green,blue,alpha);
-    glDisable(GL_TEXTURE_2D);
+
+    TextureManager::deactivateTextures();
+
     glDisable(GL_BLEND);
     glDisable(GL_DITHER);
 
@@ -371,11 +363,9 @@
     const State& s(drawingState());
     
     // bind our texture
-    validateTexture(texture.name);
+    TextureManager::activateTexture(texture, needsFiltering());
     uint32_t width  = texture.width; 
     uint32_t height = texture.height;
-    
-    glEnable(GL_TEXTURE_2D);
 
     GLenum src = mPremultipliedAlpha ? GL_ONE : GL_SRC_ALPHA;
     if (UNLIKELY(s.alpha < 0xFF)) {
@@ -431,6 +421,12 @@
         glScalef(texture.wScale, texture.hScale, 1.0f);
     }
 
+    if (needsDithering()) {
+        glEnable(GL_DITHER);
+    } else {
+        glDisable(GL_DITHER);
+    }
+
     glEnableClientState(GL_TEXTURE_COORD_ARRAY);
     glVertexPointer(2, GL_FLOAT, 0, mVertices);
     glTexCoordPointer(2, GL_FLOAT, 0, texCoords);
@@ -444,26 +440,6 @@
     glDisableClientState(GL_TEXTURE_COORD_ARRAY);
 }
 
-void LayerBase::validateTexture(GLint textureName) const
-{
-    glBindTexture(GL_TEXTURE_2D, textureName);
-    // TODO: reload the texture if needed
-    // this is currently done in loadTexture() below
-    if (needsFiltering()) {
-        glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
-        glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
-    } else {
-        glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
-        glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
-    }
-
-    if (needsDithering()) {
-        glEnable(GL_DITHER);
-    } else {
-        glDisable(GL_DITHER);
-    }
-}
-
 void LayerBase::dump(String8& result, char* buffer, size_t SIZE) const
 {
     const Layer::State& s(drawingState());
diff --git a/libs/surfaceflinger/LayerBase.h b/libs/surfaceflinger/LayerBase.h
index 1a07f32..4288cf7 100644
--- a/libs/surfaceflinger/LayerBase.h
+++ b/libs/surfaceflinger/LayerBase.h
@@ -260,7 +260,6 @@
 
 private:
     LayerBase(const LayerBase& rhs);
-    void validateTexture(GLint textureName) const;
 };
 
 
diff --git a/libs/surfaceflinger/LayerBlur.cpp b/libs/surfaceflinger/LayerBlur.cpp
index 4c8bae8..c1c440b 100644
--- a/libs/surfaceflinger/LayerBlur.cpp
+++ b/libs/surfaceflinger/LayerBlur.cpp
@@ -146,6 +146,9 @@
     Region::const_iterator it = clip.begin();
     Region::const_iterator const end = clip.end();
     if (it != end) {
+#if defined(GL_OES_texture_external)
+        glDisable(GL_TEXTURE_EXTERNAL_OES);
+#endif
         glEnable(GL_TEXTURE_2D);
         glBindTexture(GL_TEXTURE_2D, mTextureName);
 
diff --git a/libs/surfaceflinger/LayerDim.cpp b/libs/surfaceflinger/LayerDim.cpp
index d528d2f..906a583 100644
--- a/libs/surfaceflinger/LayerDim.cpp
+++ b/libs/surfaceflinger/LayerDim.cpp
@@ -119,6 +119,9 @@
         glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
         glColor4x(0, 0, 0, alpha);
         
+#if defined(GL_OES_texture_external)
+        glDisable(GL_TEXTURE_EXTERNAL_OES);
+#endif
 #if defined(DIM_WITH_TEXTURE) && defined(EGL_ANDROID_image_native_buffer)
         if (sUseTexture) {
             glBindTexture(GL_TEXTURE_2D, sTexId);
diff --git a/libs/surfaceflinger/SurfaceFlinger.cpp b/libs/surfaceflinger/SurfaceFlinger.cpp
index 4dea62f..96a5411 100644
--- a/libs/surfaceflinger/SurfaceFlinger.cpp
+++ b/libs/surfaceflinger/SurfaceFlinger.cpp
@@ -332,13 +332,6 @@
     dcblk->density      = hw.getDensity();
 
     // Initialize OpenGL|ES
-    glActiveTexture(GL_TEXTURE0);
-    glBindTexture(GL_TEXTURE_2D, 0);
-    glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
-    glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
-    glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
-    glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
-    glTexEnvx(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
     glPixelStorei(GL_UNPACK_ALIGNMENT, 4);
     glPixelStorei(GL_PACK_ALIGNMENT, 4); 
     glEnableClientState(GL_VERTEX_ARRAY);
@@ -918,17 +911,18 @@
 
 void SurfaceFlinger::debugFlashRegions()
 {
-     const DisplayHardware& hw(graphicPlane(0).displayHardware());
-     const uint32_t flags = hw.getFlags();
+    const DisplayHardware& hw(graphicPlane(0).displayHardware());
+    const uint32_t flags = hw.getFlags();
 
-     if (!((flags & DisplayHardware::SWAP_RECTANGLE) ||
-             (flags & DisplayHardware::BUFFER_PRESERVED))) {
-         const Region repaint((flags & DisplayHardware::PARTIAL_UPDATES) ?
-                 mDirtyRegion.bounds() : hw.bounds());
-         composeSurfaces(repaint);
-     }
-    
-    glDisable(GL_TEXTURE_2D);
+    if (!((flags & DisplayHardware::SWAP_RECTANGLE) ||
+            (flags & DisplayHardware::BUFFER_PRESERVED))) {
+        const Region repaint((flags & DisplayHardware::PARTIAL_UPDATES) ?
+                mDirtyRegion.bounds() : hw.bounds());
+        composeSurfaces(repaint);
+    }
+
+    TextureManager::deactivateTextures();
+
     glDisable(GL_BLEND);
     glDisable(GL_DITHER);
     glDisable(GL_SCISSOR_TEST);
@@ -936,9 +930,9 @@
     static int toggle = 0;
     toggle = 1 - toggle;
     if (toggle) {
-        glColor4x(0x10000, 0, 0x10000, 0x10000);
+        glColor4f(1, 0, 1, 1);
     } else {
-        glColor4x(0x10000, 0x10000, 0, 0x10000);
+        glColor4f(1, 1, 0, 1);
     }
 
     Region::const_iterator it = mDirtyRegion.begin();
@@ -954,7 +948,7 @@
         glVertexPointer(2, GL_FLOAT, 0, vertices);
         glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
     }
-    
+
     if (mInvalidRegion.isEmpty()) {
         mDirtyRegion.dump("mDirtyRegion");
         mInvalidRegion.dump("mInvalidRegion");
@@ -962,7 +956,7 @@
     hw.flip(mInvalidRegion);
 
     if (mDebugRegion > 1)
-       usleep(mDebugRegion * 1000);
+        usleep(mDebugRegion * 1000);
 
     glEnable(GL_SCISSOR_TEST);
     //mDirtyRegion.dump("mDirtyRegion");
@@ -982,7 +976,7 @@
     glDisable(GL_DITHER);
 
     if (LIKELY(!mDebugBackground)) {
-        glClearColorx(0,0,0,0);
+        glClearColor(0,0,0,0);
         Region::const_iterator it = region.begin();
         Region::const_iterator const end = region.end();
         while (it != end) {
@@ -998,6 +992,9 @@
         glVertexPointer(2, GL_SHORT, 0, vertices);
         glTexCoordPointer(2, GL_SHORT, 0, tcoords);
         glEnableClientState(GL_TEXTURE_COORD_ARRAY);
+#if defined(GL_OES_texture_external)
+        glDisable(GL_TEXTURE_EXTERNAL_OES);
+#endif
         glEnable(GL_TEXTURE_2D);
         glBindTexture(GL_TEXTURE_2D, mWormholeTexName);
         glTexEnvx(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
diff --git a/libs/surfaceflinger/TextureManager.cpp b/libs/surfaceflinger/TextureManager.cpp
index ee2159b..996a683 100644
--- a/libs/surfaceflinger/TextureManager.cpp
+++ b/libs/surfaceflinger/TextureManager.cpp
@@ -41,43 +41,112 @@
 {
 }
 
-GLuint TextureManager::createTexture()
+GLenum TextureManager::getTextureTarget(const Image* image) {
+#if defined(GL_OES_texture_external)
+    switch (image->target) {
+        case Texture::TEXTURE_EXTERNAL:
+            return GL_TEXTURE_EXTERNAL_OES;
+    }
+#endif
+    return GL_TEXTURE_2D;
+}
+
+status_t TextureManager::initTexture(Texture* texture)
 {
+    if (texture->name != -1UL)
+        return INVALID_OPERATION;
+
     GLuint textureName = -1;
     glGenTextures(1, &textureName);
-    glBindTexture(GL_TEXTURE_2D, textureName);
-    glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
-    glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
-    glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
-    glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
-    return textureName;
+    texture->name = textureName;
+    texture->width = 0;
+    texture->height = 0;
+
+    const GLenum target = GL_TEXTURE_2D;
+    glBindTexture(target, textureName);
+    glTexParameterx(target, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
+    glTexParameterx(target, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
+    glTexParameterx(target, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+    glTexParameterx(target, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+
+    return NO_ERROR;
+}
+
+status_t TextureManager::initTexture(Image* pImage, int32_t format)
+{
+    if (pImage->name != -1UL)
+        return INVALID_OPERATION;
+
+    GLuint textureName = -1;
+    glGenTextures(1, &textureName);
+    pImage->name = textureName;
+    pImage->width = 0;
+    pImage->height = 0;
+
+    GLenum target = GL_TEXTURE_2D;
+#if defined(GL_OES_texture_external)
+    if (format && isSupportedYuvFormat(format)) {
+        target = GL_TEXTURE_EXTERNAL_OES;
+        pImage->target = Texture::TEXTURE_EXTERNAL;
+    }
+#endif
+
+    glBindTexture(target, textureName);
+    glTexParameterx(target, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
+    glTexParameterx(target, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
+    glTexParameterx(target, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+    glTexParameterx(target, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+
+    return NO_ERROR;
 }
 
 bool TextureManager::isSupportedYuvFormat(int format)
 {
+    // TODO: how to we know which YUV formats are supported by the GPU?
+
+    // Adreno 200 supports these
+    // YUVY_adreno
+    // UYVY_adreno
+    // NV21_adreno
+    // YV12_adreno
+    // Adreno 205 adds
+    // NV12_adreno_tiled
+    // NV21_adreno_tiled
+
+    // for now pretend we support them all, failure will happen when
+    // we try to use them.
+    return isYuvFormat(format);
+}
+
+bool TextureManager::isYuvFormat(int format)
+{
     switch (format) {
-        case HAL_PIXEL_FORMAT_YCbCr_422_SP:
-        case HAL_PIXEL_FORMAT_YCbCr_420_SP:
-        case HAL_PIXEL_FORMAT_YCbCr_422_P:
-        case HAL_PIXEL_FORMAT_YCbCr_420_P:
-        case HAL_PIXEL_FORMAT_YCbCr_422_I:
-        case HAL_PIXEL_FORMAT_YCbCr_420_I:
-        case HAL_PIXEL_FORMAT_YCrCb_420_SP:
-            return true;
+    case HAL_PIXEL_FORMAT_NV16:
+    case HAL_PIXEL_FORMAT_NV21:
+    case HAL_PIXEL_FORMAT_IYUV:
+    case HAL_PIXEL_FORMAT_YUV9:
+    case HAL_PIXEL_FORMAT_YUY2:
+    case HAL_PIXEL_FORMAT_UYVY:
+    case HAL_PIXEL_FORMAT_NV12:
+    case HAL_PIXEL_FORMAT_NV61:
+    case HAL_PIXEL_FORMAT_YV12:
+    case HAL_PIXEL_FORMAT_NV12_ADRENO_TILED:
+    case HAL_PIXEL_FORMAT_NV21_ADRENO_TILED:
+        return true;
     }
     return false;
 }
 
-status_t TextureManager::initEglImage(Image* texture,
+status_t TextureManager::initEglImage(Image* pImage,
         EGLDisplay dpy, const sp<GraphicBuffer>& buffer)
 {
     status_t err = NO_ERROR;
-    if (!texture->dirty) return err;
+    if (!pImage->dirty) return err;
 
     // free the previous image
-    if (texture->image != EGL_NO_IMAGE_KHR) {
-        eglDestroyImageKHR(dpy, texture->image);
-        texture->image = EGL_NO_IMAGE_KHR;
+    if (pImage->image != EGL_NO_IMAGE_KHR) {
+        eglDestroyImageKHR(dpy, pImage->image);
+        pImage->image = EGL_NO_IMAGE_KHR;
     }
 
     // construct an EGL_NATIVE_BUFFER_ANDROID
@@ -88,29 +157,27 @@
             EGL_IMAGE_PRESERVED_KHR,    EGL_TRUE,
             EGL_NONE,                   EGL_NONE
     };
-    texture->image = eglCreateImageKHR(
+    pImage->image = eglCreateImageKHR(
             dpy, EGL_NO_CONTEXT, EGL_NATIVE_BUFFER_ANDROID,
             (EGLClientBuffer)clientBuf, attrs);
 
-    if (texture->image != EGL_NO_IMAGE_KHR) {
-        if (texture->name == -1UL) {
-            texture->name = createTexture();
-            texture->width = 0;
-            texture->height = 0;
+    if (pImage->image != EGL_NO_IMAGE_KHR) {
+        if (pImage->name == -1UL) {
+            initTexture(pImage, buffer->format);
         }
-        glBindTexture(GL_TEXTURE_2D, texture->name);
-        glEGLImageTargetTexture2DOES(GL_TEXTURE_2D,
-                (GLeglImageOES)texture->image);
+        const GLenum target = getTextureTarget(pImage);
+        glBindTexture(target, pImage->name);
+        glEGLImageTargetTexture2DOES(target, (GLeglImageOES)pImage->image);
         GLint error = glGetError();
         if (error != GL_NO_ERROR) {
             LOGE("glEGLImageTargetTexture2DOES(%p) failed err=0x%04x",
-                    texture->image, error);
+                    pImage->image, error);
             err = INVALID_OPERATION;
         } else {
             // Everything went okay!
-            texture->dirty  = false;
-            texture->width  = clientBuf->width;
-            texture->height = clientBuf->height;
+            pImage->dirty  = false;
+            pImage->width  = clientBuf->width;
+            pImage->height = clientBuf->height;
         }
     } else {
         LOGE("eglCreateImageKHR() failed. err=0x%4x", eglGetError());
@@ -123,11 +190,14 @@
         const Region& dirty, const GGLSurface& t)
 {
     if (texture->name == -1UL) {
-        texture->name = createTexture();
-        texture->width = 0;
-        texture->height = 0;
+        status_t err = initTexture(texture);
+        LOGE_IF(err, "loadTexture failed in initTexture (%s)", strerror(err));
+        return err;
     }
 
+    if (texture->target != GL_TEXTURE_2D)
+        return INVALID_OPERATION;
+
     glBindTexture(GL_TEXTURE_2D, texture->name);
 
     /*
@@ -197,7 +267,7 @@
             glTexImage2D(GL_TEXTURE_2D, 0,
                     GL_RGBA, texture->potWidth, texture->potHeight, 0,
                     GL_RGBA, GL_UNSIGNED_BYTE, data);
-        } else if (isSupportedYuvFormat(t.format)) {
+        } else if (isYuvFormat(t.format)) {
             // just show the Y plane of YUV buffers
             glTexImage2D(GL_TEXTURE_2D, 0,
                     GL_LUMINANCE, texture->potWidth, texture->potHeight, 0,
@@ -225,7 +295,7 @@
                     0, bounds.top, t.width, bounds.height(),
                     GL_RGBA, GL_UNSIGNED_BYTE,
                     t.data + bounds.top*t.stride*4);
-        } else if (isSupportedYuvFormat(t.format)) {
+        } else if (isYuvFormat(t.format)) {
             // just show the Y plane of YUV buffers
             glTexSubImage2D(GL_TEXTURE_2D, 0,
                     0, bounds.top, t.width, bounds.height(),
@@ -236,6 +306,38 @@
     return NO_ERROR;
 }
 
+void TextureManager::activateTexture(const Texture& texture, bool filter)
+{
+    const GLenum target = getTextureTarget(&texture);
+
+    glBindTexture(target, texture.name);
+    glEnable(target);
+
+#if defined(GL_OES_texture_external)
+    if (texture.target == Texture::TEXTURE_2D) {
+        glDisable(GL_TEXTURE_EXTERNAL_OES);
+    } else {
+        glDisable(GL_TEXTURE_2D);
+    }
+#endif
+
+    if (filter) {
+        glTexParameterx(target, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+        glTexParameterx(target, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
+    } else {
+        glTexParameterx(target, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+        glTexParameterx(target, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+    }
+}
+
+void TextureManager::deactivateTextures()
+{
+    glDisable(GL_TEXTURE_2D);
+#if defined(GL_OES_texture_external)
+    glDisable(GL_TEXTURE_EXTERNAL_OES);
+#endif
+}
+
 // ---------------------------------------------------------------------------
 
 }; // namespace android
diff --git a/libs/surfaceflinger/TextureManager.h b/libs/surfaceflinger/TextureManager.h
index d0acfe9..1f7fe3f 100644
--- a/libs/surfaceflinger/TextureManager.h
+++ b/libs/surfaceflinger/TextureManager.h
@@ -37,31 +37,36 @@
 // ---------------------------------------------------------------------------
 
 struct Image {
+    enum { TEXTURE_2D=0, TEXTURE_EXTERNAL=1 };
     Image() : name(-1U), image(EGL_NO_IMAGE_KHR), width(0), height(0),
-        transform(0), dirty(true) { }
+        transform(0), dirty(1), target(TEXTURE_2D) { }
     GLuint        name;
     EGLImageKHR   image;
     GLuint        width;
     GLuint        height;
     uint32_t      transform;
-    bool          dirty;
+    unsigned      dirty     : 1;
+    unsigned      target    : 1;
 };
 
 struct Texture : public Image {
-    Texture() : Image(), NPOTAdjust(false)  { }
-    GLuint        potWidth;
-    GLuint        potHeight;
-    GLfloat       wScale;
-    GLfloat       hScale;
-    bool          NPOTAdjust;
+    Texture() : Image(), NPOTAdjust(0) { }
+    GLuint      potWidth;
+    GLuint      potHeight;
+    GLfloat     wScale;
+    GLfloat     hScale;
+    unsigned    NPOTAdjust  : 1;
 };
 
 // ---------------------------------------------------------------------------
 
 class TextureManager {
     uint32_t mFlags;
-    GLuint createTexture();
+    static status_t initTexture(Image* texture, int32_t format);
+    static status_t initTexture(Texture* texture);
     static bool isSupportedYuvFormat(int format);
+    static bool isYuvFormat(int format);
+    static GLenum getTextureTarget(const Image* pImage);
 public:
 
     TextureManager(uint32_t flags);
@@ -73,6 +78,12 @@
     // make active buffer an EGLImage if needed
     status_t initEglImage(Image* texture,
             EGLDisplay dpy, const sp<GraphicBuffer>& buffer);
+
+    // activate a texture
+    static void activateTexture(const Texture& texture, bool filter);
+
+    // deactivate a texture
+    static void deactivateTextures();
 };
 
 // ---------------------------------------------------------------------------
diff --git a/libs/ui/PixelFormat.cpp b/libs/ui/PixelFormat.cpp
index 9b41804..04c4779 100644
--- a/libs/ui/PixelFormat.cpp
+++ b/libs/ui/PixelFormat.cpp
@@ -70,8 +70,6 @@
     case HAL_PIXEL_FORMAT_YCbCr_420_SP_TILED:
     case HAL_PIXEL_FORMAT_YCrCb_420_SP_TILED:
     case HAL_PIXEL_FORMAT_YCbCr_420_P:
-    case HAL_PIXEL_FORMAT_YCbCr_420_I:
-    case HAL_PIXEL_FORMAT_CbYCrY_420_I:
         info->bitsPerPixel = 12;
      done:
         info->format = format;
diff --git a/opengl/include/GLES/glext.h b/opengl/include/GLES/glext.h
index 9596148..a5b3ead 100644
--- a/opengl/include/GLES/glext.h
+++ b/opengl/include/GLES/glext.h
@@ -211,6 +211,11 @@
 #define GL_VERTEX_ARRAY_BINDING_OES                             0x85B5
 #endif
 
+/* GL_OES_texture_external */
+#ifndef GL_TEXTURE_EXTERNAL_OES
+#define GL_TEXTURE_EXTERNAL_OES                                 0x8D65
+#endif
+
 /*------------------------------------------------------------------------*
  * AMD extension tokens
  *------------------------------------------------------------------------*/
@@ -777,6 +782,11 @@
 typedef GLboolean (GL_APIENTRYP PFNGLISVERTEXARRAYOESPROC) (GLuint array);
 #endif
 
+/* GL_OES_texture_external */
+#ifndef GL_OES_texture_external
+#define GL_OES_texture_external 1
+#endif
+
 /*------------------------------------------------------------------------*
  * AMD extension functions
  *------------------------------------------------------------------------*/
diff --git a/opengl/include/GLES2/gl2ext.h b/opengl/include/GLES2/gl2ext.h
index d8c9f41..de5d65a 100644
--- a/opengl/include/GLES2/gl2ext.h
+++ b/opengl/include/GLES2/gl2ext.h
@@ -146,6 +146,11 @@
 #define GL_INT_10_10_10_2_OES                                   0x8DF7
 #endif
 
+/* GL_OES_texture_external */
+#ifndef GL_TEXTURE_EXTERNAL_OES
+#define GL_TEXTURE_EXTERNAL_OES                                 0x8D65
+#endif
+
 /*------------------------------------------------------------------------*
  * AMD extension tokens
  *------------------------------------------------------------------------*/
@@ -541,6 +546,11 @@
 #define GL_OES_vertex_type_10_10_10_2 1
 #endif
 
+/* GL_OES_texture_external */
+#ifndef GL_OES_texture_external
+#define GL_OES_texture_external 1
+#endif
+
 /*------------------------------------------------------------------------*
  * AMD extension functions
  *------------------------------------------------------------------------*/