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

Commit 7773c435 authored by Mathias Agopian's avatar Mathias Agopian
Browse files

EGLConfig is now not remaped to an internal EGLConfig

this is possible now that we support only a single
EGL implementation. this allows a large code simplification.

Change-Id: I7a6b9db4c5d60f4407c6061e7a68729af63d5242
parent ada798b7
Loading
Loading
Loading
Loading
+3 −3
Original line number Diff line number Diff line
@@ -198,7 +198,7 @@ void Loader::init_api(void* dso,
        __eglMustCastToProperFunctionPointerType* curr, 
        getProcAddressType getProcAddress) 
{
    const size_t SIZE = 256;
    const ssize_t SIZE = 256;
    char scrap[SIZE];
    while (*api) {
        char const * name = *api;
@@ -303,14 +303,14 @@ void *Loader::load_driver(const char* kind, const char *tag,
    if (mask & GLESv1_CM) {
        init_api(dso, gl_names,
            (__eglMustCastToProperFunctionPointerType*)
                &cnx->hooks[GLESv1_INDEX]->gl,
                &cnx->hooks[egl_connection_t::GLESv1_INDEX]->gl,
            getProcAddress);
    }

    if (mask & GLESv2) {
      init_api(dso, gl_names,
            (__eglMustCastToProperFunctionPointerType*)
                &cnx->hooks[GLESv2_INDEX]->gl,
                &cnx->hooks[egl_connection_t::GLESv2_INDEX]->gl,
            getProcAddress);
    }
    
+5 −6
Original line number Diff line number Diff line
@@ -187,15 +187,12 @@ egl_display_t* validate_display(EGLDisplay dpy) {
    return dp;
}

egl_connection_t* validate_display_config(EGLDisplay dpy, EGLConfig config,
egl_connection_t* validate_display_config(EGLDisplay dpy, EGLConfig,
        egl_display_t const*& dp) {
    dp = validate_display(dpy);
    if (!dp)
        return (egl_connection_t*) NULL;

    if (intptr_t(config) >= dp->numTotalConfigs) {
        return setError(EGL_BAD_CONFIG, (egl_connection_t*)NULL);
    }
    egl_connection_t* const cnx = &gEGLImpl;
    if (cnx->dso == 0) {
        return setError(EGL_BAD_CONFIG, (egl_connection_t*)NULL);
@@ -269,8 +266,10 @@ static EGLBoolean egl_init_drivers_locked() {
    // dynamically load our EGL implementation
    egl_connection_t* cnx = &gEGLImpl;
    if (cnx->dso == 0) {
        cnx->hooks[GLESv1_INDEX] = &gHooks[GLESv1_INDEX];
        cnx->hooks[GLESv2_INDEX] = &gHooks[GLESv2_INDEX];
        cnx->hooks[egl_connection_t::GLESv1_INDEX] =
                &gHooks[egl_connection_t::GLESv1_INDEX];
        cnx->hooks[egl_connection_t::GLESv2_INDEX] =
                &gHooks[egl_connection_t::GLESv2_INDEX];
        cnx->dso = loader.open(cnx);
    }

+28 −166
Original line number Diff line number Diff line
@@ -89,24 +89,6 @@ static void(*findProcAddress(const char* name,

// ----------------------------------------------------------------------------

template<typename T>
static __attribute__((noinline))
int binarySearch(T const sortedArray[], int first, int last, T key) {
    while (first <= last) {
        int mid = (first + last) / 2;
        if (sortedArray[mid] < key) {
            first = mid + 1;
        } else if (key < sortedArray[mid]) {
            last = mid - 1;
        } else {
            return mid;
        }
    }
    return -1;
}

// ----------------------------------------------------------------------------

namespace android {
extern void setGLHooksThreadSpecific(gl_hooks_t const *value);
extern EGLBoolean egl_init_drivers();
@@ -184,21 +166,20 @@ EGLBoolean eglGetConfigs( EGLDisplay dpy,
    egl_display_t const * const dp = validate_display(dpy);
    if (!dp) return EGL_FALSE;

    GLint numConfigs = dp->numTotalConfigs;
    if (!configs) {
        *num_config = numConfigs;
        return EGL_TRUE;
    if (num_config==0) {
        return setError(EGL_BAD_PARAMETER, EGL_FALSE);
    }

    GLint n = 0;
    for (intptr_t i=0 ; i<dp->numTotalConfigs && config_size ; i++) {
        *configs++ = EGLConfig(i);
        config_size--;
        n++;
    EGLBoolean res = EGL_FALSE;
    *num_config = 0;

    egl_connection_t* const cnx = &gEGLImpl;
    if (cnx->dso) {
        res = cnx->egl.eglGetConfigs(
                dp->disp.dpy, configs, config_size, num_config);
    }

    *num_config = n;
    return EGL_TRUE;
    return res;
}

EGLBoolean eglChooseConfig( EGLDisplay dpy, const EGLint *attrib_list,
@@ -214,105 +195,14 @@ EGLBoolean eglChooseConfig( EGLDisplay dpy, const EGLint *attrib_list,
        return setError(EGL_BAD_PARAMETER, EGL_FALSE);
    }

    EGLint n;
    EGLBoolean res = EGL_FALSE;
    *num_config = 0;

    
    // It is unfortunate, but we need to remap the EGL_CONFIG_IDs, 
    // to do this, we have to go through the attrib_list array once
    // to figure out both its size and if it contains an EGL_CONFIG_ID
    // key. If so, the full array is copied and patched.
    // NOTE: we assume that there can be only one occurrence
    // of EGL_CONFIG_ID.
    
    EGLint patch_index = -1;
    GLint attr;
    size_t size = 0;
    if (attrib_list) {
        while ((attr=attrib_list[size]) != EGL_NONE) {
            if (attr == EGL_CONFIG_ID)
                patch_index = size;
            size += 2;
        }
    }
    if (patch_index >= 0) {
        size += 2; // we need copy the sentinel as well
        EGLint* new_list = (EGLint*)malloc(size*sizeof(EGLint));
        if (new_list == 0)
            return setError(EGL_BAD_ALLOC, EGL_FALSE);
        memcpy(new_list, attrib_list, size*sizeof(EGLint));

        // patch the requested EGL_CONFIG_ID
        bool found = false;
        EGLConfig ourConfig(0);
        EGLint& configId(new_list[patch_index+1]);
        for (intptr_t i=0 ; i<dp->numTotalConfigs ; i++) {
            if (dp->configs[i].configId == configId) {
                ourConfig = EGLConfig(i);
                configId = dp->configs[i].implConfigId;
                found = true;
                break;
            }
        }

        egl_connection_t* const cnx = &gEGLImpl;
        if (found && cnx->dso) {
            // and switch to the new list
            attrib_list = const_cast<const EGLint *>(new_list);

            // At this point, the only configuration that can match is
            // dp->configs[i][index], however, we don't know if it would be
            // rejected because of the other attributes, so we do have to call
            // cnx->egl.eglChooseConfig() -- but we don't have to loop
            // through all the EGLimpl[].
            // We also know we can only get a single config back, and we know
            // which one.

            res = cnx->egl.eglChooseConfig(
                    dp->disp.dpy,
                    attrib_list, configs, config_size, &n);
            if (res && n>0) {
                // n has to be 0 or 1, by construction, and we already know
                // which config it will return (since there can be only one).
                if (configs) {
                    configs[0] = ourConfig;
                }
                *num_config = 1;
            }
        }

        free(const_cast<EGLint *>(attrib_list));
        return res;
    }


    egl_connection_t* const cnx = &gEGLImpl;
    if (cnx->dso) {
        if (cnx->egl.eglChooseConfig(
                dp->disp.dpy, attrib_list, configs, config_size, &n)) {
            if (configs) {
                // now we need to convert these client EGLConfig to our
                // internal EGLConfig format.
                // This is done in O(n Log(n)) time.
                for (int j=0 ; j<n ; j++) {
                    egl_config_t key(configs[j]);
                    intptr_t index = binarySearch<egl_config_t>(
                            dp->configs, 0, dp->numTotalConfigs, key);
                    if (index >= 0) {
                        configs[j] = EGLConfig(index);
                    } else {
                        return setError(EGL_BAD_CONFIG, EGL_FALSE);
                    }
                }
                configs += n;
                config_size -= n;
            }
            *num_config += n;
            res = EGL_TRUE;
        }
        res = cnx->egl.eglChooseConfig(
                dp->disp.dpy, attrib_list, configs, config_size, num_config);
    }

    return res;
}

@@ -325,13 +215,8 @@ EGLBoolean eglGetConfigAttrib(EGLDisplay dpy, EGLConfig config,
    egl_connection_t* cnx = validate_display_config(dpy, config, dp);
    if (!cnx) return EGL_FALSE;
    
    if (attribute == EGL_CONFIG_ID) {
        *value = dp->configs[intptr_t(config)].configId;
        return EGL_TRUE;
    }
    return cnx->egl.eglGetConfigAttrib(
            dp->disp.dpy,
            dp->configs[intptr_t(config)].config, attribute, value);
            dp->disp.dpy, config, attribute, value);
}

// ----------------------------------------------------------------------------
@@ -348,7 +233,6 @@ EGLSurface eglCreateWindowSurface( EGLDisplay dpy, EGLConfig config,
    egl_connection_t* cnx = validate_display_config(dpy, config, dp);
    if (cnx) {
        EGLDisplay iDpy = dp->disp.dpy;
        EGLConfig iConfig = dp->configs[intptr_t(config)].config;
        EGLint format;

        if (native_window_api_connect(window, NATIVE_WINDOW_API_EGL) != OK) {
@@ -359,7 +243,7 @@ EGLSurface eglCreateWindowSurface( EGLDisplay dpy, EGLConfig config,

        // set the native window's buffers format to match this config
        if (cnx->egl.eglGetConfigAttrib(iDpy,
                iConfig, EGL_NATIVE_VISUAL_ID, &format)) {
                config, EGL_NATIVE_VISUAL_ID, &format)) {
            if (format != 0) {
                int err = native_window_set_buffers_format(window, format);
                if (err != 0) {
@@ -377,7 +261,7 @@ EGLSurface eglCreateWindowSurface( EGLDisplay dpy, EGLConfig config,
        anw->setSwapInterval(anw, 1);

        EGLSurface surface = cnx->egl.eglCreateWindowSurface(
                iDpy, iConfig, window, attrib_list);
                iDpy, config, window, attrib_list);
        if (surface != EGL_NO_SURFACE) {
            egl_surface_t* s = new egl_surface_t(dpy, config, window, surface, cnx);
            return s;
@@ -400,8 +284,7 @@ EGLSurface eglCreatePixmapSurface( EGLDisplay dpy, EGLConfig config,
    egl_connection_t* cnx = validate_display_config(dpy, config, dp);
    if (cnx) {
        EGLSurface surface = cnx->egl.eglCreatePixmapSurface(
                dp->disp.dpy,
                dp->configs[intptr_t(config)].config, pixmap, attrib_list);
                dp->disp.dpy, config, pixmap, attrib_list);
        if (surface != EGL_NO_SURFACE) {
            egl_surface_t* s = new egl_surface_t(dpy, config, NULL, surface, cnx);
            return s;
@@ -419,8 +302,7 @@ EGLSurface eglCreatePbufferSurface( EGLDisplay dpy, EGLConfig config,
    egl_connection_t* cnx = validate_display_config(dpy, config, dp);
    if (cnx) {
        EGLSurface surface = cnx->egl.eglCreatePbufferSurface(
                dp->disp.dpy,
                dp->configs[intptr_t(config)].config, attrib_list);
                dp->disp.dpy, config, attrib_list);
        if (surface != EGL_NO_SURFACE) {
            egl_surface_t* s = new egl_surface_t(dpy, config, NULL, surface, cnx);
            return s;
@@ -461,18 +343,10 @@ EGLBoolean eglQuerySurface( EGLDisplay dpy, EGLSurface surface,
        return setError(EGL_BAD_SURFACE, EGL_FALSE);

    egl_surface_t const * const s = get_surface(surface);
    EGLBoolean result(EGL_TRUE);
    if (attribute == EGL_CONFIG_ID) {
        // We need to remap EGL_CONFIG_IDs
        *value = dp->configs[intptr_t(s->config)].configId;
    } else {
        result = s->cnx->egl.eglQuerySurface(
    return s->cnx->egl.eglQuerySurface(
            dp->disp.dpy, s->surface, attribute, value);
}

    return result;
}

void EGLAPI eglBeginFrame(EGLDisplay dpy, EGLSurface surface) {
    clearError();

@@ -510,9 +384,7 @@ EGLContext eglCreateContext(EGLDisplay dpy, EGLConfig config,
            share_list = c->context;
        }
        EGLContext context = cnx->egl.eglCreateContext(
                dp->disp.dpy,
                dp->configs[intptr_t(config)].config,
                share_list, attrib_list);
                dp->disp.dpy, config, share_list, attrib_list);
        if (context != EGL_NO_CONTEXT) {
            // figure out if it's a GLESv1 or GLESv2
            int version = 0;
@@ -522,9 +394,9 @@ EGLContext eglCreateContext(EGLDisplay dpy, EGLConfig config,
                    GLint value = *attrib_list++;
                    if (attr == EGL_CONTEXT_CLIENT_VERSION) {
                        if (value == 1) {
                            version = GLESv1_INDEX;
                            version = egl_connection_t::GLESv1_INDEX;
                        } else if (value == 2) {
                            version = GLESv2_INDEX;
                            version = egl_connection_t::GLESv2_INDEX;
                        }
                    }
                };
@@ -668,17 +540,9 @@ EGLBoolean eglQueryContext( EGLDisplay dpy, EGLContext ctx,
    if (!_c.get()) return setError(EGL_BAD_CONTEXT, EGL_FALSE);

    egl_context_t * const c = get_context(ctx);

    EGLBoolean result(EGL_TRUE);
    if (attribute == EGL_CONFIG_ID) {
        *value = dp->configs[intptr_t(c->config)].configId;
    } else {
        // We need to remap EGL_CONFIG_IDs
        result = c->cnx->egl.eglQueryContext(
    return c->cnx->egl.eglQueryContext(
            dp->disp.dpy, c->context, attribute, value);
    }

    return result;
}

EGLContext eglGetCurrentContext(void)
@@ -849,8 +713,8 @@ __eglMustCastToProperFunctionPointerType eglGetProcAddress(const char *procname)
            if (cnx->dso && cnx->egl.eglGetProcAddress) {
                found = true;
                // Extensions are independent of the bound context
                cnx->hooks[GLESv1_INDEX]->ext.extensions[slot] =
                cnx->hooks[GLESv2_INDEX]->ext.extensions[slot] =
                cnx->hooks[egl_connection_t::GLESv1_INDEX]->ext.extensions[slot] =
                cnx->hooks[egl_connection_t::GLESv2_INDEX]->ext.extensions[slot] =
#if EGL_TRACE
                debugHooks->ext.extensions[slot] =
                gHooksTrace.ext.extensions[slot] =
@@ -1105,9 +969,7 @@ EGLSurface eglCreatePbufferFromClientBuffer(
    if (!cnx) return EGL_FALSE;
    if (cnx->egl.eglCreatePbufferFromClientBuffer) {
        return cnx->egl.eglCreatePbufferFromClientBuffer(
                dp->disp.dpy,
                buftype, buffer,
                dp->configs[intptr_t(config)].config, attrib_list);
                dp->disp.dpy, buftype, buffer, config, attrib_list);
    }
    return setError(EGL_BAD_CONFIG, EGL_NO_SURFACE);
}
+8 −56
Original line number Diff line number Diff line
@@ -60,18 +60,12 @@ static char const * const sExtensionString =
extern void initEglTraceLevel();
extern void setGLHooksThreadSpecific(gl_hooks_t const *value);

static int cmp_configs(const void* a, const void *b) {
    const egl_config_t& c0 = *(egl_config_t const *)a;
    const egl_config_t& c1 = *(egl_config_t const *)b;
    return c0<c1 ? -1 : (c1<c0 ? 1 : 0);
}

// ----------------------------------------------------------------------------

egl_display_t egl_display_t::sDisplay[NUM_DISPLAYS];

egl_display_t::egl_display_t() :
    magic('_dpy'), numTotalConfigs(0), configs(0), refs(0) {
    magic('_dpy'), refs(0) {
}

egl_display_t::~egl_display_t() {
@@ -207,7 +201,7 @@ EGLBoolean egl_display_t::initialize(EGLint *major, EGLint *minor) {
    mVersionString.setTo(sVersionString);
    mClientApiString.setTo(sClientApiString);

    // we only add extensions that exist in at least one implementation
    // we only add extensions that exist in the implementation
    char const* start = sExtensionString;
    char const* end;
    do {
@@ -236,39 +230,6 @@ EGLBoolean egl_display_t::initialize(EGLint *major, EGLint *minor) {

    egl_cache_t::get()->initialize(this);

    EGLBoolean res = EGL_FALSE;
    if (cnx->dso && cnx->major >= 0 && cnx->minor >= 0) {
        EGLint n;
        if (cnx->egl.eglGetConfigs(disp.dpy, 0, 0, &n)) {
            disp.config = (EGLConfig*) malloc(sizeof(EGLConfig) * n);
            if (disp.config) {
                if (cnx->egl.eglGetConfigs(disp.dpy, disp.config, n,
                        &disp.numConfigs)) {
                    numTotalConfigs += n;
                    res = EGL_TRUE;
                }
            }
        }
    }

    if (res == EGL_TRUE) {
        configs = new egl_config_t[numTotalConfigs];
        int k = 0;
        egl_connection_t* const cnx = &gEGLImpl;
        if (cnx->dso && cnx->major >= 0 && cnx->minor >= 0) {
            for (int j = 0; j < disp.numConfigs; j++) {
                configs[k].config = disp.config[j];
                configs[k].configId = k + 1; // CONFIG_ID start at 1
                // store the implementation's CONFIG_ID
                cnx->egl.eglGetConfigAttrib(disp.dpy, disp.config[j],
                        EGL_CONFIG_ID, &configs[k].implConfigId);
                k++;
            }
        }

        // sort our configurations so we can do binary-searches
        qsort(configs, numTotalConfigs, sizeof(egl_config_t), cmp_configs);

    refs++;
    if (major != NULL)
        *major = VERSION_MAJOR;
@@ -276,8 +237,6 @@ EGLBoolean egl_display_t::initialize(EGLint *major, EGLint *minor) {
        *minor = VERSION_MINOR;
    return EGL_TRUE;
}
    return setError(EGL_NOT_INITIALIZED, EGL_FALSE);
}

EGLBoolean egl_display_t::terminate() {

@@ -301,12 +260,7 @@ EGLBoolean egl_display_t::terminate() {
                    egl_tls_t::egl_strerror(cnx->egl.eglGetError()));
        }
        // REVISIT: it's unclear what to do if eglTerminate() fails
        free(disp.config);

        disp.numConfigs = 0;
        disp.config = 0;
        disp.state = egl_display_t::TERMINATED;

        res = EGL_TRUE;
    }

@@ -324,8 +278,6 @@ EGLBoolean egl_display_t::terminate() {
    objects.clear();

    refs--;
    numTotalConfigs = 0;
    delete[] configs;
    return res;
}

+1 −20
Original line number Diff line number Diff line
@@ -44,20 +44,6 @@ class egl_connection_t;

// ----------------------------------------------------------------------------

struct egl_config_t {
    egl_config_t() {}
    egl_config_t(EGLConfig config)
        : config(config), configId(0), implConfigId(0) { }
    EGLConfig   config;         // the implementation's EGLConfig
    EGLint      configId;       // our CONFIG_ID
    EGLint      implConfigId;   // the implementation's CONFIG_ID
    inline bool operator < (const egl_config_t& rhs) const {
        return config < rhs.config;
    }
};

// ----------------------------------------------------------------------------

class EGLAPI egl_display_t { // marked as EGLAPI for testing purposes
    static egl_display_t sDisplay[NUM_DISPLAYS];
    EGLDisplay getDisplay(EGLNativeDisplayType display);
@@ -110,12 +96,9 @@ public:
    };

    struct DisplayImpl {
        DisplayImpl() : dpy(EGL_NO_DISPLAY), config(0),
                        state(NOT_INITIALIZED), numConfigs(0) { }
        DisplayImpl() : dpy(EGL_NO_DISPLAY), state(NOT_INITIALIZED) { }
        EGLDisplay  dpy;
        EGLConfig*  config;
        EGLint      state;
        EGLint      numConfigs;
        strings_t   queryString;
    };

@@ -124,8 +107,6 @@ private:

public:
    DisplayImpl     disp;
    EGLint          numTotalConfigs;
    egl_config_t*   configs;

private:
            uint32_t                    refs;
Loading