/*
* Copyright (C) 2011 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.
*/
#include "eglDisplay.h"
#include "HostConnection.h"
#include "KeyedVectorUtils.h"

#ifdef HOST_BUILD
#include "android/base/files/PathUtils.cpp"
#include "android/base/system/System.cpp"
#endif

#include <string>
#include <dlfcn.h>
#include <GLES3/gl31.h>

#include <system/graphics.h>

static const int systemEGLVersionMajor = 1;
static const int systemEGLVersionMinor = 4;
static const char systemEGLVendor[] = "Google Android emulator";

// list of extensions supported by this EGL implementation
//  NOTE that each extension name should be suffixed with space
static const char systemStaticEGLExtensions[] =
            "EGL_ANDROID_image_native_buffer "
            "EGL_KHR_fence_sync "
            "EGL_KHR_image_base "
            "EGL_KHR_gl_texture_2d_image ";

// extensions to add dynamically depending on host-side support
static const char kDynamicEGLExtNativeSync[] = "EGL_ANDROID_native_fence_sync ";
static const char kDynamicEGLExtWaitSync[] = "EGL_KHR_wait_sync ";

static void *s_gles_lib = NULL;
static void *s_gles2_lib = NULL;

// The following function will be called when we (libEGL)
// gets unloaded
// At this point we want to unload the gles libraries we
// might have loaded during initialization
static void __attribute__ ((destructor)) do_on_unload(void)
{
    if (s_gles_lib) {
        dlclose(s_gles_lib);
    }

    if (s_gles2_lib) {
        dlclose(s_gles2_lib);
    }
}

eglDisplay::eglDisplay() :
    m_initialized(false),
    m_major(0),
    m_minor(0),
    m_hostRendererVersion(0),
    m_numConfigs(0),
    m_numConfigAttribs(0),
    m_attribs(),
    m_configs(NULL),
    m_gles_iface(NULL),
    m_gles2_iface(NULL),
    m_versionString(NULL),
    m_vendorString(NULL),
    m_extensionString(NULL),
    m_hostDriverCaps_knownMajorVersion(0),
    m_hostDriverCaps_knownMinorVersion(0)
{
    pthread_mutex_init(&m_lock, NULL);
    pthread_mutex_init(&m_ctxLock, NULL);
    pthread_mutex_init(&m_surfaceLock, NULL);
}

eglDisplay::~eglDisplay()
{
    terminate();
    pthread_mutex_destroy(&m_lock);
    pthread_mutex_destroy(&m_ctxLock);
    pthread_mutex_destroy(&m_surfaceLock);
}



bool eglDisplay::initialize(EGLClient_eglInterface *eglIface)
{
    pthread_mutex_lock(&m_lock);
    if (!m_initialized) {

        //
        // load GLES client API
        //
        m_gles_iface = loadGLESClientAPI("libGLESv1_CM_emulation",
                                         eglIface,
                                         &s_gles_lib);
        if (!m_gles_iface) {
            pthread_mutex_unlock(&m_lock);
            ALOGE("Failed to load gles1 iface");
            return false;
        }

        m_gles2_iface = loadGLESClientAPI("libGLESv2_emulation",
                                          eglIface,
                                          &s_gles2_lib);

        //
        // establish connection with the host
        //
        HostConnection *hcon = HostConnection::get();
        if (!hcon) {
            pthread_mutex_unlock(&m_lock);
            ALOGE("Failed to establish connection with the host\n");
            return false;
        }

        //
        // get renderControl encoder instance
        //
        renderControl_encoder_context_t *rcEnc = hcon->rcEncoder();
        if (!rcEnc) {
            pthread_mutex_unlock(&m_lock);
            ALOGE("Failed to get renderControl encoder instance");
            return false;
        }

        //
        // Query host reneder and EGL version
        //
        m_hostRendererVersion = rcEnc->rcGetRendererVersion(rcEnc);
        EGLint status = rcEnc->rcGetEGLVersion(rcEnc, &m_major, &m_minor);
        if (status != EGL_TRUE) {
            // host EGL initialization failed !!
            pthread_mutex_unlock(&m_lock);
            return false;
        }

        //
        // Take minimum version beween what we support and what the host support
        //
        if (m_major > systemEGLVersionMajor) {
            m_major = systemEGLVersionMajor;
            m_minor = systemEGLVersionMinor;
        }
        else if (m_major == systemEGLVersionMajor &&
                 m_minor > systemEGLVersionMinor) {
            m_minor = systemEGLVersionMinor;
        }

        //
        // Query the host for the set of configs
        //
        m_numConfigs = rcEnc->rcGetNumConfigs(rcEnc, (uint32_t*)&m_numConfigAttribs);
        if (m_numConfigs <= 0 || m_numConfigAttribs <= 0) {
            // just sanity check - should never happen
            pthread_mutex_unlock(&m_lock);
            return false;
        }

        uint32_t nInts = m_numConfigAttribs * (m_numConfigs + 1);
        EGLint tmp_buf[nInts];

        m_configs = new EGLint[nInts-m_numConfigAttribs];

        if (!m_configs) {
            pthread_mutex_unlock(&m_lock);
            return false;
        }

        EGLint n = rcEnc->rcGetConfigs(rcEnc, nInts*sizeof(EGLint), (GLuint*)tmp_buf);
        if (n != m_numConfigs) {
            pthread_mutex_unlock(&m_lock);
            return false;
        }

        // Fill the attributes vector.
        // The first m_numConfigAttribs values of tmp_buf are the actual attributes enums.
        for (int i=0; i<m_numConfigAttribs; i++) {
            m_attribs[tmp_buf[i]] = i;
        }

        memcpy(m_configs, tmp_buf + m_numConfigAttribs,
               m_numConfigs*m_numConfigAttribs*sizeof(EGLint));

        m_initialized = true;
    }
    pthread_mutex_unlock(&m_lock);

    processConfigs();

    return true;
}

