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

Commit 37836571 authored by Courtney Goeltzenleuchter's avatar Courtney Goeltzenleuchter
Browse files

Apply and Track EGL_GL_COLORSPACE_KHR

As part of implementing EGL_KHR_gl_colorspace we need to
keep track of the EGL_GL_COLORSPACE_KHR so that eqlQuerySurface
gets the value the application set.
Do the work in the EGL layer because colorspace information
is not handled in the driver.
Test: adb shell /data/nativetest/EGL_test/EGL_test
Bug: 37709988

Change-Id: Ic92e717a46769144d724f4a84fb3560df076da4f
parent c9c0075b
Loading
Loading
Loading
Loading
+79 −15
Original line number Diff line number Diff line
@@ -473,6 +473,45 @@ static android_dataspace modifyBufferDataspace( android_dataspace dataSpace,
    return dataSpace;
}

static EGLBoolean getColorSpaceAttribute(egl_display_ptr dp, const EGLint* attrib_list,
                                         EGLint& colorSpace, android_dataspace& dataSpace) {
    colorSpace = EGL_GL_COLORSPACE_LINEAR_KHR;
    dataSpace = HAL_DATASPACE_UNKNOWN;
    if (attrib_list && dp->haveExtension("EGL_KHR_gl_colorspace")) {
        for (const EGLint* attr = attrib_list; *attr != EGL_NONE; attr += 2) {
            if (*attr == EGL_GL_COLORSPACE_KHR) {
                colorSpace = attr[1];
                bool found = false;
                // Verify that color space is allowed
                if (colorSpace == EGL_GL_COLORSPACE_SRGB_KHR ||
                    colorSpace == EGL_GL_COLORSPACE_LINEAR_KHR) {
                    found = true;
                } else if (colorSpace == EGL_EXT_gl_colorspace_bt2020_linear &&
                           dp->haveExtension("EGL_EXT_gl_colorspace_bt2020_linear")) {
                    found = true;
                } else if (colorSpace == EGL_EXT_gl_colorspace_bt2020_pq &&
                           dp->haveExtension("EGL_EXT_gl_colorspace_bt2020_pq")) {
                    found = true;
                } else if (colorSpace == EGL_GL_COLORSPACE_SCRGB_LINEAR_EXT &&
                           dp->haveExtension("EGL_EXT_gl_colorspace_scrgb_linear")) {
                    found = true;
                } else if (colorSpace == EGL_GL_COLORSPACE_DISPLAY_P3_LINEAR_EXT &&
                           dp->haveExtension("EGL_EXT_gl_colorspace_display_p3_linear")) {
                    found = true;
                } else if (colorSpace == EGL_GL_COLORSPACE_DISPLAY_P3_EXT &&
                           dp->haveExtension("EGL_EXT_gl_colorspace_display_p3")) {
                    found = true;
                }
                if (!found) {
                    return false;
                }
            }
        }
        dataSpace = modifyBufferDataspace(dataSpace, colorSpace);
    }
    return true;
}

EGLSurface eglCreateWindowSurface(  EGLDisplay dpy, EGLConfig config,
                                    NativeWindowType window,
                                    const EGLint *attrib_list)
@@ -513,7 +552,8 @@ EGLSurface eglCreateWindowSurface( EGLDisplay dpy, EGLConfig config,
                                    &componentType);

        EGLint format;
        android_dataspace dataSpace = HAL_DATASPACE_UNKNOWN;
        EGLint colorSpace;
        android_dataspace dataSpace;
        EGLint a = 0;
        EGLint r, g, b;
        r = g = b = 0;
