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

Commit d508e473 authored by Lucas Dupin's avatar Lucas Dupin
Browse files

Add protected context support

So DRM protected content can still be played on SkiaRE

Test: play videos on YT, pull down the shade with blur
Bug: 164223050
Change-Id: Ia12657c41782c175c2ebd7f95775aa09a4597974
parent 74f22bbc
Loading
Loading
Loading
Loading
+37 −21
Original line number Diff line number Diff line
@@ -252,8 +252,8 @@ std::unique_ptr<SkiaGLRenderEngine> SkiaGLRenderEngine::create(

    // initialize the renderer while GL is current
    std::unique_ptr<SkiaGLRenderEngine> engine =
            std::make_unique<SkiaGLRenderEngine>(args, display, config, ctxt, placeholder,
                                                 protectedContext, protectedPlaceholder);
            std::make_unique<SkiaGLRenderEngine>(args, display, ctxt, placeholder, protectedContext,
                                                 protectedPlaceholder);

    ALOGI("OpenGL ES informations:");
    ALOGI("vendor    : %s", extensions.getVendor());
@@ -306,38 +306,52 @@ EGLConfig SkiaGLRenderEngine::chooseEglConfig(EGLDisplay display, int format, bo
}

SkiaGLRenderEngine::SkiaGLRenderEngine(const RenderEngineCreationArgs& args, EGLDisplay display,
                                       EGLConfig config, EGLContext ctxt, EGLSurface placeholder,
                                       EGLContext ctxt, EGLSurface placeholder,
                                       EGLContext protectedContext, EGLSurface protectedPlaceholder)
      : mEGLDisplay(display),
        mEGLConfig(config),
        mEGLContext(ctxt),
        mPlaceholderSurface(placeholder),
        mProtectedEGLContext(protectedContext),
        mProtectedPlaceholderSurface(protectedPlaceholder),
        mUseColorManagement(args.useColorManagement) {
    // Suppress unused field warnings for things we definitely will need/use
    // These EGL fields will all be needed for toggling between protected & unprotected contexts
    // Or we need different RE instances for that
    (void)mEGLDisplay;
    (void)mEGLConfig;
    (void)mEGLContext;
    (void)mPlaceholderSurface;
    (void)mProtectedEGLContext;
    (void)mProtectedPlaceholderSurface;

    sk_sp<const GrGLInterface> glInterface(GrGLCreateNativeInterface());
    LOG_ALWAYS_FATAL_IF(!glInterface.get());

    GrContextOptions options;
    options.fPreferExternalImagesOverES3 = true;
    options.fDisableDistanceFieldPaths = true;
    mGrContext = GrDirectContext::MakeGL(std::move(glInterface), options);
    mGrContext = GrDirectContext::MakeGL(glInterface, options);
    if (useProtectedContext(true)) {
        mProtectedGrContext = GrDirectContext::MakeGL(glInterface, options);
        useProtectedContext(false);
    }

    if (args.supportsBackgroundBlur) {
        mBlurFilter = new BlurFilter();
    }
}

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

bool SkiaGLRenderEngine::useProtectedContext(bool useProtectedContext) {
    if (useProtectedContext == mInProtectedContext) {
        return true;
    }
    if (useProtectedContext && supportsProtectedContent()) {
        return false;
    }
    const EGLSurface surface =
            useProtectedContext ? mProtectedPlaceholderSurface : mPlaceholderSurface;
    const EGLContext context = useProtectedContext ? mProtectedEGLContext : mEGLContext;
    const bool success = eglMakeCurrent(mEGLDisplay, surface, surface, context) == EGL_TRUE;
    if (success) {
        mInProtectedContext = useProtectedContext;
    }
    return success;
}

base::unique_fd SkiaGLRenderEngine::flush() {
    ATRACE_CALL();
    if (!gl::GLExtensions::getInstance().hasNativeFenceSync()) {
@@ -471,22 +485,23 @@ status_t SkiaGLRenderEngine::drawLayers(const DisplaySettings& display,
        return BAD_VALUE;
    }

    auto grContext = mInProtectedContext ? mProtectedGrContext : mGrContext;
    auto cache = mInProtectedContext ? mProtectedSurfaceCache : mSurfaceCache;
    AHardwareBuffer_Desc bufferDesc;
    AHardwareBuffer_describe(buffer->toAHardwareBuffer(), &bufferDesc);

    LOG_ALWAYS_FATAL_IF(!hasUsage(bufferDesc, AHARDWAREBUFFER_USAGE_GPU_SAMPLED_IMAGE),
                        "missing usage");

    sk_sp<SkSurface> surface;
    if (useFramebufferCache) {
        auto iter = mSurfaceCache.find(buffer->getId());
        if (iter != mSurfaceCache.end()) {
        auto iter = cache.find(buffer->getId());
        if (iter != cache.end()) {
            ALOGV("Cache hit!");
            surface = iter->second;
        }
    }
    if (!surface) {
        surface = SkSurface::MakeFromAHardwareBuffer(mGrContext.get(), buffer->toAHardwareBuffer(),
        surface = SkSurface::MakeFromAHardwareBuffer(grContext.get(), buffer->toAHardwareBuffer(),
                                                     GrSurfaceOrigin::kTopLeft_GrSurfaceOrigin,
                                                     mUseColorManagement
                                                             ? toColorSpace(display.outputDataspace)
@@ -494,7 +509,7 @@ status_t SkiaGLRenderEngine::drawLayers(const DisplaySettings& display,
                                                     nullptr);
        if (useFramebufferCache && surface) {
            ALOGD("Adding to cache");
            mSurfaceCache.insert({buffer->getId(), surface});
            cache.insert({buffer->getId(), surface});
        }
    }
    if (!surface) {
@@ -699,7 +714,7 @@ status_t SkiaGLRenderEngine::drawLayers(const DisplaySettings& display,
    } else {
        ATRACE_BEGIN("Submit(sync=false)");
    }
    bool success = mGrContext->submit(requireSync);
    bool success = grContext->submit(requireSync);
    ATRACE_END();
    if (!success) {
        ALOGE("Failed to flush RenderEngine commands");
@@ -868,6 +883,7 @@ EGLSurface SkiaGLRenderEngine::createPlaceholderEglPbufferSurface(EGLDisplay dis

void SkiaGLRenderEngine::cleanFramebufferCache() {
    mSurfaceCache.clear();
    mProtectedSurfaceCache.clear();
}

} // namespace skia
+10 −3
Original line number Diff line number Diff line
@@ -40,8 +40,8 @@ namespace skia {
class SkiaGLRenderEngine : public skia::SkiaRenderEngine {
public:
    static std::unique_ptr<SkiaGLRenderEngine> create(const RenderEngineCreationArgs& args);
    SkiaGLRenderEngine(const RenderEngineCreationArgs& args, EGLDisplay display, EGLConfig config,
                       EGLContext ctxt, EGLSurface placeholder, EGLContext protectedContext,
    SkiaGLRenderEngine(const RenderEngineCreationArgs& args, EGLDisplay display, EGLContext ctxt,
                       EGLSurface placeholder, EGLContext protectedContext,
                       EGLSurface protectedPlaceholder);
    ~SkiaGLRenderEngine() override{};

@@ -51,6 +51,9 @@ public:
                        const sp<GraphicBuffer>& buffer, const bool useFramebufferCache,
                        base::unique_fd&& bufferFence, base::unique_fd* drawFence) override;
    void cleanFramebufferCache() override;
    bool isProtected() const override { return mInProtectedContext; }
    bool supportsProtectedContent() const override;
    bool useProtectedContext(bool useProtectedContext) override;

protected:
    void dump(std::string& /*result*/) override{};
@@ -79,7 +82,6 @@ private:
                        sk_sp<SkSurface> blurrendSurface);

    EGLDisplay mEGLDisplay;
    EGLConfig mEGLConfig;
    EGLContext mEGLContext;
    EGLSurface mPlaceholderSurface;
    EGLContext mProtectedEGLContext;
@@ -98,9 +100,14 @@ private:

    sp<Fence> mLastDrawFence;

    // Graphics context used for creating surfaces and submitting commands
    sk_sp<GrDirectContext> mGrContext;
    // Same as above, but for protected content (eg. DRM)
    sk_sp<GrDirectContext> mProtectedGrContext;

    std::unordered_map<uint64_t, sk_sp<SkSurface>> mSurfaceCache;
    std::unordered_map<uint64_t, sk_sp<SkSurface>> mProtectedSurfaceCache;
    bool mInProtectedContext = false;
};

} // namespace skia