[interface][fbo] Pass extensions, GL_EXT_color_buffer_float

- Pass extensions from the underlying OpenGL to encoder for
validation.
- Add GL_EXT_color_buffer_float.

Change-Id: I67f8e68012bba9c5ffef24d9588a9615cf6f0e6b
diff --git a/system/GLESv2_enc/GL2Encoder.cpp b/system/GLESv2_enc/GL2Encoder.cpp
index 5a3a62d..d263762 100755
--- a/system/GLESv2_enc/GL2Encoder.cpp
+++ b/system/GLESv2_enc/GL2Encoder.cpp
@@ -2280,9 +2280,15 @@
         switch (fbo_format_info.rb_format) {
         case GL_R16F:
         case GL_RG16F:
-        case GL_RGB16F:
         case GL_RGBA16F:
-            res = false;
+        case GL_R32F:
+        case GL_RG32F:
+        case GL_RGBA32F:
+        case GL_R11F_G11F_B10F:
+            res = hasExtension("GL_EXT_color_buffer_float");
+            break;
+        case GL_RGB16F:
+            res = hasExtension("GL_EXT_color_buffer_half_float");
             break;
         case GL_STENCIL_INDEX8:
             if (attachment == GL_STENCIL_ATTACHMENT) {
@@ -2297,16 +2303,20 @@
         break;
     case FBO_ATTACHMENT_TEXTURE:
         switch (fbo_format_info.tex_internalformat) {
-        case GL_RED:
-        case GL_RG:
         case GL_R16F:
         case GL_RG16F:
         case GL_RGBA16F:
-        case GL_RGB16F:
-        case GL_R11F_G11F_B10F:
         case GL_R32F:
         case GL_RG32F:
         case GL_RGBA32F:
+        case GL_R11F_G11F_B10F:
+            res = hasExtension("GL_EXT_color_buffer_float");
+            break;
+        case GL_RGB16F:
+            res = hasExtension("GL_EXT_color_buffer_half_float");
+            break;
+        case GL_RED:
+        case GL_RG:
         case GL_SRGB8:
         case GL_RGB32UI:
         case GL_RGB16UI:
@@ -3951,9 +3961,9 @@
                  GL_INVALID_ENUM);
     SET_ERROR_IF(!GLESv2Validation::internalFormatTarget(ctx, target), GL_INVALID_ENUM);
     SET_ERROR_IF(!GLESv2Validation::unsizedFormat(internalformat) &&
-                 !GLESv2Validation::colorRenderableFormat(internalformat) &&
-                 !GLESv2Validation::depthRenderableFormat(internalformat) &&
-                 !GLESv2Validation::stencilRenderableFormat(internalformat),
+                 !GLESv2Validation::colorRenderableFormat(ctx, internalformat) &&
+                 !GLESv2Validation::depthRenderableFormat(ctx, internalformat) &&
+                 !GLESv2Validation::stencilRenderableFormat(ctx, internalformat),
                  GL_INVALID_ENUM);
     SET_ERROR_IF(bufSize < 0, GL_INVALID_VALUE);
 
@@ -3992,8 +4002,8 @@
                  GL_INVALID_OPERATION);
     SET_ERROR_IF(tex &&
                  !GLESv2Validation::unsizedFormat(internalformat) &&
-                 (!GLESv2Validation::colorRenderableFormat(internalformat) ||
-                  !GLESv2Validation::filterableTexFormat(internalformat)),
+                 !(GLESv2Validation::colorRenderableFormat(ctx, internalformat) &&
+                   GLESv2Validation::filterableTexFormat(ctx, internalformat)),
                  GL_INVALID_OPERATION);
 
     ctx->m_glGenerateMipmap_enc(ctx, target);
diff --git a/system/GLESv2_enc/GL2Encoder.h b/system/GLESv2_enc/GL2Encoder.h
index 14d2c9a..928547c 100644
--- a/system/GLESv2_enc/GL2Encoder.h
+++ b/system/GLESv2_enc/GL2Encoder.h
@@ -21,6 +21,8 @@
 #include "GLSharedGroup.h"
 #include "FixedBuffer.h"
 
+#include <string>
+
 class GL2Encoder : public gl2_encoder_context_t {
 public:
     GL2Encoder(IOStream *stream, ChecksumCalculator* protocol);
@@ -41,6 +43,12 @@
     }
     int majorVersion() const { return m_currMajorVersion; }
     int minorVersion() const { return m_currMinorVersion; }
+    void setExtensions(const char* exts) {
+        m_currExtensions = std::string(exts);
+    }
+    bool hasExtension(const char* ext) const {
+        return m_currExtensions.find(ext) != std::string::npos;
+    }
     const GLClientState *state() { return m_state; }
     const GLSharedGroupPtr shared() { return m_shared; }
     void flush() { m_stream->flush(); }
@@ -66,6 +74,7 @@
 
     int m_currMajorVersion;
     int m_currMinorVersion;
+    std::string m_currExtensions;
 
     bool    m_initialized;
     GLClientState *m_state;
diff --git a/system/GLESv2_enc/GLESv2Validation.cpp b/system/GLESv2_enc/GLESv2Validation.cpp
index 0bf49e3..b2ccbdb 100644
--- a/system/GLESv2_enc/GLESv2Validation.cpp
+++ b/system/GLESv2_enc/GLESv2Validation.cpp
@@ -109,6 +109,7 @@
 
 bool rboFormat(GL2Encoder* ctx, GLenum internalformat) {
     int glesMajorVersion = ctx->majorVersion();
+
     switch (internalformat) {
     // Funny internal formats
     // that will cause an incomplete framebuffer
@@ -139,24 +140,26 @@
     case GL_RGBA16I:
     case GL_RGBA32I:
     case GL_RGBA32UI:
-    // case GL_R11F_G11F_B10F:
-    // case GL_R32F:
-    // case GL_RG32F:
     case GL_RGB32F:
-    // case GL_RGBA32F:
         return glesMajorVersion >= 3;
         // These 4 formats are still not OK,
         // but dEQP expects GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT or
-        // GL_FRAMEBUFFER_UNSUPPORTED,
+        // GL_FRAMEBUFFER_UNSUPPORTED if the extension is not present,
         // not a GL_INVALID_ENUM from earlier on.
         // So let's forward these to the rest of
         // FBO initialization
+        // In GLES 3, these are rejected immediately if not
+        // supported.
     case GL_R16F:
     case GL_RG16F:
-    case GL_RGB16F:
     case GL_RGBA16F:
-        // But in GLES 3, these are rejected immediately.
-        return glesMajorVersion < 3;
+    case GL_R32F:
+    case GL_RG32F:
+    case GL_RGBA32F:
+    case GL_R11F_G11F_B10F:
+        return glesMajorVersion < 3 || ctx->hasExtension("GL_EXT_color_buffer_float");
+    case GL_RGB16F:
+        return glesMajorVersion < 3 || ctx->hasExtension("GL_EXT_color_buffer_half_float");
         // dEQP expects GL_FRAMEBUFFER_UNSUPPORTED or GL_FRAMEBUFFER_COMPLETE
         // for this format
         // These formats are OK
@@ -480,15 +483,34 @@
     return true;
 }
 
+bool unsizedFormat(GLenum format) {
+    switch (format) {
+    case GL_RED:
+    case GL_RED_INTEGER:
+    case GL_DEPTH_COMPONENT:
+    case GL_DEPTH_STENCIL:
+    case GL_RG:
+    case GL_RG_INTEGER:
+    case GL_RGB:
+    case GL_RGB_INTEGER:
+    case GL_RGBA:
+    case GL_RGBA_INTEGER:
+    case GL_ALPHA:
+    case GL_LUMINANCE:
+    case GL_LUMINANCE_ALPHA:
+        return true;
+    }
+    return false;
+}
+
 // TODO: fix this
-bool filterableTexFormat(GLenum internalformat) {
+bool filterableTexFormat(GL2Encoder* ctx, GLenum internalformat) {
     switch (internalformat) {
-    // 32F's are not filterable.
     case GL_R32F:
     case GL_RG32F:
     case GL_RGB32F:
     case GL_RGBA32F:
-    // No integer textures are filterable.
+        return ctx->hasExtension("GL_OES_texture_float");
     case GL_R8UI:
     case GL_R8I:
     case GL_R16UI:
@@ -513,26 +535,8 @@
     return true;
 }
 
-bool unsizedFormat(GLenum format) {
-    switch (format) {
-    case GL_RED:
-    case GL_RED_INTEGER:
-    case GL_DEPTH_COMPONENT:
-    case GL_DEPTH_STENCIL:
-    case GL_RG:
-    case GL_RG_INTEGER:
-    case GL_RGB:
-    case GL_RGB_INTEGER:
-    case GL_RGBA:
-    case GL_RGBA_INTEGER:
-    case GL_ALPHA:
-    case GL_LUMINANCE:
-    case GL_LUMINANCE_ALPHA:
-        return true;
-    }
-    return false;
-}
-bool colorRenderableFormat(GLenum internalformat) {
+
+bool colorRenderableFormat(GL2Encoder* ctx, GLenum internalformat) {
     switch (internalformat) {
     case GL_R8:
     case GL_RG8:
@@ -563,11 +567,23 @@
     case GL_RGBA32I:
     case GL_RGBA32UI:
         return true;
+    case GL_R16F:
+    case GL_RG16F:
+    case GL_RGBA16F:
+    case GL_R32F:
+    case GL_RG32F:
+    case GL_RGBA32F:
+    case GL_R11F_G11F_B10F:
+        return ctx->hasExtension("GL_EXT_color_buffer_float");
+        break;
+    case GL_RGB16F:
+        return ctx->hasExtension("GL_EXT_color_buffer_half_float");
+        break;
     }
     return false;
 }
 
-bool depthRenderableFormat(GLenum internalformat) {
+bool depthRenderableFormat(GL2Encoder* ctx, GLenum internalformat) {
     switch (internalformat) {
     case GL_DEPTH_COMPONENT:
     case GL_DEPTH_STENCIL:
@@ -581,7 +597,7 @@
     return false;
 }
 
-bool stencilRenderableFormat(GLenum internalformat) {
+bool stencilRenderableFormat(GL2Encoder* ctx, GLenum internalformat) {
     switch (internalformat) {
     case GL_DEPTH_STENCIL:
     case GL_STENCIL_INDEX8:
diff --git a/system/GLESv2_enc/GLESv2Validation.h b/system/GLESv2_enc/GLESv2Validation.h
index 9fe9278..981589c 100644
--- a/system/GLESv2_enc/GLESv2Validation.h
+++ b/system/GLESv2_enc/GLESv2Validation.h
@@ -54,11 +54,13 @@
 
 bool isCompressedFormat(GLenum internalformat);
 bool supportedCompressedFormat(GL2Encoder* ctx, GLenum internalformat);
-bool filterableTexFormat(GLenum internalformat);
+
 bool unsizedFormat(GLenum format);
-bool colorRenderableFormat(GLenum internalformat);
-bool depthRenderableFormat(GLenum internalformat);
-bool stencilRenderableFormat(GLenum internalformat);
+
+bool filterableTexFormat(GL2Encoder* ctx, GLenum internalformat);
+bool colorRenderableFormat(GL2Encoder* ctx, GLenum internalformat);
+bool depthRenderableFormat(GL2Encoder* ctx, GLenum internalformat);
+bool stencilRenderableFormat(GL2Encoder* ctx, GLenum internalformat);
 
 bool isCubeMapTarget(GLenum target);
 
diff --git a/system/egl/egl.cpp b/system/egl/egl.cpp
index 7dcd836..275971c 100644
--- a/system/egl/egl.cpp
+++ b/system/egl/egl.cpp
@@ -1538,7 +1538,7 @@
                     max_draw_buffers);
         }
 
-        //set the client state
+        // set the client state and share group
         if (context->majorVersion > 1) {
             hostCon->gl2Encoder()->setClientStateMakeCurrent(
                     contextState,
@@ -1578,6 +1578,10 @@
                 hostCon->gl2Encoder()->setInitialized();
                 ClientAPIExts::initClientFuncs(s_display.gles2_iface(), 1);
             }
+            const char* exts = getGLString(GL_EXTENSIONS);
+            if (exts) {
+                hostCon->gl2Encoder()->setExtensions(exts);
+            }
         }
         else {
             if (!hostCon->glEncoder()->isInitialized()) {