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

Commit 00c1ff65 authored by Lingfeng Yang's avatar Lingfeng Yang
Browse files

Move common Skia code to SkiaRenderEngine

This CL takes the code in SkiaGLRenderEngine that is not GL-specific and
moves it to SkiaRenderEngine. This is a pure refactoring, no change in
functionality. This is to prepare for adding a SkiaVk backend.

We introduce virtual functions waitFence, flushAndSubmit, and
backendDump to SkiaRenderEngine so that the same GL fence flush logic
can be called from drawLayers in SkiaRenderEngine, and that most of the
dump() logic can also stay in SkiaRenderEngine.

That leaves SkiaGLRenderEngine doing only EGL context initialization and
fence handling.

Test: librenderengine_test
Bug: 236390072
Change-Id: I240d1723d28836a050b6c694bc61011311106937
parent 08cec35e
Loading
Loading
Loading
Loading
+69 −1220

File changed.

Preview size limit exceeded, changes collapsed.

+13 −116
Original line number Diff line number Diff line
@@ -55,33 +55,23 @@ public:
    SkiaGLRenderEngine(const RenderEngineCreationArgs& args, EGLDisplay display, EGLContext ctxt,
                       EGLSurface placeholder, EGLContext protectedContext,
                       EGLSurface protectedPlaceholder);
    ~SkiaGLRenderEngine() override EXCLUDES(mRenderingMutex);
    ~SkiaGLRenderEngine() override;

    std::future<void> primeCache() override;
    void cleanupPostRender() override;
    void cleanFramebufferCache() override{};
    int getContextPriority() override;
    bool isProtected() const override { return mInProtectedContext; }
    bool supportsProtectedContent() const override;
    void useProtectedContext(bool useProtectedContext) override;
    bool supportsBackgroundBlur() override { return mBlurFilter != nullptr; }
    void onActiveDisplaySizeChanged(ui::Size size) override;
    int reportShadersCompiled() override;

protected:
    void dump(std::string& result) override;
    size_t getMaxTextureSize() const override;
    size_t getMaxViewportDims() const override;
    void mapExternalTextureBuffer(const sp<GraphicBuffer>& buffer, bool isRenderable) override;
    void unmapExternalTextureBuffer(const sp<GraphicBuffer>& buffer) override;
    bool canSkipPostRenderCleanup() const override;
    void drawLayersInternal(const std::shared_ptr<std::promise<RenderEngineResult>>&& resultPromise,
                            const DisplaySettings& display,
                            const std::vector<LayerSettings>& layers,
                            const std::shared_ptr<ExternalTexture>& buffer,
                            const bool useFramebufferCache, base::unique_fd&& bufferFence) override;
    // Implementations of abstract SkiaRenderEngine functions specific to
    // rendering backend
    virtual SkiaRenderEngine::Contexts createDirectContexts(const GrContextOptions& options);
    bool supportsProtectedContentImpl() const override;
    bool useProtectedContextImpl(GrProtected isProtected) override;
    void waitFence(GrDirectContext* grContext, base::borrowed_fd fenceFd) override;
    base::unique_fd flushAndSubmit(GrDirectContext* context) override;
    void appendBackendSpecificInfoToDump(std::string& result) override;

