Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit df0518c1 authored by Courtney Goeltzenleuchter's avatar Courtney Goeltzenleuchter Committed by Jiyong Park
Browse files

Add useful helper functions for tests

Trying to reduce code duplication by putting common
EGL functions used by opengl and surfaceflinger tests
here.
Test: adb shell /data/nativetest/test-opengl-gl2_basic/test-opengl-gl2_basic

Merged-In: Id7a32aedc565f3fbe56fa62ceb79cbb1e8c80727
Change-Id: Id7a32aedc565f3fbe56fa62ceb79cbb1e8c80727
(cherry picked from commit fe98f50b)
parent e89483f1
Loading
Loading
Loading
Loading
+172 −6
Original line number Diff line number Diff line
@@ -20,11 +20,16 @@

#include <stdint.h>
#include <stdlib.h>
#include <vector>

#include <EGL/egl.h>
#include <EGL/eglext.h>
#include <GLES2/gl2.h>
#include <system/window.h>
#include <utils/Errors.h>
#include <EGL/egl.h>
#include <utils/String8.h>

EGLAPI const char* eglQueryStringImplementationANDROID(EGLDisplay dpy, EGLint name);

// ----------------------------------------------------------------------------
namespace android {
@@ -47,6 +52,17 @@ public:
            EGLint const* attrs,
            EGLNativeWindowType window,
            EGLConfig* outConfig);

    static inline String8 printGLString(const char* name, GLenum s);
    static inline String8 printEGLString(EGLDisplay dpy, const char* name, GLenum s);
    static inline String8 checkEglError(const char* op, EGLBoolean returnVal);
    static inline String8 checkGlError(const char* op);
    static inline String8 printEGLConfiguration(EGLDisplay dpy, EGLConfig config);
    static inline bool printEGLConfigurations(EGLDisplay dpy, String8& msg);
    static inline bool printEGLConfigurations(FILE* output, EGLDisplay dpy);
    static inline String8 decodeColorSpace(EGLint colorSpace);
    static inline bool hasEglExtension(EGLDisplay dpy, const char* name);
    static inline bool hasExtension(const char* exts, const char* name);
};