void eglDisplay::processConfigs()
{
    for (intptr_t i=0; i<m_numConfigs; i++) {
        EGLConfig config = getConfigAtIndex(i);
        uint32_t format;
        if (getConfigNativePixelFormat(config, &format)) {
            setConfigAttrib(config, EGL_NATIVE_VISUAL_ID, format);
        }
    }
}

void eglDisplay::terminate()
{
    pthread_mutex_lock(&m_lock);
    if (m_initialized) {
        // Cannot use the for loop in the following code because
        // eglDestroyContext may erase elements.
        EGLContextSet::iterator ctxIte = m_contexts.begin();
        while (ctxIte != m_contexts.end()) {
            EGLContextSet::iterator ctxToDelete = ctxIte;
            ctxIte ++;
            eglDestroyContext(static_cast<EGLDisplay>(this), *ctxToDelete);
        }
        EGLSurfaceSet::iterator surfaceIte = m_surfaces.begin();
        while (surfaceIte != m_surfaces.end()) {
            EGLSurfaceSet::iterator surfaceToDelete = surfaceIte;
            surfaceIte ++;
            eglDestroySurface(static_cast<EGLDisplay>(this), *surfaceToDelete);
        }
        m_initialized = false;
        delete [] m_configs;
        m_configs = NULL;

        if (m_versionString) {
            free(m_versionString);
            m_versionString = NULL;
        }
        if (m_vendorString) {
            free(m_vendorString);
            m_vendorString = NULL;
        }
        if (m_extensionString) {
            free(m_extensionString);
            m_extensionString = NULL;
        }
    }
    pthread_mutex_unlock(&m_lock);
}

#ifdef __APPLE__
#define LIBSUFFIX ".dylib"
#else
#ifdef _WIN32
#define LIBSUFFIX ".dll"
#else
#define LIBSUFFIX ".so"
#endif // !_WIN32 (linux)
#endif // !__APPLE__

#ifndef HOST_BUILD
#if PLATFORM_SDK_VERSION >= 26
#define PARTITION "/vendor"
#else
#define PARTITION "/system"
#endif // !PLATFORM_SDK_VERSION >= 26
#if __LP64__
#define LIBDIR "/lib64/egl/"
#else
#define LIBDIR "/lib/egl/"
#endif // !__LP64__
#endif // !HOST_BUILD