private:
    bool waitGpuFence(base::borrowed_fd fenceFd);
    base::unique_fd flush();
    static EGLConfig chooseEglConfig(EGLDisplay display, int format, bool logConfig);
    static EGLContext createEglContext(EGLDisplay display, EGLConfig config,
                                       EGLContext shareContext,
@@ -89,107 +79,14 @@ private:
                                       Protection protection);
    static std::optional<RenderEngine::ContextPriority> createContextPriority(
            const RenderEngineCreationArgs& args);
    static EGLSurface createPlaceholderEglPbufferSurface(EGLDisplay display, EGLConfig config,
                                                         int hwcFormat, Protection protection);
    inline SkRect getSkRect(const FloatRect& layer);
    inline SkRect getSkRect(const Rect& layer);
    inline std::pair<SkRRect, SkRRect> getBoundsAndClip(const FloatRect& bounds,
                                                        const FloatRect& crop,
                                                        const vec2& cornerRadius);
    inline bool layerHasBlur(const LayerSettings& layer, bool colorTransformModifiesAlpha);
    inline SkColor getSkColor(const vec4& color);
    inline SkM44 getSkM44(const mat4& matrix);
    inline SkPoint3 getSkPoint3(const vec3& vector);
    inline GrDirectContext* getActiveGrContext() const;

    base::unique_fd flush();
    // waitFence attempts to wait in the GPU, and if unable to waits on the CPU instead.
    void waitFence(base::borrowed_fd fenceFd);
    bool waitGpuFence(base::borrowed_fd fenceFd);

    void initCanvas(SkCanvas* canvas, const DisplaySettings& display);
    void drawShadow(SkCanvas* canvas, const SkRRect& casterRRect,
                    const ShadowSettings& shadowSettings);

    // If requiresLinearEffect is true or the layer has a stretchEffect a new shader is returned.
    // Otherwise it returns the input shader.
    struct RuntimeEffectShaderParameters {
        sk_sp<SkShader> shader;
        const LayerSettings& layer;
        const DisplaySettings& display;
        bool undoPremultipliedAlpha;
        bool requiresLinearEffect;
        float layerDimmingRatio;
    };
    sk_sp<SkShader> createRuntimeEffectShader(const RuntimeEffectShaderParameters&);
    static EGLSurface createPlaceholderEglPbufferSurface(
            EGLDisplay display, EGLConfig config, int hwcFormat, Protection protection);

    EGLDisplay mEGLDisplay;
    EGLContext mEGLContext;
    EGLSurface mPlaceholderSurface;
    EGLContext mProtectedEGLContext;
    EGLSurface mProtectedPlaceholderSurface;
    BlurFilter* mBlurFilter = nullptr;

    const PixelFormat mDefaultPixelFormat;
    const bool mUseColorManagement;

    // Identifier used or various mappings of layers to various
    // textures or shaders
    using GraphicBufferId = uint64_t;

    // Number of external holders of ExternalTexture references, per GraphicBuffer ID.
    std::unordered_map<GraphicBufferId, int32_t> mGraphicBufferExternalRefs
            GUARDED_BY(mRenderingMutex);
    // Cache of GL textures that we'll store per GraphicBuffer ID, shared between GPU contexts.
    std::unordered_map<GraphicBufferId, std::shared_ptr<AutoBackendTexture::LocalRef>> mTextureCache
            GUARDED_BY(mRenderingMutex);
    std::unordered_map<shaders::LinearEffect, sk_sp<SkRuntimeEffect>, shaders::LinearEffectHasher>
            mRuntimeEffects;
    AutoBackendTexture::CleanupManager mTextureCleanupMgr GUARDED_BY(mRenderingMutex);

    StretchShaderFactory mStretchShaderFactory;
    // Mutex guarding rendering operations, so that:
    // 1. GL operations aren't interleaved, and
    // 2. Internal state related to rendering that is potentially modified by
    // multiple threads is guaranteed thread-safe.
    mutable std::mutex mRenderingMutex;

    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;

    bool mInProtectedContext = false;
    // Object to capture commands send to Skia.
    std::unique_ptr<SkiaCapture> mCapture;

    // Implements PersistentCache as a way to monitor what SkSL shaders Skia has
    // cached.
    class SkSLCacheMonitor : public GrContextOptions::PersistentCache {
    public:
        SkSLCacheMonitor() = default;
        ~SkSLCacheMonitor() override = default;

        sk_sp<SkData> load(const SkData& key) override;

        void store(const SkData& key, const SkData& data, const SkString& description) override;

        int shadersCachedSinceLastCall() {
            const int shadersCachedSinceLastCall = mShadersCachedSinceLastCall;
            mShadersCachedSinceLastCall = 0;
            return shadersCachedSinceLastCall;
        }

        int totalShadersCompiled() const { return mTotalShadersCompiled; }

    private:
        int mShadersCachedSinceLastCall = 0;
        int mTotalShadersCompiled = 0;
    };

    SkSLCacheMonitor mSkSLCacheMonitor;
};

} // namespace skia
+1229 −1

File changed.

Preview size limit exceeded, changes collapsed.