// ----------------------------------------------------------------------------
@@ -91,9 +107,8 @@ status_t EGLUtils::selectConfigForPixelFormat(
    if (eglGetConfigs(dpy, NULL, 0, &numConfigs) == EGL_FALSE)
        return BAD_VALUE;

    EGLConfig* const configs = (EGLConfig*)malloc(sizeof(EGLConfig)*numConfigs);
    if (eglChooseConfig(dpy, attrs, configs, numConfigs, &n) == EGL_FALSE) {
        free(configs);
    std::vector<EGLConfig> configs(numConfigs);
    if (eglChooseConfig(dpy, attrs, configs.data(), numConfigs, &n) == EGL_FALSE) {
        return BAD_VALUE;
    }

@@ -108,8 +123,6 @@ status_t EGLUtils::selectConfigForPixelFormat(
        }
    }

    free(configs);

    if (i<n) {
        *outConfig = config;
        return NO_ERROR;
@@ -137,6 +150,159 @@ status_t EGLUtils::selectConfigForNativeWindow(
    return selectConfigForPixelFormat(dpy, attrs, format, outConfig);
}

String8 EGLUtils::printGLString(const char* name, GLenum s) {
    String8 msg;
    const char* v = reinterpret_cast<const char*>(glGetString(s));
    msg.appendFormat("GL %s = %s\n", name, v);
    return msg;
}

String8 EGLUtils::printEGLString(EGLDisplay dpy, const char* name, GLenum s) {
    String8 msg;
    const char* v = static_cast<const char*>(eglQueryString(dpy, s));
    msg.appendFormat("GL %s = %s\n", name, v);
    const char* va = (const char*)eglQueryStringImplementationANDROID(dpy, s);
    msg.appendFormat("ImplementationANDROID: %s = %s\n", name, va);
    return msg;
}

String8 EGLUtils::checkEglError(const char* op, EGLBoolean returnVal = EGL_TRUE) {
    String8 msg;
    if (returnVal != EGL_TRUE) {
        msg.appendFormat("%s() returned %d\n", op, returnVal);
    }

    for (EGLint error = eglGetError(); error != EGL_SUCCESS; error = eglGetError()) {
        msg.appendFormat("after %s() eglError %s (0x%x)\n", op, EGLUtils::strerror(error), error);
    }
    return msg;
}

String8 EGLUtils::checkGlError(const char* op) {
    String8 msg;
    for (GLint error = glGetError(); error != GL_NO_ERROR; error = glGetError()) {
        msg.appendFormat("after %s() glError (0x%x)\n", op, error);
    }
    return msg;
}

String8 EGLUtils::printEGLConfiguration(EGLDisplay dpy, EGLConfig config) {
#define X(VAL) \
    { VAL, #VAL }
    struct {
        EGLint attribute;
        const char* name;
    } names[] = {
            X(EGL_BUFFER_SIZE),
            X(EGL_ALPHA_SIZE),
            X(EGL_BLUE_SIZE),
            X(EGL_GREEN_SIZE),
            X(EGL_RED_SIZE),
            X(EGL_DEPTH_SIZE),
            X(EGL_STENCIL_SIZE),
            X(EGL_CONFIG_CAVEAT),
            X(EGL_CONFIG_ID),
            X(EGL_LEVEL),
            X(EGL_MAX_PBUFFER_HEIGHT),
            X(EGL_MAX_PBUFFER_PIXELS),
            X(EGL_MAX_PBUFFER_WIDTH),
            X(EGL_NATIVE_RENDERABLE),
            X(EGL_NATIVE_VISUAL_ID),
            X(EGL_NATIVE_VISUAL_TYPE),
            X(EGL_SAMPLES),
            X(EGL_SAMPLE_BUFFERS),
            X(EGL_SURFACE_TYPE),
            X(EGL_TRANSPARENT_TYPE),
            X(EGL_TRANSPARENT_RED_VALUE),
            X(EGL_TRANSPARENT_GREEN_VALUE),
            X(EGL_TRANSPARENT_BLUE_VALUE),
            X(EGL_BIND_TO_TEXTURE_RGB),
            X(EGL_BIND_TO_TEXTURE_RGBA),
            X(EGL_MIN_SWAP_INTERVAL),
            X(EGL_MAX_SWAP_INTERVAL),
            X(EGL_LUMINANCE_SIZE),
            X(EGL_ALPHA_MASK_SIZE),
            X(EGL_COLOR_BUFFER_TYPE),
            X(EGL_RENDERABLE_TYPE),
            X(EGL_CONFORMANT),
    };
#undef X

    String8 msg;
    for (size_t j = 0; j < sizeof(names) / sizeof(names[0]); j++) {
        EGLint value = -1;
        EGLint returnVal = eglGetConfigAttrib(dpy, config, names[j].attribute, &value);
        EGLint error = eglGetError();
        if (returnVal && error == EGL_SUCCESS) {
            msg.appendFormat(" %s: %d (0x%x)", names[j].name, value, value);
        }
    }
    msg.append("\n");
    return msg;
}

bool EGLUtils::printEGLConfigurations(EGLDisplay dpy, String8& msg) {
    EGLint numConfig = 0;
    EGLint returnVal = eglGetConfigs(dpy, NULL, 0, &numConfig);
    msg.append(checkEglError("eglGetConfigs", returnVal));
    if (!returnVal) {
        return false;
    }

    msg.appendFormat("Number of EGL configuration: %d\n", numConfig);

    std::vector<EGLConfig> configs(numConfig);

    returnVal = eglGetConfigs(dpy, configs.data(), numConfig, &numConfig);
    msg.append(checkEglError("eglGetConfigs", returnVal));
    if (!returnVal) {
        return false;
    }

    for (int i = 0; i < numConfig; i++) {
        msg.appendFormat("Configuration %d\n", i);
        msg.append(printEGLConfiguration(dpy, configs[i]));
    }

    return true;
}

bool EGLUtils::printEGLConfigurations(FILE* output, EGLDisplay dpy) {
    String8 msg;
    bool status = printEGLConfigurations(dpy, msg);
    fprintf(output, "%s", msg.c_str());
    return status;
}

String8 EGLUtils::decodeColorSpace(EGLint colorSpace) {
    switch (colorSpace) {
        case EGL_GL_COLORSPACE_SRGB_KHR:
            return String8("EGL_GL_COLORSPACE_SRGB_KHR");
        case EGL_GL_COLORSPACE_DISPLAY_P3_EXT:
            return String8("EGL_GL_COLORSPACE_DISPLAY_P3_EXT");
        case  EGL_GL_COLORSPACE_LINEAR_KHR:
            return String8("EGL_GL_COLORSPACE_LINEAR_KHR");
        default:
            return String8::format("UNKNOWN ColorSpace %d", colorSpace);
    }
}

bool EGLUtils::hasExtension(const char* exts, const char* name) {
    size_t nameLen = strlen(name);
    if (exts) {
        for (const char* match = strstr(exts, name); match; match = strstr(match + nameLen, name)) {
            if (match[nameLen] == '\0' || match[nameLen] == ' ') {
                return true;
            }
        }
    }
    return false;
}

bool EGLUtils::hasEglExtension(EGLDisplay dpy, const char* name) {
    return hasExtension(eglQueryString(dpy, EGL_EXTENSIONS), name);
}

// ----------------------------------------------------------------------------
}; // namespace android
// ----------------------------------------------------------------------------