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

Commit 12ffe096 authored by Courtney Goeltzenleuchter's avatar Courtney Goeltzenleuchter
Browse files

Add HDR dataspaces to EGL

bug: 63710530
Test: adb shell /data/nativetest/EGL_test/EGL_test
Test: adb -d shell am start -n \
      com.drawelements.deqp/android.app.NativeActivity \
      -e cmdLine '"deqp --deqp-case=dEQP-EGL.functional.hdr_color.* \
      --deqp-log-filename=/sdcard/dEQP-Log.qpa"'
Change-Id: I52c43539806c901c674f037489d502d771080a30
parent 47f36ab4
Loading
Loading
Loading
Loading
+99 −24
Original line number Diff line number Diff line
@@ -468,12 +468,17 @@ static android_dataspace modifyBufferDataspace(android_dataspace dataSpace,
        return HAL_DATASPACE_V0_SCRGB;
    } else if (colorspace == EGL_GL_COLORSPACE_SCRGB_LINEAR_EXT) {
        return HAL_DATASPACE_V0_SCRGB_LINEAR;
    } else if (colorspace == EGL_GL_COLORSPACE_BT2020_LINEAR_EXT) {
        return HAL_DATASPACE_BT2020_LINEAR;
    } else if (colorspace == EGL_GL_COLORSPACE_BT2020_PQ_EXT) {
        return HAL_DATASPACE_BT2020_PQ;
    }
    return dataSpace;
}