+154 −23
Original line number Diff line number Diff line
@@ -20,6 +20,31 @@
#include <renderengine/RenderEngine.h>
#include <sys/types.h>

#include <GrBackendSemaphore.h>
#include <GrDirectContext.h>
#include <SkSurface.h>
#include <android-base/thread_annotations.h>
#include <renderengine/ExternalTexture.h>
#include <renderengine/RenderEngine.h>
#include <sys/types.h>

#include <mutex>
#include <unordered_map>

#include "AutoBackendTexture.h"
#include "GrContextOptions.h"
#include "SkImageInfo.h"
#include "SkiaRenderEngine.h"
#include "android-base/macros.h"
#include "debug/SkiaCapture.h"
#include "filters/BlurFilter.h"
#include "filters/LinearEffect.h"
#include "filters/StretchShaderFactory.h"

class SkData;

struct SkPoint3;

namespace android {

namespace renderengine {
@@ -31,35 +56,141 @@ namespace skia {

class BlurFilter;

// TODO: Put common skia stuff here that can be shared between the GL & Vulkan backends
// Currently mostly just handles all the no-op / missing APIs
class SkiaRenderEngine : public RenderEngine {
public:
    static std::unique_ptr<SkiaRenderEngine> create(const RenderEngineCreationArgs& args);
    SkiaRenderEngine(RenderEngineType type);
    ~SkiaRenderEngine() override {}

    virtual std::future<void> primeCache() override { return {}; };
    virtual void genTextures(size_t /*count*/, uint32_t* /*names*/) override{};
    virtual void deleteTextures(size_t /*count*/, uint32_t const* /*names*/) override{};
    virtual bool isProtected() const override { return false; } // mInProtectedContext; }
    virtual bool supportsProtectedContent() const override { return false; };
    virtual int getContextPriority() override { return 0; }
    virtual int reportShadersCompiled() { return 0; }
    virtual void setEnableTracing(bool tracingEnabled) override;
    SkiaRenderEngine(RenderEngineType type,
                     PixelFormat pixelFormat,
                     bool useColorManagement,
                     bool supportsBackgroundBlur);
    ~SkiaRenderEngine() override;

    std::future<void> primeCache() override final;
    void cleanupPostRender() override final;
    void cleanFramebufferCache() override final{ }
    bool isProtected() const override final{ return mInProtectedContext; }
    bool supportsBackgroundBlur() override final {
        return mBlurFilter != nullptr;
    }
    void onActiveDisplaySizeChanged(ui::Size size) override final;
    int reportShadersCompiled();

    virtual void genTextures(size_t /*count*/, uint32_t* /*names*/) override final{};
    virtual void deleteTextures(size_t /*count*/, uint32_t const* /*names*/) override final{};
    virtual void setEnableTracing(bool tracingEnabled) override final;

    void useProtectedContext(bool useProtectedContext) override;
    bool supportsProtectedContent() const override {
        return supportsProtectedContentImpl();
    }
    void ensureGrContextsCreated();
protected:
    virtual void mapExternalTextureBuffer(const sp<GraphicBuffer>& /*buffer*/,
                                          bool /*isRenderable*/) override = 0;
    virtual void unmapExternalTextureBuffer(const sp<GraphicBuffer>& /*buffer*/) override = 0;

    virtual void drawLayersInternal(
            const std::shared_ptr<std::promise<RenderEngineResult>>&& resultPromise,
            const DisplaySettings& display, const std::vector<LayerSettings>& layers,
            const std::shared_ptr<ExternalTexture>& buffer, const bool useFramebufferCache,
            base::unique_fd&& bufferFence) override {
        resultPromise->set_value({NO_ERROR, base::unique_fd()});
    // This is so backends can stop the generic rendering state first before
    // cleaning up backend-specific state
    void finishRenderingAndAbandonContext();

    // Functions that a given backend (GLES, Vulkan) must implement
    using Contexts = std::pair<sk_sp<GrDirectContext>, sk_sp<GrDirectContext>>;
    virtual Contexts createDirectContexts(const GrContextOptions& options) = 0;
    virtual bool supportsProtectedContentImpl() const = 0;
    virtual bool useProtectedContextImpl(GrProtected isProtected) = 0;
    virtual void waitFence(GrDirectContext* grContext, base::borrowed_fd fenceFd) = 0;
    virtual base::unique_fd flushAndSubmit(GrDirectContext* context) = 0;
    virtual void appendBackendSpecificInfoToDump(std::string& result) = 0;

    size_t getMaxTextureSize() const override final;
    size_t getMaxViewportDims() const override final;
    GrDirectContext* getActiveGrContext();

    // Implements PersistentCache as a way to monitor what SkSL shaders Skia has
    // cached.
    class SkSLCacheMonitor : public GrContextOptions::PersistentCache {
    public:
        SkSLCacheMonitor() = default;
        ~SkSLCacheMonitor() override = default;

        sk_sp<SkData> load(const SkData& key) override;

        void store(const SkData& key, const SkData& data, const SkString& description) override;

        int shadersCachedSinceLastCall() {
            const int shadersCachedSinceLastCall = mShadersCachedSinceLastCall;
            mShadersCachedSinceLastCall = 0;
            return shadersCachedSinceLastCall;
        }

        int totalShadersCompiled() const { return mTotalShadersCompiled; }

    private:
        int mShadersCachedSinceLastCall = 0;
        int mTotalShadersCompiled = 0;
    };

private:
    void mapExternalTextureBuffer(const sp<GraphicBuffer>& buffer,
                                  bool isRenderable) override final;
    void unmapExternalTextureBuffer(const sp<GraphicBuffer>& buffer) override final;
    bool canSkipPostRenderCleanup() const override final;

    void initCanvas(SkCanvas* canvas, const DisplaySettings& display);
    void drawShadow(SkCanvas* canvas, const SkRRect& casterRRect,
                    const ShadowSettings& shadowSettings);
    void drawLayersInternal(const std::shared_ptr<std::promise<RenderEngineResult>>&& resultPromise,
                            const DisplaySettings& display,
                            const std::vector<LayerSettings>& layers,
                            const std::shared_ptr<ExternalTexture>& buffer,
                            const bool useFramebufferCache,
                            base::unique_fd&& bufferFence) override final;

    void dump(std::string& result) override final;

    // If requiresLinearEffect is true or the layer has a stretchEffect a new shader is returned.
    // Otherwise it returns the input shader.
    struct RuntimeEffectShaderParameters {
        sk_sp<SkShader> shader;
        const LayerSettings& layer;
        const DisplaySettings& display;
        bool undoPremultipliedAlpha;
        bool requiresLinearEffect;
        float layerDimmingRatio;
    };
    sk_sp<SkShader> createRuntimeEffectShader(const RuntimeEffectShaderParameters&);

    const PixelFormat mDefaultPixelFormat;
    const bool mUseColorManagement;

    // Identifier used for various mappings of layers to various
    // textures or shaders
    using GraphicBufferId = uint64_t;

    // Number of external holders of ExternalTexture references, per GraphicBuffer ID.
    std::unordered_map<GraphicBufferId, int32_t> mGraphicBufferExternalRefs
            GUARDED_BY(mRenderingMutex);
    // Cache of GL textures that we'll store per GraphicBuffer ID, shared between GPU contexts.
    std::unordered_map<GraphicBufferId, std::shared_ptr<AutoBackendTexture::LocalRef>> mTextureCache
            GUARDED_BY(mRenderingMutex);
    std::unordered_map<shaders::LinearEffect, sk_sp<SkRuntimeEffect>, shaders::LinearEffectHasher>
            mRuntimeEffects;
    AutoBackendTexture::CleanupManager mTextureCleanupMgr GUARDED_BY(mRenderingMutex);

    StretchShaderFactory mStretchShaderFactory;

    sp<Fence> mLastDrawFence;
    BlurFilter* mBlurFilter = nullptr;

    // Object to capture commands send to Skia.
    std::unique_ptr<SkiaCapture> mCapture;

    // Mutex guarding rendering operations, so that internal state related to
    // rendering that is potentially modified by multiple threads is guaranteed thread-safe.
    mutable std::mutex mRenderingMutex;
    SkSLCacheMonitor mSkSLCacheMonitor;

    // 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;
    bool mInProtectedContext = false;
};

} // namespace skia