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

Commit fb530cf2 authored by Peiyong Lin's avatar Peiyong Lin
Browse files

Revert "Revert "[SurfaceFlinger] Add GPU protected content support.""

This reverts commit 78fb96f3.
Reason for revert: Revert the revert with Fix.

BUG: 35315015
Test: Test with a hacked patch.
Test: Watch Youtube movie, verifed by force GPU composition.
Change-Id: Ic738b5f873dbff322473d4f999074dc35c8813c7
parent 7bd483a2
Loading
Loading
Loading
Loading
+96 −18
Original line number Diff line number Diff line
@@ -242,23 +242,43 @@ std::unique_ptr<GLESRenderEngine> GLESRenderEngine::create(int hwcFormat, uint32

    bool useContextPriority = extensions.hasContextPriority() &&
            (featureFlags & RenderEngine::USE_HIGH_PRIORITY_CONTEXT);
    EGLContext ctxt = createEglContext(display, config, EGL_NO_CONTEXT, useContextPriority);
    EGLContext protectedContext = EGL_NO_CONTEXT;
    if (extensions.hasProtectedContent()) {
        protectedContext = createEglContext(display, config, nullptr, useContextPriority,
                                            Protection::PROTECTED);
        ALOGE_IF(protectedContext == EGL_NO_CONTEXT, "Can't create protected context");
    }

    EGLContext ctxt = createEglContext(display, config, protectedContext, useContextPriority,
                                       Protection::UNPROTECTED);

    // if can't create a GL context, we can only abort.
    LOG_ALWAYS_FATAL_IF(ctxt == EGL_NO_CONTEXT, "EGLContext creation failed");

    EGLSurface dummy = EGL_NO_SURFACE;
    if (!extensions.hasSurfacelessContext()) {
        dummy = createDummyEglPbufferSurface(display, config, hwcFormat);
        dummy = createDummyEglPbufferSurface(display, config, hwcFormat, Protection::UNPROTECTED);
        LOG_ALWAYS_FATAL_IF(dummy == EGL_NO_SURFACE, "can't create dummy pbuffer");
    }

    EGLBoolean success = eglMakeCurrent(display, dummy, dummy, ctxt);
    LOG_ALWAYS_FATAL_IF(!success, "can't make dummy pbuffer current");

    extensions.initWithGLStrings(glGetString(GL_VENDOR), glGetString(GL_RENDERER),
                                 glGetString(GL_VERSION), glGetString(GL_EXTENSIONS));

    // In order to have protected contents in GPU composition, the OpenGL ES extension
    // GL_EXT_protected_textures must be supported. If it's not supported, reset
    // protected context to EGL_NO_CONTEXT to indicate that protected contents is not supported.
    if (!extensions.hasProtectedTexture()) {
        protectedContext = EGL_NO_CONTEXT;
    }

    EGLSurface protectedDummy = EGL_NO_SURFACE;
    if (protectedContext != EGL_NO_CONTEXT && !extensions.hasSurfacelessContext()) {
        protectedDummy =
                createDummyEglPbufferSurface(display, config, hwcFormat, Protection::PROTECTED);
        ALOGE_IF(protectedDummy == EGL_NO_SURFACE, "can't create protected dummy pbuffer");
    }

    // now figure out what version of GL did we actually get
    GlesVersion version = parseGlesVersion(extensions.getVersion());

@@ -271,7 +291,8 @@ std::unique_ptr<GLESRenderEngine> GLESRenderEngine::create(int hwcFormat, uint32
            break;
        case GLES_VERSION_2_0:
        case GLES_VERSION_3_0:
            engine = std::make_unique<GLESRenderEngine>(featureFlags, display, config, ctxt, dummy);
            engine = std::make_unique<GLESRenderEngine>(featureFlags, display, config, ctxt, dummy,
                                                        protectedContext, protectedDummy);
            break;
    }

@@ -326,12 +347,15 @@ EGLConfig GLESRenderEngine::chooseEglConfig(EGLDisplay display, int format, bool
}

GLESRenderEngine::GLESRenderEngine(uint32_t featureFlags, EGLDisplay display, EGLConfig config,
                                   EGLContext ctxt, EGLSurface dummy)
                                   EGLContext ctxt, EGLSurface dummy, EGLContext protectedContext,
                                   EGLSurface protectedDummy)
      : renderengine::impl::RenderEngine(featureFlags),
        mEGLDisplay(display),
        mEGLConfig(config),
        mEGLContext(ctxt),
        mDummySurface(dummy),
        mProtectedEGLContext(protectedContext),
        mProtectedDummySurface(protectedDummy),
        mVpWidth(0),
        mVpHeight(0),
        mUseColorManagement(featureFlags & USE_COLOR_MANAGEMENT) {
@@ -341,6 +365,17 @@ GLESRenderEngine::GLESRenderEngine(uint32_t featureFlags, EGLDisplay display, EG
    glPixelStorei(GL_UNPACK_ALIGNMENT, 4);
    glPixelStorei(GL_PACK_ALIGNMENT, 4);

    // Initialize protected EGL Context.
    if (mProtectedEGLContext != EGL_NO_CONTEXT) {
        EGLBoolean success = eglMakeCurrent(display, mProtectedDummySurface, mProtectedDummySurface,
                                            mProtectedEGLContext);
        ALOGE_IF(!success, "can't make protected context current");
        glPixelStorei(GL_UNPACK_ALIGNMENT, 4);
        glPixelStorei(GL_PACK_ALIGNMENT, 4);
        success = eglMakeCurrent(display, mDummySurface, mDummySurface, mEGLContext);
        LOG_ALWAYS_FATAL_IF(!success, "can't make default context current");
    }

    const uint16_t protTexData[] = {0};
    glGenTextures(1, &mProtectedTexName);
    glBindTexture(GL_TEXTURE_2D, mProtectedTexName);
@@ -395,7 +430,8 @@ std::unique_ptr<Image> GLESRenderEngine::createImage() {
}

void GLESRenderEngine::primeCache() const {
    ProgramCache::getInstance().primeCache(mFeatureFlags & USE_COLOR_MANAGEMENT);
    ProgramCache::getInstance().primeCache(mInProtectedContext ? mProtectedEGLContext : mEGLContext,
                                           mFeatureFlags & USE_COLOR_MANAGEMENT);
}

bool GLESRenderEngine::isCurrent() const {
@@ -539,6 +575,10 @@ void GLESRenderEngine::bindExternalTextureImage(uint32_t texName, const Image& i
    const GLenum target = GL_TEXTURE_EXTERNAL_OES;

    glBindTexture(target, texName);
    if (supportsProtectedContent()) {
        glTexParameteri(target, GL_TEXTURE_PROTECTED_EXT,
                        glImage.isProtected() ? GL_TRUE : GL_FALSE);
    }
    if (glImage.getEGLImage() != EGL_NO_IMAGE_KHR) {
        glEGLImageTargetTexture2DOES(target, static_cast<GLeglImageOES>(glImage.getEGLImage()));
    }
@@ -552,6 +592,10 @@ status_t GLESRenderEngine::bindFrameBuffer(Framebuffer* framebuffer) {

    // Bind the texture and turn our EGLImage into a texture
    glBindTexture(GL_TEXTURE_2D, textureName);
    if (supportsProtectedContent()) {
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_PROTECTED_EXT,
                        mInProtectedContext ? GL_TRUE : GL_FALSE);
    }
    glEGLImageTargetTexture2DOES(GL_TEXTURE_2D, (GLeglImageOES)eglImage);

    // Bind the Framebuffer to render into
@@ -584,6 +628,26 @@ void GLESRenderEngine::checkErrors() const {
    } while (true);
}

bool GLESRenderEngine::supportsProtectedContent() const {
    return mProtectedEGLContext != EGL_NO_CONTEXT;
}

bool GLESRenderEngine::useProtectedContext(bool useProtectedContext) {
    if (useProtectedContext == mInProtectedContext) {
        return true;
    }
    if (useProtectedContext && mProtectedEGLContext == EGL_NO_CONTEXT) {
        return false;
    }
    const EGLSurface surface = useProtectedContext ? mProtectedDummySurface : mDummySurface;
    const EGLContext context = useProtectedContext ? mProtectedEGLContext : mEGLContext;
    const bool success = eglMakeCurrent(mEGLDisplay, surface, surface, context) == EGL_TRUE;
    if (success) {
        mInProtectedContext = useProtectedContext;
    }
    return success;
}

status_t GLESRenderEngine::drawLayers(const DisplaySettings& /*settings*/,
                                      const std::vector<LayerSettings>& /*layers*/,
                                      ANativeWindowBuffer* const /*buffer*/,
@@ -822,7 +886,9 @@ void GLESRenderEngine::drawMesh(const Mesh& mesh) {
                    Description::dataSpaceToTransferFunction(outputTransfer);
        }

        ProgramCache::getInstance().useProgram(managedState);
        ProgramCache::getInstance().useProgram(mInProtectedContext ? mProtectedEGLContext
                                                                   : mEGLContext,
                                               managedState);

        glDrawArrays(mesh.getPrimitive(), 0, mesh.getVertexCount());

@@ -833,7 +899,9 @@ void GLESRenderEngine::drawMesh(const Mesh& mesh) {
            writePPM(out.str().c_str(), mVpWidth, mVpHeight);
        }
    } else {
        ProgramCache::getInstance().useProgram(mState);
        ProgramCache::getInstance().useProgram(mInProtectedContext ? mProtectedEGLContext
                                                                   : mEGLContext,
                                               mState);

        glDrawArrays(mesh.getPrimitive(), 0, mesh.getVertexCount());
    }
@@ -857,17 +925,18 @@ size_t GLESRenderEngine::getMaxViewportDims() const {

void GLESRenderEngine::dump(std::string& result) {
    const GLExtensions& extensions = GLExtensions::getInstance();
    ProgramCache& cache = ProgramCache::getInstance();

    StringAppendF(&result, "EGL implementation : %s\n", extensions.getEGLVersion());
    StringAppendF(&result, "%s\n", extensions.getEGLExtensions());

    StringAppendF(&result, "GLES: %s, %s, %s\n", extensions.getVendor(), extensions.getRenderer(),
                  extensions.getVersion());
    StringAppendF(&result, "%s\n", extensions.getExtensions());

    StringAppendF(&result, "RenderEngine program cache size: %zu\n",
                  ProgramCache::getInstance().getSize());

    StringAppendF(&result, "RenderEngine is in protected context : %d\n", mInProtectedContext);
    StringAppendF(&result, "RenderEngine program cache size for unprotected context: %zu\n",
                  cache.getSize(mEGLContext));
    StringAppendF(&result, "RenderEngine program cache size for protected context: %zu\n",
                  cache.getSize(mProtectedEGLContext));
    StringAppendF(&result, "RenderEngine last dataspace conversion: (%s) to (%s)\n",
                  dataspaceDetails(static_cast<android_dataspace>(mDataSpace)).c_str(),
                  dataspaceDetails(static_cast<android_dataspace>(mOutputDataSpace)).c_str());
@@ -892,7 +961,8 @@ GLESRenderEngine::GlesVersion GLESRenderEngine::parseGlesVersion(const char* str
}

EGLContext GLESRenderEngine::createEglContext(EGLDisplay display, EGLConfig config,
                                              EGLContext shareContext, bool useContextPriority) {
                                              EGLContext shareContext, bool useContextPriority,
                                              Protection protection) {
    EGLint renderableType = 0;
    if (config == EGL_NO_CONFIG) {
        renderableType = EGL_OPENGL_ES3_BIT;
@@ -911,13 +981,17 @@ EGLContext GLESRenderEngine::createEglContext(EGLDisplay display, EGLConfig conf
    }

    std::vector<EGLint> contextAttributes;
    contextAttributes.reserve(5);
    contextAttributes.reserve(7);
    contextAttributes.push_back(EGL_CONTEXT_CLIENT_VERSION);
    contextAttributes.push_back(contextClientVersion);
    if (useContextPriority) {
        contextAttributes.push_back(EGL_CONTEXT_PRIORITY_LEVEL_IMG);
        contextAttributes.push_back(EGL_CONTEXT_PRIORITY_HIGH_IMG);
    }
    if (protection == Protection::PROTECTED) {
        contextAttributes.push_back(EGL_PROTECTED_CONTENT_EXT);
        contextAttributes.push_back(EGL_TRUE);
    }
    contextAttributes.push_back(EGL_NONE);

    EGLContext context = eglCreateContext(display, config, shareContext, contextAttributes.data());
@@ -938,17 +1012,21 @@ EGLContext GLESRenderEngine::createEglContext(EGLDisplay display, EGLConfig conf
}

EGLSurface GLESRenderEngine::createDummyEglPbufferSurface(EGLDisplay display, EGLConfig config,
                                                          int hwcFormat) {
                                                          int hwcFormat, Protection protection) {
    EGLConfig dummyConfig = config;
    if (dummyConfig == EGL_NO_CONFIG) {
        dummyConfig = chooseEglConfig(display, hwcFormat, /*logConfig*/ true);
    }
    std::vector<EGLint> attributes;
    attributes.reserve(5);
    attributes.reserve(7);
    attributes.push_back(EGL_WIDTH);
    attributes.push_back(1);
    attributes.push_back(EGL_HEIGHT);
    attributes.push_back(1);
    if (protection == Protection::PROTECTED) {
        attributes.push_back(EGL_PROTECTED_CONTENT_EXT);
        attributes.push_back(EGL_TRUE);
    }
    attributes.push_back(EGL_NONE);

    return eglCreatePbufferSurface(display, dummyConfig, attributes.data());
+11 −4
Original line number Diff line number Diff line
@@ -45,7 +45,8 @@ public:
    static EGLConfig chooseEglConfig(EGLDisplay display, int format, bool logConfig);

    GLESRenderEngine(uint32_t featureFlags, // See RenderEngine::FeatureFlag
                     EGLDisplay display, EGLConfig config, EGLContext ctxt, EGLSurface dummy);
                     EGLDisplay display, EGLConfig config, EGLContext ctxt, EGLSurface dummy,
                     EGLContext protectedContext, EGLSurface protectedDummy);
    ~GLESRenderEngine() override;

    std::unique_ptr<Framebuffer> createFramebuffer() override;
@@ -68,6 +69,9 @@ public:
    void unbindFrameBuffer(Framebuffer* framebuffer) override;
    void checkErrors() const override;

    bool isProtected() const override { return mInProtectedContext; }
    bool supportsProtectedContent() const override;
    bool useProtectedContext(bool useProtectedContext) override;
    status_t drawLayers(const DisplaySettings& settings, const std::vector<LayerSettings>& layers,
                        ANativeWindowBuffer* const buffer,
                        base::unique_fd* displayFence) const override;
@@ -112,20 +116,22 @@ private:

    static GlesVersion parseGlesVersion(const char* str);
    static EGLContext createEglContext(EGLDisplay display, EGLConfig config,
                                       EGLContext shareContext, bool useContextPriority);
                                       EGLContext shareContext, bool useContextPriority,
                                       Protection protection);
    static EGLSurface createDummyEglPbufferSurface(EGLDisplay display, EGLConfig config,
                                                   int hwcFormat);
                                                   int hwcFormat, Protection protection);

    // A data space is considered HDR data space if it has BT2020 color space
    // with PQ or HLG transfer function.
    bool isHdrDataSpace(const ui::Dataspace dataSpace) const;
    bool needsXYZTransformMatrix() const;
    void setEGLHandles(EGLDisplay display, EGLConfig config, EGLContext ctxt, EGLSurface dummy);

    EGLDisplay mEGLDisplay;
    EGLConfig mEGLConfig;
    EGLContext mEGLContext;
    EGLSurface mDummySurface;
    EGLContext mProtectedEGLContext;
    EGLSurface mProtectedDummySurface;
    GLuint mProtectedTexName;
    GLint mMaxViewportDims[2];
    GLint mMaxTextureSize;
@@ -146,6 +152,7 @@ private:
    mat4 mBt2020ToSrgb;
    mat4 mBt2020ToDisplayP3;

    bool mInProtectedContext = false;
    int32_t mFboHeight = 0;

    // Current dataspace of layer being rendered
+5 −0
Original line number Diff line number Diff line
@@ -60,6 +60,11 @@ void GLExtensions::initWithGLStrings(GLubyte const* vendor, GLubyte const* rende
    mRenderer = (char const*)renderer;
    mVersion = (char const*)version;
    mExtensions = (char const*)extensions;

    ExtensionSet extensionSet(mExtensions.c_str());
    if (extensionSet.hasExtension("GL_EXT_protected_textures")) {
        mHasProtectedTexture = true;
    }
}

char const* GLExtensions::getVendor() const {
+2 −1
Original line number Diff line number Diff line
@@ -40,6 +40,7 @@ public:
    bool hasProtectedContent() const { return mHasProtectedContent; }
    bool hasContextPriority() const { return mHasContextPriority; }
    bool hasSurfacelessContext() const { return mHasSurfacelessContext; }
    bool hasProtectedTexture() const { return mHasProtectedTexture; }

    void initWithGLStrings(GLubyte const* vendor, GLubyte const* renderer, GLubyte const* version,
                           GLubyte const* extensions);
@@ -65,12 +66,12 @@ private:
    bool mHasProtectedContent = false;
    bool mHasContextPriority = false;
    bool mHasSurfacelessContext = false;
    bool mHasProtectedTexture = false;

    String8 mVendor;
    String8 mRenderer;
    String8 mVersion;
    String8 mExtensions;

    String8 mEGLVersion;
    String8 mEGLExtensions;

+7 −2
Original line number Diff line number Diff line
@@ -39,7 +39,7 @@ GLFramebuffer::~GLFramebuffer() {
    eglDestroyImageKHR(mEGLDisplay, mEGLImage);
}

bool GLFramebuffer::setNativeWindowBuffer(ANativeWindowBuffer* nativeBuffer) {
bool GLFramebuffer::setNativeWindowBuffer(ANativeWindowBuffer* nativeBuffer, bool isProtected) {
    if (mEGLImage != EGL_NO_IMAGE_KHR) {
        eglDestroyImageKHR(mEGLDisplay, mEGLImage);
        mEGLImage = EGL_NO_IMAGE_KHR;
@@ -48,8 +48,13 @@ bool GLFramebuffer::setNativeWindowBuffer(ANativeWindowBuffer* nativeBuffer) {
    }

    if (nativeBuffer) {
        EGLint attributes[] = {
                isProtected ? EGL_PROTECTED_CONTENT_EXT : EGL_NONE,
                isProtected ? EGL_TRUE : EGL_NONE,
                EGL_NONE,
        };
        mEGLImage = eglCreateImageKHR(mEGLDisplay, EGL_NO_CONTEXT, EGL_NATIVE_BUFFER_ANDROID,
                                      nativeBuffer, nullptr);
                                      nativeBuffer, attributes);
        if (mEGLImage == EGL_NO_IMAGE_KHR) {
            return false;
        }
Loading