EGLClient_glesInterface *eglDisplay::loadGLESClientAPI(const char *basename,
                                                       EGLClient_eglInterface *eglIface,
                                                       void **libHandle)
{
#ifdef HOST_BUILD
    std::string baseDir =
        android::base::System::get()->getProgramDirectory();
    std::string path =
        android::base::pj({
            baseDir, "lib64", std::string(basename) + LIBSUFFIX});
    void *lib = dlopen(path.c_str(), RTLD_NOW);
#else
    std::string path(PARTITION);
    path += LIBDIR;
    path += basename;
    path += LIBSUFFIX;
    void *lib = dlopen(path.c_str(), RTLD_NOW);
#endif

    if (!lib) {
        ALOGE("Failed to dlopen %s", basename);
        return NULL;
    }

    init_emul_gles_t init_gles_func = (init_emul_gles_t)dlsym(lib,"init_emul_gles");
    if (!init_gles_func) {
        ALOGE("Failed to find init_emul_gles");
        dlclose((void*)lib);
        return NULL;
    }

    *libHandle = lib;
    return (*init_gles_func)(eglIface);
}

static char *queryHostEGLString(EGLint name)
{
    HostConnection *hcon = HostConnection::get();
    if (hcon) {
        renderControl_encoder_context_t *rcEnc = hcon->rcEncoder();
        if (rcEnc) {
            int n = rcEnc->rcQueryEGLString(rcEnc, name, NULL, 0);
            if (n < 0) {
                // allocate space for the string.
                char *str = (char *)malloc(-n);
                n = rcEnc->rcQueryEGLString(rcEnc, name, str, -n);
                if (n > 0) {
                    return str;
                }

                free(str);
            }
        }
    }

    return NULL;
}

static char *buildExtensionString()
{
    //Query host extension string
    char *hostExt = queryHostEGLString(EGL_EXTENSIONS);
    if (!hostExt || (hostExt[1] == '\0')) {
        // no extensions on host - only static extension list supported
        return strdup(systemStaticEGLExtensions);
    }

    int n = strlen(hostExt);
    if (n > 0) {
        char *initialEGLExts;
        char *finalEGLExts;

        HostConnection *hcon = HostConnection::get();
        // If we got here, we must have succeeded in queryHostEGLString
        // and we thus should have a valid connection
        assert(hcon);

        asprintf(&initialEGLExts,"%s%s", systemStaticEGLExtensions, hostExt);

        std::string dynamicEGLExtensions;

        if ((hcon->rcEncoder()->hasVirtioGpuNativeSync() || hcon->rcEncoder()->hasNativeSync()) &&
            !strstr(initialEGLExts, kDynamicEGLExtNativeSync)) {
            dynamicEGLExtensions += kDynamicEGLExtNativeSync;

            if (hcon->rcEncoder()->hasVirtioGpuNativeSync() || hcon->rcEncoder()->hasNativeSyncV3()) {
                dynamicEGLExtensions += kDynamicEGLExtWaitSync;
            }
        }

        asprintf(&finalEGLExts, "%s%s", initialEGLExts, dynamicEGLExtensions.c_str());

        free(initialEGLExts);
        free((char*)hostExt);
        return finalEGLExts;
    }
    else {
        free((char*)hostExt);
        return strdup(systemStaticEGLExtensions);
    }
}

const char *eglDisplay::queryString(EGLint name)
{
    if (name == EGL_CLIENT_APIS) {
        return "OpenGL_ES";
    }
    else if (name == EGL_VERSION) {
        pthread_mutex_lock(&m_lock);
        if (m_versionString) {
            pthread_mutex_unlock(&m_lock);
            return m_versionString;
        }

        // build version string
        asprintf(&m_versionString, "%d.%d", m_major, m_minor);
        pthread_mutex_unlock(&m_lock);

        return m_versionString;
    }
    else if (name == EGL_VENDOR) {
        pthread_mutex_lock(&m_lock);
        if (m_vendorString) {
            pthread_mutex_unlock(&m_lock);
            return m_vendorString;
        }

        // build vendor string
        const char *hostVendor = queryHostEGLString(EGL_VENDOR);

        if (hostVendor) {
            asprintf(&m_vendorString, "%s Host: %s",
                                     systemEGLVendor, hostVendor);
            free((char*)hostVendor);
        }
        else {
            m_vendorString = (char *)systemEGLVendor;
        }
        pthread_mutex_unlock(&m_lock);

        return m_vendorString;
    }
    else if (name == EGL_EXTENSIONS) {
        pthread_mutex_lock(&m_lock);
        if (m_extensionString) {
            pthread_mutex_unlock(&m_lock);
            return m_extensionString;
        }

        // build extension string
        m_extensionString = buildExtensionString();
        pthread_mutex_unlock(&m_lock);

        return m_extensionString;
    }
    else {
        ALOGE("[%s] Unknown name %d\n", __FUNCTION__, name);
        return NULL;
    }
}

