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

Commit a2208d67 authored by Courtney Goeltzenleuchter's avatar Courtney Goeltzenleuchter Committed by Android (Google) Code Review
Browse files

Merge "Add HDR dataspaces to EGL"

parents 7ce38ef0 12ffe096
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.