@@ -550,12 +590,9 @@ EGLSurface eglCreateWindowSurface( EGLDisplay dpy, EGLConfig config,
        }

        // now select a corresponding sRGB format if needed
        if (attrib_list && dp->haveExtension("EGL_KHR_gl_colorspace")) {
            for (const EGLint* attr = attrib_list; *attr != EGL_NONE; attr += 2) {
                if (*attr == EGL_GL_COLORSPACE_KHR) {
                    dataSpace = modifyBufferDataspace(dataSpace, *(attr+1));
                }
            }
        if (!getColorSpaceAttribute(dp, attrib_list, colorSpace, dataSpace)) {
            ALOGE("error invalid colorspace: %d", colorSpace);
            return setError(EGL_BAD_ATTRIBUTE, EGL_NO_SURFACE);
        }

        if (format != 0) {
@@ -586,8 +623,8 @@ EGLSurface eglCreateWindowSurface( EGLDisplay dpy, EGLConfig config,
        EGLSurface surface = cnx->egl.eglCreateWindowSurface(
                iDpy, config, window, attrib_list);
        if (surface != EGL_NO_SURFACE) {
            egl_surface_t* s = new egl_surface_t(dp.get(), config, window,
                    surface, cnx);
            egl_surface_t* s =
                    new egl_surface_t(dp.get(), config, window, surface, colorSpace, cnx);
            return s;
        }

@@ -606,12 +643,19 @@ EGLSurface eglCreatePixmapSurface( EGLDisplay dpy, EGLConfig config,

    egl_connection_t* cnx = NULL;
    egl_display_ptr dp = validate_display_connection(dpy, cnx);
    EGLint colorSpace;
    android_dataspace dataSpace;
    if (dp) {
        // now select a corresponding sRGB format if needed
        if (!getColorSpaceAttribute(dp, attrib_list, colorSpace, dataSpace)) {
            ALOGE("error invalid colorspace: %d", colorSpace);
            return setError(EGL_BAD_ATTRIBUTE, EGL_NO_SURFACE);
        }

        EGLSurface surface = cnx->egl.eglCreatePixmapSurface(
                dp->disp.dpy, config, pixmap, attrib_list);
        if (surface != EGL_NO_SURFACE) {
            egl_surface_t* s = new egl_surface_t(dp.get(), config, NULL,
                    surface, cnx);
            egl_surface_t* s = new egl_surface_t(dp.get(), config, NULL, surface, colorSpace, cnx);
            return s;
        }
    }
@@ -625,12 +669,19 @@ EGLSurface eglCreatePbufferSurface( EGLDisplay dpy, EGLConfig config,

    egl_connection_t* cnx = NULL;
    egl_display_ptr dp = validate_display_connection(dpy, cnx);
    EGLint colorSpace;
    android_dataspace dataSpace;
    if (dp) {
        // now select a corresponding sRGB format if needed
        if (!getColorSpaceAttribute(dp, attrib_list, colorSpace, dataSpace)) {
            ALOGE("error invalid colorspace: %d", colorSpace);
            return setError(EGL_BAD_ATTRIBUTE, EGL_NO_SURFACE);
        }

        EGLSurface surface = cnx->egl.eglCreatePbufferSurface(
                dp->disp.dpy, config, attrib_list);
        if (surface != EGL_NO_SURFACE) {
            egl_surface_t* s = new egl_surface_t(dp.get(), config, NULL,
                    surface, cnx);
            egl_surface_t* s = new egl_surface_t(dp.get(), config, NULL, surface, colorSpace, cnx);
            return s;
        }
    }
@@ -669,6 +720,10 @@ EGLBoolean eglQuerySurface( EGLDisplay dpy, EGLSurface surface,
        return setError(EGL_BAD_SURFACE, (EGLBoolean)EGL_FALSE);

    egl_surface_t const * const s = get_surface(surface);
    if (attribute == EGL_GL_COLORSPACE_KHR) {
        *value = s->getColorSpace();
        return EGL_TRUE;
    }
    return s->cnx->egl.eglQuerySurface(
            dp->disp.dpy, s->surface, attribute, value);
}
@@ -1708,13 +1763,22 @@ EGLSurface eglCreateStreamProducerSurfaceKHR(EGLDisplay dpy, EGLConfig config,
    egl_display_ptr dp = validate_display(dpy);
    if (!dp) return EGL_NO_SURFACE;

    EGLint colorSpace = EGL_GL_COLORSPACE_LINEAR_KHR;
    android_dataspace dataSpace = HAL_DATASPACE_UNKNOWN;
    // TODO: Probably need to update EGL_KHR_stream_producer_eglsurface to
    // indicate support for EGL_GL_COLORSPACE_KHR.
    // now select a corresponding sRGB format if needed
    if (!getColorSpaceAttribute(dp, attrib_list, colorSpace, dataSpace)) {
        ALOGE("error invalid colorspace: %d", colorSpace);
        return setError(EGL_BAD_ATTRIBUTE, EGL_NO_SURFACE);
    }

    egl_connection_t* const cnx = &gEGLImpl;
    if (cnx->dso && cnx->egl.eglCreateStreamProducerSurfaceKHR) {
        EGLSurface surface = cnx->egl.eglCreateStreamProducerSurfaceKHR(
                dp->disp.dpy, config, stream, attrib_list);
        if (surface != EGL_NO_SURFACE) {
            egl_surface_t* s = new egl_surface_t(dp.get(), config, NULL,
                    surface, cnx);
            egl_surface_t* s = new egl_surface_t(dp.get(), config, NULL, surface, colorSpace, cnx);
            return s;
        }
    }
+9 −6
Original line number Diff line number Diff line
@@ -55,12 +55,15 @@ bool egl_object_t::get(egl_display_t const* display, egl_object_t* object) {

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

egl_surface_t::egl_surface_t(egl_display_t* dpy, EGLConfig config,
        EGLNativeWindowType win, EGLSurface surface,
        egl_connection_t const* cnx) :
    egl_object_t(dpy), surface(surface), config(config), win(win), cnx(cnx),
    connected(true)
{
egl_surface_t::egl_surface_t(egl_display_t* dpy, EGLConfig config, EGLNativeWindowType win,
                             EGLSurface surface, EGLint colorSpace, egl_connection_t const* cnx)
      : egl_object_t(dpy),
        surface(surface),
        config(config),
        win(win),
        cnx(cnx),
        connected(true),
        colorSpace(colorSpace) {
    if (win) {
        win->incStrong(this);
    }
+4 −3
Original line number Diff line number Diff line
@@ -131,12 +131,12 @@ protected:
public:
    typedef egl_object_t::LocalRef<egl_surface_t, EGLSurface> Ref;

    egl_surface_t(egl_display_t* dpy, EGLConfig config,
            EGLNativeWindowType win, EGLSurface surface,
            egl_connection_t const* cnx);
    egl_surface_t(egl_display_t* dpy, EGLConfig config, EGLNativeWindowType win, EGLSurface surface,
                  EGLint colorSpace, egl_connection_t const* cnx);

    ANativeWindow* getNativeWindow() { return win; }
    ANativeWindow* getNativeWindow() const { return win; }
    EGLint getColorSpace() const { return colorSpace; }

    // Try to keep the order of these fields and size unchanged. It's not public API, but
    // it's not hard to imagine native games accessing them.
@@ -149,6 +149,7 @@ public:
private:
    bool connected;
    void disconnect();
    EGLint colorSpace;
};

class egl_context_t: public egl_object_t {