/* To get the value of attribute <a> of config <c> use the following formula:
 * value = *(m_configs + (int)c*m_numConfigAttribs + a);
 */
EGLBoolean eglDisplay::getAttribValue(EGLConfig config, EGLint attribIdx, EGLint * value)
{
    if (attribIdx == ATTRIBUTE_NONE)
    {
        ALOGE("[%s] Bad attribute idx\n", __FUNCTION__);
        return EGL_FALSE;
    }
    *value = *(m_configs + (intptr_t)(getIndexOfConfig(config))*m_numConfigAttribs + attribIdx);
    return EGL_TRUE;
}

#define EGL_COLOR_COMPONENT_TYPE_EXT 0x3339
#define EGL_COLOR_COMPONENT_TYPE_FIXED_EXT 0x333A

EGLConfig eglDisplay::getConfigAtIndex(uint32_t index) const {
    uintptr_t asPtr = (uintptr_t)index;
    return (EGLConfig)(asPtr + 1);
}

uint32_t eglDisplay::getIndexOfConfig(EGLConfig config) const {
    uintptr_t asInteger = (uintptr_t)config;
    return (uint32_t)(asInteger - 1);
}

bool eglDisplay::isValidConfig(EGLConfig cfg) const {
    uint32_t index = getIndexOfConfig(cfg);
    intptr_t asInt = (intptr_t)index;
    return !(asInt < 0 || asInt > m_numConfigs);
}

EGLBoolean eglDisplay::getConfigAttrib(EGLConfig config, EGLint attrib, EGLint * value)
{
    if (attrib == EGL_FRAMEBUFFER_TARGET_ANDROID) {
        *value = EGL_TRUE;
        return EGL_TRUE;
    }
    if (attrib == EGL_COVERAGE_SAMPLES_NV ||
        attrib == EGL_COVERAGE_BUFFERS_NV) {
        *value = 0;
        return EGL_TRUE;
    }
    if (attrib == EGL_DEPTH_ENCODING_NV) {
        *value = EGL_DEPTH_ENCODING_NONE_NV;
        return EGL_TRUE;
    }
    if  (attrib == EGL_COLOR_COMPONENT_TYPE_EXT) {
        *value = EGL_COLOR_COMPONENT_TYPE_FIXED_EXT;
        return EGL_TRUE;
    }
    //Though it seems that valueFor() is thread-safe, we don't take chanses
    pthread_mutex_lock(&m_lock);
    EGLBoolean ret =
        getAttribValue(
            config,
            findObjectOrDefault(
                m_attribs, attrib, EGL_DONT_CARE),
            value);
    pthread_mutex_unlock(&m_lock);
    return ret;
}

void eglDisplay::dumpConfig(EGLConfig config)
{
    EGLint value = 0;
    DBG("^^^^^^^^^^ dumpConfig %p ^^^^^^^^^^^^^^^^^^", config);
    for (int i=0; i<m_numConfigAttribs; i++) {
        getAttribValue(config, i, &value);
        DBG("Config %p: {%u}[%d] %d\n", config, getIndexOfConfig(config), i, value);
    }
}

/* To set the value of attribute <a> of config <c> use the following formula:
 * *(m_configs + (int)c*m_numConfigAttribs + a) = value;
 */
EGLBoolean eglDisplay::setAttribValue(EGLConfig config, EGLint attribIdx, EGLint value)
{
    if (attribIdx == ATTRIBUTE_NONE)
    {
        ALOGE("[%s] Bad attribute idx\n", __FUNCTION__);
        return EGL_FALSE;
    }
    *(m_configs + (intptr_t)(getIndexOfConfig(config))*m_numConfigAttribs + attribIdx) = value;
    return EGL_TRUE;
}

EGLBoolean eglDisplay::setConfigAttrib(EGLConfig config, EGLint attrib, EGLint value)
{
    //Though it seems that valueFor() is thread-safe, we don't take chanses
    pthread_mutex_lock(&m_lock);
    EGLBoolean ret =
        setAttribValue(
            config,
            findObjectOrDefault(
                m_attribs,
                attrib,
                EGL_DONT_CARE),
            value);
    pthread_mutex_unlock(&m_lock);
    return ret;
}


