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

Commit 45af43a5 authored by TreeHugger Robot's avatar TreeHugger Robot Committed by Android (Google) Code Review
Browse files

Merge changes I8972c9dd,I38a8a055,Ic92e717a

* changes:
  Add EGL_KHR_no_config_context extension header info
  Add test for 10:10:10:2 support in EGL
  Apply and Track EGL_GL_COLORSPACE_KHR
parents 1388edb8 f372c1ff
Loading
Loading
Loading
Loading
+5 −0
Original line number Diff line number Diff line
@@ -625,6 +625,11 @@ typedef EGLClientBuffer (EGLAPIENTRYP PFNEGLGETNATIVECLIENTBUFFERANDROID) (const
#define EGL_MUTABLE_RENDER_BUFFER_BIT_KHR 0x1000
#endif

#ifndef EGL_KHR_no_config_context
#define EGL_KHR_no_config_context 1
#define EGL_NO_CONFIG_KHR                 EGL_CAST(EGLConfig,0)
#endif /* EGL_KHR_no_config_context */

#ifndef EGL_ANDROID_get_frame_timestamps
#define EGL_ANDROID_get_frame_timestamps 1
#define EGL_TIMESTAMPS_ANDROID 0x3430
+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 {
+93 −26
Original line number Diff line number Diff line
@@ -28,18 +28,17 @@
#include <gui/IGraphicBufferConsumer.h>
#include <gui/BufferQueue.h>

#define PIXEL_FORMAT_FLOAT "EGL_EXT_pixel_format_float"

bool hasEglPixelFormatFloat() {
    EGLDisplay dpy = eglGetDisplay(EGL_DEFAULT_DISPLAY);
bool hasEglExtension(EGLDisplay dpy, const char* extensionName) {
    const char* exts = eglQueryString(dpy, EGL_EXTENSIONS);
    size_t cropExtLen = strlen(PIXEL_FORMAT_FLOAT);
    size_t cropExtLen = strlen(extensionName);
    size_t extsLen = strlen(exts);
    bool equal = !strcmp(PIXEL_FORMAT_FLOAT, exts);
    bool atStart = !strncmp(PIXEL_FORMAT_FLOAT " ", exts, cropExtLen + 1);
    bool equal = !strcmp(extensionName, exts);
    android::String8 extString(extensionName);
    android::String8 space(" ");
    bool atStart = !strncmp(extString + space, exts, cropExtLen + 1);
    bool atEnd = (cropExtLen + 1) < extsLen &&
            !strcmp(" " PIXEL_FORMAT_FLOAT, exts + extsLen - (cropExtLen + 1));
    bool inMiddle = strstr(exts, " " PIXEL_FORMAT_FLOAT " ");
            !strcmp(space + extString, exts + extsLen - (cropExtLen + 1));
    bool inMiddle = strstr(exts, space + extString + space);
    return equal || atStart || atEnd || inMiddle;
}

@@ -203,23 +202,20 @@ TEST_F(EGLTest, EGLConfigFP16) {
        return;
    }

    ASSERT_TRUE(hasEglPixelFormatFloat());

    EGLint attrs[] = {EGL_SURFACE_TYPE,
                      EGL_WINDOW_BIT,
                      EGL_RENDERABLE_TYPE,
                      EGL_OPENGL_ES2_BIT,
                      EGL_RED_SIZE,
                      16,
                      EGL_GREEN_SIZE,
                      16,
                      EGL_BLUE_SIZE,
                      16,
                      EGL_ALPHA_SIZE,
                      16,
                      EGL_COLOR_COMPONENT_TYPE_EXT,
                      EGL_COLOR_COMPONENT_TYPE_FLOAT_EXT,
                      EGL_NONE};
    ASSERT_TRUE(hasEglExtension(mEglDisplay, "EGL_EXT_pixel_format_float"));

    EGLint attrs[] = {
            // clang-format off
            EGL_SURFACE_TYPE,             EGL_WINDOW_BIT,
            EGL_RENDERABLE_TYPE,          EGL_OPENGL_ES2_BIT,
            EGL_RED_SIZE,                 16,
            EGL_GREEN_SIZE,               16,
            EGL_BLUE_SIZE,                16,
            EGL_ALPHA_SIZE,               16,
            EGL_COLOR_COMPONENT_TYPE_EXT, EGL_COLOR_COMPONENT_TYPE_FLOAT_EXT,
            EGL_NONE,                     EGL_NONE
            // clang-format on
    };
    success = eglChooseConfig(mEglDisplay, attrs, &config, 1, &numConfigs);
    ASSERT_EQ(EGL_UNSIGNED_TRUE, success);
    ASSERT_EQ(1, numConfigs);
@@ -250,6 +246,77 @@ TEST_F(EGLTest, EGLConfigFP16) {
        void onSidebandStreamChanged() override {}
    };

    sp<IGraphicBufferProducer> producer;
    sp<IGraphicBufferConsumer> consumer;
    BufferQueue::createBufferQueue(&producer, &consumer);
    consumer->consumerConnect(new DummyConsumer, false);
    sp<Surface> mSTC = new Surface(producer);
    sp<ANativeWindow> mANW = mSTC;

    EGLSurface eglSurface = eglCreateWindowSurface(mEglDisplay, config, mANW.get(), NULL);
    ASSERT_EQ(EGL_SUCCESS, eglGetError());
    ASSERT_NE(EGL_NO_SURFACE, eglSurface);

    EXPECT_TRUE(eglDestroySurface(mEglDisplay, eglSurface));
}

// Emulate what a native application would do to create a
// 10:10:10:2 surface.
TEST_F(EGLTest, EGLConfig1010102) {
    EGLint numConfigs;
    EGLConfig config;
    EGLBoolean success;

    if (!hasWideColorDisplay) {
        // skip this test if device does not have wide-color display
        return;
    }

    EGLint attrs[] = {
            // clang-format off
            EGL_SURFACE_TYPE,             EGL_WINDOW_BIT,
            EGL_RENDERABLE_TYPE,          EGL_OPENGL_ES2_BIT,
            EGL_SURFACE_TYPE,             EGL_WINDOW_BIT | EGL_PBUFFER_BIT,
            EGL_RED_SIZE,                 10,
            EGL_GREEN_SIZE,               10,
            EGL_BLUE_SIZE,                10,
            EGL_ALPHA_SIZE,               2,
            EGL_COLOR_COMPONENT_TYPE_EXT, EGL_COLOR_COMPONENT_TYPE_FIXED_EXT,
            EGL_NONE,                     EGL_NONE
            // clang-format on
    };
    success = eglChooseConfig(mEglDisplay, attrs, &config, 1, &numConfigs);
    ASSERT_EQ(EGL_UNSIGNED_TRUE, success);
    ASSERT_EQ(1, numConfigs);

    EGLint components[4];
    EGLint value;
    eglGetConfigAttrib(mEglDisplay, config, EGL_CONFIG_ID, &value);

    success = eglGetConfigAttrib(mEglDisplay, config, EGL_RED_SIZE, &components[0]);
    ASSERT_EQ(EGL_UNSIGNED_TRUE, success);
    ASSERT_EQ(EGL_SUCCESS, eglGetError());
    success = eglGetConfigAttrib(mEglDisplay, config, EGL_GREEN_SIZE, &components[1]);
    ASSERT_EQ(EGL_UNSIGNED_TRUE, success);
    ASSERT_EQ(EGL_SUCCESS, eglGetError());
    success = eglGetConfigAttrib(mEglDisplay, config, EGL_BLUE_SIZE, &components[2]);
    ASSERT_EQ(EGL_UNSIGNED_TRUE, success);
    ASSERT_EQ(EGL_SUCCESS, eglGetError());
    success = eglGetConfigAttrib(mEglDisplay, config, EGL_ALPHA_SIZE, &components[3]);
    ASSERT_EQ(EGL_UNSIGNED_TRUE, success);
    ASSERT_EQ(EGL_SUCCESS, eglGetError());

    EXPECT_EQ(components[0], 10);
    EXPECT_EQ(components[1], 10);
    EXPECT_EQ(components[2], 10);
    EXPECT_EQ(components[3], 2);

    struct DummyConsumer : public BnConsumerListener {
        void onFrameAvailable(const BufferItem& /* item */) override {}
        void onBuffersReleased() override {}
        void onSidebandStreamChanged() override {}
    };

    // Create a EGLSurface
    sp<IGraphicBufferProducer> producer;
    sp<IGraphicBufferConsumer> consumer;
Loading