// Return true if we stripped any EGL_GL_COLORSPACE_KHR attributes.
static EGLBoolean stripColorSpaceAttribute(egl_display_ptr dp, const EGLint* attrib_list,
// Return true if we stripped any EGL_GL_COLORSPACE_KHR or HDR metadata attributes.
// Protect devices from attributes they don't recognize that are  managed by Android
static EGLBoolean stripAttributes(egl_display_ptr dp, const EGLint* attrib_list,
                                           EGLint format,
                                           std::vector<EGLint>& stripped_attrib_list) {
    std::vector<EGLint> allowedColorSpaces;
@@ -494,10 +499,12 @@ static EGLBoolean stripColorSpaceAttribute(egl_display_ptr dp, const EGLint* att
            break;
    }

    if (!attrib_list) return false;

    bool stripped = false;
    if (attrib_list && dp->haveExtension("EGL_KHR_gl_colorspace")) {
    for (const EGLint* attr = attrib_list; attr[0] != EGL_NONE; attr += 2) {
            if (attr[0] == EGL_GL_COLORSPACE_KHR) {
        switch (attr[0]) {
            case EGL_GL_COLORSPACE_KHR: {
                    EGLint colorSpace = attr[1];
                    bool found = false;
                    // Verify that color space is allowed
@@ -506,21 +513,50 @@ static EGLBoolean stripColorSpaceAttribute(egl_display_ptr dp, const EGLint* att
                            found = true;
                        }
                    }
                if (!found) {
                    if (found && dp->haveExtension("EGL_KHR_gl_colorspace")) {
                        stripped = true;
                    } else {
                        stripped_attrib_list.push_back(attr[0]);
                        stripped_attrib_list.push_back(attr[1]);
                    }
                }
                break;
            case EGL_SMPTE2086_DISPLAY_PRIMARY_RX_EXT:
            case EGL_SMPTE2086_DISPLAY_PRIMARY_RY_EXT:
            case EGL_SMPTE2086_DISPLAY_PRIMARY_GX_EXT:
            case EGL_SMPTE2086_DISPLAY_PRIMARY_GY_EXT:
            case EGL_SMPTE2086_DISPLAY_PRIMARY_BX_EXT:
            case EGL_SMPTE2086_DISPLAY_PRIMARY_BY_EXT:
            case EGL_SMPTE2086_WHITE_POINT_X_EXT:
            case EGL_SMPTE2086_WHITE_POINT_Y_EXT:
            case EGL_SMPTE2086_MAX_LUMINANCE_EXT:
            case EGL_SMPTE2086_MIN_LUMINANCE_EXT:
                if (dp->haveExtension("EGL_EXT_surface_SMPTE2086_metadata")) {
                    stripped = true;
                } else {
                    stripped_attrib_list.push_back(attr[0]);
                    stripped_attrib_list.push_back(attr[1]);
                }
                break;
            case EGL_CTA861_3_MAX_CONTENT_LIGHT_LEVEL_EXT:
            case EGL_CTA861_3_MAX_FRAME_AVERAGE_LEVEL_EXT:
                if (dp->haveExtension("EGL_EXT_surface_CTA861_3_metadata")) {
                    stripped = true;
                } else {
                    stripped_attrib_list.push_back(attr[0]);
                    stripped_attrib_list.push_back(attr[1]);
                }
                break;
            default:
                stripped_attrib_list.push_back(attr[0]);
                stripped_attrib_list.push_back(attr[1]);
                break;
        }
    }

    // Make sure there is at least one attribute
    if (stripped) {
        stripped_attrib_list.push_back(EGL_NONE);
        stripped_attrib_list.push_back(EGL_NONE);
    }
    return stripped;
}
@@ -544,10 +580,10 @@ static EGLBoolean getColorSpaceAttribute(egl_display_ptr dp, NativeWindowType wi
                    // is available, so no need to verify.
                    found = true;
                    verify = false;
                } else if (colorSpace == EGL_EXT_gl_colorspace_bt2020_linear &&
                } else if (colorSpace == EGL_GL_COLORSPACE_BT2020_LINEAR_EXT &&
                           dp->haveExtension("EGL_EXT_gl_colorspace_bt2020_linear")) {
                    found = true;
                } else if (colorSpace == EGL_EXT_gl_colorspace_bt2020_pq &&
                } else if (colorSpace == EGL_GL_COLORSPACE_BT2020_PQ_EXT &&
                           dp->haveExtension("EGL_EXT_gl_colorspace_bt2020_pq")) {
                    found = true;
                } else if (colorSpace == EGL_GL_COLORSPACE_SCRGB_EXT &&
@@ -664,10 +700,43 @@ void getNativePixelFormat(EGLDisplay dpy, egl_connection_t* cnx, EGLConfig confi
    }
}

EGLBoolean setSurfaceMetadata(egl_surface_t* s, NativeWindowType window,
                              const EGLint *attrib_list) {
    // set any HDR metadata
    bool smpte2086 = false;
    bool cta8613 = false;
    if (attrib_list == nullptr) return EGL_TRUE;

    for (const EGLint* attr = attrib_list; attr[0] != EGL_NONE; attr += 2) {
        smpte2086 |= s->setSmpte2086Attribute(attr[0], attr[1]);
        cta8613 |= s->setCta8613Attribute(attr[0], attr[1]);
    }
    if (smpte2086) {
        int err = native_window_set_buffers_smpte2086_metadata(window, s->getSmpte2086Metadata());
        if (err != 0) {
            ALOGE("error setting native window smpte2086 metadata: %s (%d)",
                  strerror(-err), err);
            native_window_api_disconnect(window, NATIVE_WINDOW_API_EGL);
            return EGL_FALSE;
        }
    }
    if (cta8613) {
        int err = native_window_set_buffers_cta861_3_metadata(window, s->getCta8613Metadata());
        if (err != 0) {
            ALOGE("error setting native window CTS 861.3 metadata: %s (%d)",
                  strerror(-err), err);
            native_window_api_disconnect(window, NATIVE_WINDOW_API_EGL);
            return EGL_FALSE;
        }
    }
    return EGL_TRUE;
}

EGLSurface eglCreateWindowSurface(  EGLDisplay dpy, EGLConfig config,
                                    NativeWindowType window,
                                    const EGLint *attrib_list)
{
    const EGLint *origAttribList = attrib_list;
    clearError();

    egl_connection_t* cnx = NULL;
@@ -705,7 +774,7 @@ EGLSurface eglCreateWindowSurface( EGLDisplay dpy, EGLConfig config,
        }

        std::vector<EGLint> strippedAttribList;
        if (stripColorSpaceAttribute(dp, attrib_list, format, strippedAttribList)) {
        if (stripAttributes(dp, attrib_list, format, strippedAttribList)) {
            // Had to modify the attribute list due to use of color space.
            // Use modified list from here on.
            attrib_list = strippedAttribList.data();
@@ -741,8 +810,12 @@ EGLSurface eglCreateWindowSurface( EGLDisplay dpy, EGLConfig config,
        if (surface != EGL_NO_SURFACE) {
            egl_surface_t* s =
                    new egl_surface_t(dp.get(), config, window, surface, colorSpace, cnx);

            if (setSurfaceMetadata(s, window, origAttribList)) {
                return s;
            }
            eglDestroySurface(dpy, s);
        }

        // EGLSurface creation failed
        native_window_set_buffers_format(window, 0);
@@ -802,7 +875,7 @@ EGLSurface eglCreatePbufferSurface( EGLDisplay dpy, EGLConfig config,
        // colorspace. We do need to filter out color spaces the
        // driver doesn't know how to process.
        std::vector<EGLint> strippedAttribList;
        if (stripColorSpaceAttribute(dp, attrib_list, format, strippedAttribList)) {
        if (stripAttributes(dp, attrib_list, format, strippedAttribList)) {
            // Had to modify the attribute list due to use of color space.
            // Use modified list from here on.
            attrib_list = strippedAttribList.data();
@@ -850,12 +923,14 @@ 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();
    if (s->getColorSpaceAttribute(attribute, value)) {
        return EGL_TRUE;
    } else if (s->getSmpte2086Attribute(attribute, value)) {
        return EGL_TRUE;
    } else if (s->getCta8613Attribute(attribute, value)) {
        return EGL_TRUE;
    }
    return s->cnx->egl.eglQuerySurface(
            dp->disp.dpy, s->surface, attribute, value);
    return s->cnx->egl.eglQuerySurface(dp->disp.dpy, s->surface, attribute, value);
}

void EGLAPI eglBeginFrame(EGLDisplay dpy, EGLSurface surface) {
+17 −0
Original line number Diff line number Diff line
@@ -214,6 +214,23 @@ EGLBoolean egl_display_t::initialize(EGLint *major, EGLint *minor) {
                    "EGL_EXT_gl_colorspace_display_p3_linear EGL_EXT_gl_colorspace_display_p3 ");
        }

        bool hasHdrBoardConfig =
                getBool<ISurfaceFlingerConfigs, &ISurfaceFlingerConfigs::hasHDRDisplay>(false);

        if (hasHdrBoardConfig) {
            // hasHDRBoardConfig indicates the system is capable of supporting HDR content.
            // Typically that means there is an HDR capable display attached, but could be
            // support for attaching an HDR display. In either case, advertise support for
            // HDR color spaces.
            mExtensionString.append(
                    "EGL_EXT_gl_colorspace_bt2020_linear EGL_EXT_gl_colorspace_bt2020_pq ");
        }

        // Always advertise HDR metadata extensions since it's okay for an application
        // to specify such information even though it may not be used by the system.
        mExtensionString.append(
                "EGL_EXT_surface_SMPTE2086_metadata EGL_EXT_surface_CTA861_3_metadata ");

        char const* start = gExtensionString;
        do {
            // length of the extension name
+120 −1
Original line number Diff line number Diff line
@@ -63,7 +63,9 @@ egl_surface_t::egl_surface_t(egl_display_t* dpy, EGLConfig config, EGLNativeWind
        win(win),
        cnx(cnx),
        connected(true),
        colorSpace(colorSpace) {
        colorSpace(colorSpace),
        smpte2086_metadata({}),
        cta861_3_metadata({}) {
    if (win) {
        win->incStrong(this);
    }
@@ -86,6 +88,123 @@ void egl_surface_t::disconnect() {
    }
}

EGLBoolean egl_surface_t::setSmpte2086Attribute(EGLint attribute, EGLint value) {
    switch (attribute) {
            break;
        case EGL_SMPTE2086_DISPLAY_PRIMARY_RX_EXT:
            smpte2086_metadata.displayPrimaryRed.x = value;
            return EGL_TRUE;
        case EGL_SMPTE2086_DISPLAY_PRIMARY_RY_EXT:
            smpte2086_metadata.displayPrimaryRed.y = value;
            return EGL_TRUE;
        case EGL_SMPTE2086_DISPLAY_PRIMARY_GX_EXT:
            smpte2086_metadata.displayPrimaryGreen.x = value;
            return EGL_TRUE;
        case EGL_SMPTE2086_DISPLAY_PRIMARY_GY_EXT:
            smpte2086_metadata.displayPrimaryGreen.y = value;
            return EGL_TRUE;
        case EGL_SMPTE2086_DISPLAY_PRIMARY_BX_EXT:
            smpte2086_metadata.displayPrimaryBlue.x = value;
            return EGL_TRUE;
        case EGL_SMPTE2086_DISPLAY_PRIMARY_BY_EXT:
            smpte2086_metadata.displayPrimaryBlue.y = value;
            return EGL_TRUE;
        case EGL_SMPTE2086_WHITE_POINT_X_EXT:
            smpte2086_metadata.whitePoint.x = value;
            return EGL_TRUE;
        case EGL_SMPTE2086_WHITE_POINT_Y_EXT:
            smpte2086_metadata.whitePoint.y = value;
            return EGL_TRUE;
        case EGL_SMPTE2086_MAX_LUMINANCE_EXT:
            smpte2086_metadata.maxLuminance = value;
            return EGL_TRUE;
        case EGL_SMPTE2086_MIN_LUMINANCE_EXT:
            smpte2086_metadata.minLuminance = value;
            return EGL_TRUE;
    }
    return EGL_FALSE;
}

EGLBoolean egl_surface_t::setCta8613Attribute(EGLint attribute, EGLint value) {
    switch (attribute) {
        case EGL_CTA861_3_MAX_CONTENT_LIGHT_LEVEL_EXT:
            cta861_3_metadata.maxContentLightLevel = value;
            return EGL_TRUE;
        case EGL_CTA861_3_MAX_FRAME_AVERAGE_LEVEL_EXT:
            cta861_3_metadata.maxFrameAverageLightLevel = value;
            return EGL_TRUE;
    }
    return EGL_FALSE;
}

EGLBoolean egl_surface_t::getColorSpaceAttribute(EGLint attribute, EGLint* value) const {
    if (attribute == EGL_GL_COLORSPACE_KHR) {
        *value = colorSpace;
        return EGL_TRUE;
    }
    return EGL_FALSE;
}

EGLBoolean egl_surface_t::getSmpte2086Attribute(EGLint attribute, EGLint *value) const {
    switch (attribute) {
        case EGL_SMPTE2086_DISPLAY_PRIMARY_RX_EXT:
            *value = *reinterpret_cast<const int*>(&smpte2086_metadata.displayPrimaryRed.x);
            return EGL_TRUE;
            break;
        case EGL_SMPTE2086_DISPLAY_PRIMARY_RY_EXT:
            *value = *reinterpret_cast<const int*>(&smpte2086_metadata.displayPrimaryRed.y);
            return EGL_TRUE;
            break;
        case EGL_SMPTE2086_DISPLAY_PRIMARY_GX_EXT:
            *value = *reinterpret_cast<const int*>(&smpte2086_metadata.displayPrimaryGreen.x);
            return EGL_TRUE;
            break;
        case EGL_SMPTE2086_DISPLAY_PRIMARY_GY_EXT:
            *value = *reinterpret_cast<const int*>(&smpte2086_metadata.displayPrimaryGreen.y);
            return EGL_TRUE;
            break;
        case EGL_SMPTE2086_DISPLAY_PRIMARY_BX_EXT:
            *value = *reinterpret_cast<const int*>(&smpte2086_metadata.displayPrimaryBlue.x);
            return EGL_TRUE;
            break;
        case EGL_SMPTE2086_DISPLAY_PRIMARY_BY_EXT:
            *value = *reinterpret_cast<const int*>(&smpte2086_metadata.displayPrimaryBlue.y);
            return EGL_TRUE;
            break;
        case EGL_SMPTE2086_WHITE_POINT_X_EXT:
            *value = *reinterpret_cast<const int*>(&smpte2086_metadata.whitePoint.x);
            return EGL_TRUE;
            break;
        case EGL_SMPTE2086_WHITE_POINT_Y_EXT:
            *value = *reinterpret_cast<const int*>(&smpte2086_metadata.whitePoint.y);
            return EGL_TRUE;
            break;
        case EGL_SMPTE2086_MAX_LUMINANCE_EXT:
            *value = *reinterpret_cast<const int*>(&smpte2086_metadata.maxLuminance);
            return EGL_TRUE;
            break;
        case EGL_SMPTE2086_MIN_LUMINANCE_EXT:
            *value = *reinterpret_cast<const int*>(&smpte2086_metadata.minLuminance);
            return EGL_TRUE;
            break;
    }
    return EGL_FALSE;
}

EGLBoolean egl_surface_t::getCta8613Attribute(EGLint attribute, EGLint *value) const {
    switch (attribute) {
        case EGL_CTA861_3_MAX_CONTENT_LIGHT_LEVEL_EXT:
            *value = *reinterpret_cast<const int*>(&cta861_3_metadata.maxContentLightLevel);
            return EGL_TRUE;
            break;
        case EGL_CTA861_3_MAX_FRAME_AVERAGE_LEVEL_EXT:
            *value = *reinterpret_cast<const int*>(&cta861_3_metadata.maxFrameAverageLightLevel);
            return EGL_TRUE;
            break;
    }
    return EGL_FALSE;
}

void egl_surface_t::terminate() {
    disconnect();
    egl_object_t::terminate();
+9 −0
Original line number Diff line number Diff line
@@ -137,6 +137,13 @@ public:
    ANativeWindow* getNativeWindow() { return win; }
    ANativeWindow* getNativeWindow() const { return win; }
    EGLint getColorSpace() const { return colorSpace; }
    EGLBoolean setSmpte2086Attribute(EGLint attribute, EGLint value);
    EGLBoolean setCta8613Attribute(EGLint attribute, EGLint value);
    EGLBoolean getColorSpaceAttribute(EGLint attribute, EGLint* value) const;
    EGLBoolean getSmpte2086Attribute(EGLint attribute, EGLint* value) const;
    EGLBoolean getCta8613Attribute(EGLint attribute, EGLint* value) const;
    const android_smpte2086_metadata* getSmpte2086Metadata() const { return &smpte2086_metadata; }
    const android_cta861_3_metadata* getCta8613Metadata() const { return &cta861_3_metadata; }

    // 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.
@@ -150,6 +157,8 @@ private:
    bool connected;
    void disconnect();
    EGLint colorSpace;
    android_smpte2086_metadata smpte2086_metadata;
    android_cta861_3_metadata cta861_3_metadata;
};

class egl_context_t: public egl_object_t {
+274 −6

File changed.

Preview size limit exceeded, changes collapsed.