EGLBoolean eglDisplay::getConfigNativePixelFormat(EGLConfig config, uint32_t * format)
{
    EGLint redSize, blueSize, greenSize, alphaSize;

    if (!(
            getAttribValue(
                config,
                findObjectOrDefault(m_attribs, EGL_RED_SIZE, EGL_DONT_CARE),
                &redSize) &&
            getAttribValue(
                config,
                findObjectOrDefault(m_attribs, EGL_BLUE_SIZE, EGL_DONT_CARE),
                &blueSize) &&
            getAttribValue(
                config,
                findObjectOrDefault(m_attribs, EGL_GREEN_SIZE, EGL_DONT_CARE),
                &greenSize) &&
            getAttribValue(
                config,
                findObjectOrDefault(m_attribs, EGL_ALPHA_SIZE, EGL_DONT_CARE),
                &alphaSize))) {
        ALOGE("Couldn't find value for one of the pixel format attributes");
        return EGL_FALSE;
    }

    //calculate the GL internal format
    if ((redSize==8)&&(greenSize==8)&&(blueSize==8)&&(alphaSize==8)) *format = HAL_PIXEL_FORMAT_RGBA_8888; //XXX: BGR?
    else if ((redSize==8)&&(greenSize==8)&&(blueSize==8)&&(alphaSize==0)) *format = HAL_PIXEL_FORMAT_RGBX_8888; //XXX or HAL_PIXEL_FORMAT_RGB_888
    else if ((redSize==5)&&(greenSize==6)&&(blueSize==5)&&(alphaSize==0)) *format = HAL_PIXEL_FORMAT_RGB_565;
    else {
        return EGL_FALSE;
    }
    return EGL_TRUE;
}
EGLBoolean eglDisplay::getConfigGLPixelFormat(EGLConfig config, GLenum * format)
{
    EGLint redSize, blueSize, greenSize, alphaSize;

    if (!(
            getAttribValue(
                config,
                findObjectOrDefault(m_attribs, EGL_RED_SIZE, EGL_DONT_CARE),
                &redSize) &&
            getAttribValue(
                config,
                findObjectOrDefault(m_attribs, EGL_BLUE_SIZE, EGL_DONT_CARE),
                &blueSize) &&
            getAttribValue(
                config,
                findObjectOrDefault(m_attribs, EGL_GREEN_SIZE, EGL_DONT_CARE),
                &greenSize) &&
            getAttribValue(
                config,
                findObjectOrDefault(m_attribs, EGL_ALPHA_SIZE, EGL_DONT_CARE),
                &alphaSize))) {
        ALOGE("Couldn't find value for one of the pixel format attributes");
        return EGL_FALSE;
    }

    //calculate the GL internal format
    if ((redSize == greenSize) && (redSize == blueSize) &&
        ((redSize == 8) || (redSize == 16) || (redSize == 32)))
    {
        if (alphaSize == 0) *format = GL_RGB;
        else *format = GL_RGBA;
    }
    else if ((redSize==5)&&(greenSize==6)&&(blueSize==5)&&(alphaSize==0)) *format = GL_RGB565_OES;
    else if ((redSize==5)&&(greenSize==5)&&(blueSize==5)&&(alphaSize==1)) *format = GL_RGB5_A1_OES;
    else if ((redSize==4)&&(greenSize==4)&&(blueSize==4)&&(alphaSize==4)) *format = GL_RGBA4_OES;
    else return EGL_FALSE;

    return EGL_TRUE;
}

void eglDisplay::onCreateContext(EGLContext ctx) {
    pthread_mutex_lock(&m_ctxLock);
    m_contexts.insert(ctx);
    pthread_mutex_unlock(&m_ctxLock);
}

void eglDisplay::onCreateSurface(EGLSurface surface) {
    pthread_mutex_lock(&m_surfaceLock);
    m_surfaces.insert(surface);
    pthread_mutex_unlock(&m_surfaceLock);
}

void eglDisplay::onDestroyContext(EGLContext ctx) {
    pthread_mutex_lock(&m_ctxLock);
    m_contexts.erase(ctx);
    pthread_mutex_unlock(&m_ctxLock);
}

void eglDisplay::onDestroySurface(EGLSurface surface) {
    pthread_mutex_lock(&m_surfaceLock);
    m_surfaces.erase(surface);
    pthread_mutex_unlock(&m_surfaceLock);
}

