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

Commit 49db2b17 authored by Yiwei Zhang's avatar Yiwei Zhang Committed by Gerrit Code Review
Browse files

Merge "EGL: two fixes for colorspace attribute handling"

parents 9d0d9ee8 ab4f07e3
Loading
Loading
Loading
Loading
+45 −55
Original line number Original line Diff line number Diff line
@@ -482,33 +482,17 @@ static EGLint getReportedColorSpace(EGLint colorspace) {
}
}


// Returns a list of color spaces understood by the vendor EGL driver.
// Returns a list of color spaces understood by the vendor EGL driver.
static std::vector<EGLint> getDriverColorSpaces(egl_display_ptr dp,
static std::vector<EGLint> getDriverColorSpaces(egl_display_ptr dp) {
                                                android_pixel_format format) {
    std::vector<EGLint> colorSpaces;
    std::vector<EGLint> colorSpaces;
    if (!dp->hasColorSpaceSupport) return colorSpaces;


    // OpenGL drivers only support sRGB encoding with 8-bit formats.
    // RGB_888 is never returned by getNativePixelFormat, but is included for completeness.
    const bool formatSupportsSRGBEncoding =
        format == HAL_PIXEL_FORMAT_RGBA_8888 || format == HAL_PIXEL_FORMAT_RGBX_8888 ||
        format == HAL_PIXEL_FORMAT_RGB_888;
    const bool formatIsFloatingPoint = format == HAL_PIXEL_FORMAT_RGBA_FP16;

    if (formatSupportsSRGBEncoding) {
    // sRGB and linear are always supported when color space support is present.
    // sRGB and linear are always supported when color space support is present.
    colorSpaces.push_back(EGL_GL_COLORSPACE_SRGB_KHR);
    colorSpaces.push_back(EGL_GL_COLORSPACE_SRGB_KHR);
    colorSpaces.push_back(EGL_GL_COLORSPACE_LINEAR_KHR);
    colorSpaces.push_back(EGL_GL_COLORSPACE_LINEAR_KHR);
        // DCI-P3 uses the sRGB transfer function, so it's only relevant for 8-bit formats.

    if (findExtension(dp->disp.queryString.extensions,
    if (findExtension(dp->disp.queryString.extensions,
                      "EGL_EXT_gl_colorspace_display_p3")) {
                      "EGL_EXT_gl_colorspace_display_p3")) {
        colorSpaces.push_back(EGL_GL_COLORSPACE_DISPLAY_P3_EXT);
        colorSpaces.push_back(EGL_GL_COLORSPACE_DISPLAY_P3_EXT);
    }
    }
    }

    // According to the spec, scRGB is only supported for floating point formats.
    // For non-linear scRGB, the application is responsible for applying the
    // transfer function.
    if (formatIsFloatingPoint) {
    if (findExtension(dp->disp.queryString.extensions,
    if (findExtension(dp->disp.queryString.extensions,
                      "EGL_EXT_gl_colorspace_scrgb")) {
                      "EGL_EXT_gl_colorspace_scrgb")) {
        colorSpaces.push_back(EGL_GL_COLORSPACE_SCRGB_EXT);
        colorSpaces.push_back(EGL_GL_COLORSPACE_SCRGB_EXT);
@@ -517,10 +501,6 @@ static std::vector<EGLint> getDriverColorSpaces(egl_display_ptr dp,
                      "EGL_EXT_gl_colorspace_scrgb_linear")) {
                      "EGL_EXT_gl_colorspace_scrgb_linear")) {
        colorSpaces.push_back(EGL_GL_COLORSPACE_SCRGB_LINEAR_EXT);
        colorSpaces.push_back(EGL_GL_COLORSPACE_SCRGB_LINEAR_EXT);
    }
    }
    }

    // BT2020 can be used with any pixel format. PQ encoding must be applied by the
    // application and does not affect the behavior of OpenGL.
    if (findExtension(dp->disp.queryString.extensions,
    if (findExtension(dp->disp.queryString.extensions,
                      "EGL_EXT_gl_colorspace_bt2020_linear")) {
                      "EGL_EXT_gl_colorspace_bt2020_linear")) {
        colorSpaces.push_back(EGL_GL_COLORSPACE_BT2020_LINEAR_EXT);
        colorSpaces.push_back(EGL_GL_COLORSPACE_BT2020_LINEAR_EXT);
@@ -529,9 +509,6 @@ static std::vector<EGLint> getDriverColorSpaces(egl_display_ptr dp,
                      "EGL_EXT_gl_colorspace_bt2020_pq")) {
                      "EGL_EXT_gl_colorspace_bt2020_pq")) {
        colorSpaces.push_back(EGL_GL_COLORSPACE_BT2020_PQ_EXT);
        colorSpaces.push_back(EGL_GL_COLORSPACE_BT2020_PQ_EXT);
    }
    }

    // Linear DCI-P3 simply uses different primaries than standard RGB and thus
    // can be used with any pixel format.
    if (findExtension(dp->disp.queryString.extensions,
    if (findExtension(dp->disp.queryString.extensions,
                      "EGL_EXT_gl_colorspace_display_p3_linear")) {
                      "EGL_EXT_gl_colorspace_display_p3_linear")) {
        colorSpaces.push_back(EGL_GL_COLORSPACE_DISPLAY_P3_LINEAR_EXT);
        colorSpaces.push_back(EGL_GL_COLORSPACE_DISPLAY_P3_LINEAR_EXT);
@@ -543,19 +520,32 @@ static std::vector<EGLint> getDriverColorSpaces(egl_display_ptr dp,
// If there is no color space attribute in attrib_list, colorSpace is left
// If there is no color space attribute in attrib_list, colorSpace is left
// unmodified.
// unmodified.
static EGLBoolean processAttributes(egl_display_ptr dp, NativeWindowType window,
static EGLBoolean processAttributes(egl_display_ptr dp, NativeWindowType window,
                                    android_pixel_format format, const EGLint* attrib_list,
                                    const EGLint* attrib_list, EGLint* colorSpace,
                                    EGLint* colorSpace,
                                    std::vector<EGLint>* strippedAttribList) {
                                    std::vector<EGLint>* strippedAttribList) {
    for (const EGLint* attr = attrib_list; attr && attr[0] != EGL_NONE; attr += 2) {
    for (const EGLint* attr = attrib_list; attr && attr[0] != EGL_NONE; attr += 2) {
        bool copyAttribute = true;
        bool copyAttribute = true;
        if (attr[0] == EGL_GL_COLORSPACE_KHR) {
        if (attr[0] == EGL_GL_COLORSPACE_KHR) {
            switch (attr[1]) {
                case EGL_GL_COLORSPACE_LINEAR_KHR:
                case EGL_GL_COLORSPACE_SRGB_KHR:
                case EGL_GL_COLORSPACE_DISPLAY_P3_EXT:
                case EGL_GL_COLORSPACE_SCRGB_LINEAR_EXT:
                case EGL_GL_COLORSPACE_SCRGB_EXT:
                case EGL_GL_COLORSPACE_BT2020_LINEAR_EXT:
                case EGL_GL_COLORSPACE_BT2020_PQ_EXT:
                case EGL_GL_COLORSPACE_DISPLAY_P3_LINEAR_EXT:
                    // Fail immediately if the driver doesn't have color space support at all.
                    // Fail immediately if the driver doesn't have color space support at all.
            if (!dp->hasColorSpaceSupport) return false;
                    if (!dp->hasColorSpaceSupport) return setError(EGL_BAD_ATTRIBUTE, EGL_FALSE);
                    break;
                default:
                    // BAD_ATTRIBUTE if attr is not any of the EGL_GL_COLORSPACE_*
                    return setError(EGL_BAD_ATTRIBUTE, EGL_FALSE);
            }
            *colorSpace = attr[1];
            *colorSpace = attr[1];


            // Strip the attribute if the driver doesn't understand it.
            // Strip the attribute if the driver doesn't understand it.
            copyAttribute = false;
            copyAttribute = false;
            std::vector<EGLint> driverColorSpaces = getDriverColorSpaces(dp, format);
            std::vector<EGLint> driverColorSpaces = getDriverColorSpaces(dp);
            for (auto driverColorSpace : driverColorSpaces) {
            for (auto driverColorSpace : driverColorSpaces) {
                if (attr[1] == driverColorSpace) {
                if (attr[1] == driverColorSpace) {
                    copyAttribute = true;
                    copyAttribute = true;
@@ -603,12 +593,12 @@ static EGLBoolean processAttributes(egl_display_ptr dp, NativeWindowType window,
            ALOGE("processAttributes: invalid window (win=%p) "
            ALOGE("processAttributes: invalid window (win=%p) "
                  "failed (%#x) (already connected to another API?)",
                  "failed (%#x) (already connected to another API?)",
                  window, err);
                  window, err);
            return false;
            return setError(EGL_BAD_NATIVE_WINDOW, EGL_FALSE);
        }
        }
        if (!windowSupportsWideColor) {
        if (!windowSupportsWideColor) {
            // Application has asked for a wide-color colorspace but
            // Application has asked for a wide-color colorspace but
            // wide-color support isn't available on the display the window is on.
            // wide-color support isn't available on the display the window is on.
            return false;
            return setError(EGL_BAD_MATCH, EGL_FALSE);
        }
        }
    }
    }
    return true;
    return true;
@@ -736,10 +726,10 @@ EGLSurface eglCreateWindowSurface( EGLDisplay dpy, EGLConfig config,
        // now select correct colorspace and dataspace based on user's attribute list
        // now select correct colorspace and dataspace based on user's attribute list
        EGLint colorSpace = EGL_UNKNOWN;
        EGLint colorSpace = EGL_UNKNOWN;
        std::vector<EGLint> strippedAttribList;
        std::vector<EGLint> strippedAttribList;
        if (!processAttributes(dp, window, format, attrib_list, &colorSpace,
        if (!processAttributes(dp, window, attrib_list, &colorSpace,
                               &strippedAttribList)) {
                               &strippedAttribList)) {
            ALOGE("error invalid colorspace: %d", colorSpace);
            ALOGE("error invalid colorspace: %d", colorSpace);
            return setError(EGL_BAD_ATTRIBUTE, EGL_NO_SURFACE);
            return EGL_NO_SURFACE;
        }
        }
        attrib_list = strippedAttribList.data();
        attrib_list = strippedAttribList.data();


@@ -801,10 +791,10 @@ EGLSurface eglCreatePixmapSurface( EGLDisplay dpy, EGLConfig config,
        // now select a corresponding sRGB format if needed
        // now select a corresponding sRGB format if needed
        EGLint colorSpace = EGL_UNKNOWN;
        EGLint colorSpace = EGL_UNKNOWN;
        std::vector<EGLint> strippedAttribList;
        std::vector<EGLint> strippedAttribList;
        if (!processAttributes(dp, nullptr, format, attrib_list, &colorSpace,
        if (!processAttributes(dp, nullptr, attrib_list, &colorSpace,
                               &strippedAttribList)) {
                               &strippedAttribList)) {
            ALOGE("error invalid colorspace: %d", colorSpace);
            ALOGE("error invalid colorspace: %d", colorSpace);
            return setError(EGL_BAD_ATTRIBUTE, EGL_NO_SURFACE);
            return EGL_NO_SURFACE;
        }
        }
        attrib_list = strippedAttribList.data();
        attrib_list = strippedAttribList.data();


@@ -835,10 +825,10 @@ EGLSurface eglCreatePbufferSurface( EGLDisplay dpy, EGLConfig config,
        // Select correct colorspace based on user's attribute list
        // Select correct colorspace based on user's attribute list
        EGLint colorSpace = EGL_UNKNOWN;
        EGLint colorSpace = EGL_UNKNOWN;
        std::vector<EGLint> strippedAttribList;
        std::vector<EGLint> strippedAttribList;
        if (!processAttributes(dp, nullptr, format, attrib_list, &colorSpace,
        if (!processAttributes(dp, nullptr, attrib_list, &colorSpace,
                               &strippedAttribList)) {
                               &strippedAttribList)) {
            ALOGE("error invalid colorspace: %d", colorSpace);
            ALOGE("error invalid colorspace: %d", colorSpace);
            return setError(EGL_BAD_ATTRIBUTE, EGL_NO_SURFACE);
            return EGL_NO_SURFACE;
        }
        }
        attrib_list = strippedAttribList.data();
        attrib_list = strippedAttribList.data();