bool eglDisplay::isContext(EGLContext ctx) {
    pthread_mutex_lock(&m_ctxLock);
    bool res = m_contexts.find(ctx) != m_contexts.end();
    pthread_mutex_unlock(&m_ctxLock);
    return res;
}

bool eglDisplay::isSurface(EGLSurface surface) {
    pthread_mutex_lock(&m_surfaceLock);
    bool res = m_surfaces.find(surface) != m_surfaces.end();
    pthread_mutex_unlock(&m_surfaceLock);
    return res;
}

HostDriverCaps eglDisplay::getHostDriverCaps(int majorVersion, int minorVersion) {
    pthread_mutex_lock(&m_lock);
    if (majorVersion <= m_hostDriverCaps_knownMajorVersion &&
        minorVersion <= m_hostDriverCaps_knownMinorVersion) {
        pthread_mutex_unlock(&m_lock);
        return m_hostDriverCaps;
    }

    memset(&m_hostDriverCaps, 0x0, sizeof(m_hostDriverCaps));

    m_hostDriverCaps.max_color_attachments = 8;

    // Can we query gles2?
    if (majorVersion >= 1) {
        m_gles2_iface->getIntegerv(GL_MAX_VERTEX_ATTRIBS, &m_hostDriverCaps.max_vertex_attribs);
        m_gles2_iface->getIntegerv(GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS, &m_hostDriverCaps.max_combined_texture_image_units);

        m_gles2_iface->getIntegerv(GL_MAX_TEXTURE_SIZE, &m_hostDriverCaps.max_texture_size);
        m_gles2_iface->getIntegerv(GL_MAX_CUBE_MAP_TEXTURE_SIZE, &m_hostDriverCaps.max_texture_size_cube_map);
        m_gles2_iface->getIntegerv(GL_MAX_RENDERBUFFER_SIZE, &m_hostDriverCaps.max_renderbuffer_size);
        m_hostDriverCaps_knownMajorVersion = 2;
    }

    // Can we query gles3.0?
    if (majorVersion >= 3) {
        m_gles2_iface->getIntegerv(GL_MAX_COLOR_ATTACHMENTS, &m_hostDriverCaps.max_color_attachments);
        m_gles2_iface->getIntegerv(GL_MAX_DRAW_BUFFERS, &m_hostDriverCaps.max_draw_buffers);
        m_gles2_iface->getIntegerv(GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT, &m_hostDriverCaps.ubo_offset_alignment);
        m_gles2_iface->getIntegerv(GL_MAX_UNIFORM_BUFFER_BINDINGS, &m_hostDriverCaps.max_uniform_buffer_bindings);
        m_gles2_iface->getIntegerv(GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_ATTRIBS, &m_hostDriverCaps.max_transform_feedback_separate_attribs);
        m_gles2_iface->getIntegerv(GL_MAX_3D_TEXTURE_SIZE, &m_hostDriverCaps.max_texture_size_3d);
        m_gles2_iface->getIntegerv(GL_MAX_ARRAY_TEXTURE_LAYERS, &m_hostDriverCaps.max_array_texture_layers);

        m_hostDriverCaps_knownMajorVersion = 3;

        // Can we query gles3.1?
        if (minorVersion >= 1) {
            m_gles2_iface->getIntegerv(GL_MAX_ATOMIC_COUNTER_BUFFER_BINDINGS, &m_hostDriverCaps.max_atomic_counter_buffer_bindings);
            m_gles2_iface->getIntegerv(GL_MAX_SHADER_STORAGE_BUFFER_BINDINGS, &m_hostDriverCaps.max_shader_storage_buffer_bindings);
            m_gles2_iface->getIntegerv(GL_MAX_VERTEX_ATTRIB_BINDINGS, &m_hostDriverCaps.max_vertex_attrib_bindings);
            m_gles2_iface->getIntegerv(GL_MAX_VERTEX_ATTRIB_STRIDE, &m_hostDriverCaps.max_vertex_attrib_stride);
            m_gles2_iface->getIntegerv(GL_SHADER_STORAGE_BUFFER_OFFSET_ALIGNMENT, &m_hostDriverCaps.ssbo_offset_alignment);
            m_hostDriverCaps_knownMinorVersion = 1;
        }
    }

    pthread_mutex_unlock(&m_lock);

    return m_hostDriverCaps;
}

