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

Commit dfec8f5f authored by Ana Krulec's avatar Ana Krulec
Browse files

Caching images and textures for threaded Skia RE

Skia also performs texture generation and deletion when
we create an image. This needs to happen on the same thread.
Running Skia on it's own thread, will allow async caching
of images, and hopefully increasing the start up/transition
of application.

Screenshot of the parallel caching:
https://screenshot.googleplex.com/BUnne3urcoavykk

Test results for DisplayOrientationMicrobench test for
SFSTATS_GLOBAL_RENDER_ENGINE_DURATION_AVG metric:
skiathreaded 1st run: 5.750296 ms
skia threaded 2nd run: 5.530306 ms
gles: 4.974821 ms
skia: 6.374791 ms

Test: Set renderengine backend to 'skiathreaded'.
      - run libsurfaceflinger_test, SurfaceFlinger_test
      - open apps
      - switch between apps
Bug: 175312877
Change-Id: I6521f9ddfadff8c839bdd7071c2bd6cfadebb663
parent e74432c5
Loading
Loading
Loading
Loading
+20 −3
Original line number Diff line number Diff line
@@ -51,11 +51,28 @@ std::unique_ptr<RenderEngine> RenderEngine::create(const RenderEngineCreationArg
            return renderengine::threaded::RenderEngineThreaded::create(
                    [args]() { return android::renderengine::gl::GLESRenderEngine::create(args); });
        case RenderEngineType::SKIA_GL:
            ALOGD("RenderEngine with SkiaGL Backend");
            return renderengine::skia::SkiaGLRenderEngine::create(args);
        case RenderEngineType::SKIA_GL_THREADED:
            return renderengine::threaded::RenderEngineThreaded::create([args]() {
                return android::renderengine::skia::SkiaGLRenderEngine::create(args);
        case RenderEngineType::SKIA_GL_THREADED: {
            // These need to be recreated, since they are a constant reference, and we need to
            // let SkiaRE know that it's running as threaded, and all GL operation will happen on
            // the same thread.
            RenderEngineCreationArgs skiaArgs =
                    RenderEngineCreationArgs::Builder()
                            .setPixelFormat(args.pixelFormat)
                            .setImageCacheSize(args.imageCacheSize)
                            .setUseColorManagerment(args.useColorManagement)
                            .setEnableProtectedContext(args.enableProtectedContext)
                            .setPrecacheToneMapperShaderOnly(args.precacheToneMapperShaderOnly)
                            .setSupportsBackgroundBlur(args.supportsBackgroundBlur)
                            .setContextPriority(args.contextPriority)
                            .setRenderEngineType(RenderEngineType::SKIA_GL_THREADED)
                            .build();
            ALOGD("Threaded RenderEngine with SkiaGL Backend");
            return renderengine::threaded::RenderEngineThreaded::create([skiaArgs]() {
                return android::renderengine::skia::SkiaGLRenderEngine::create(skiaArgs);
            });
        }
        case RenderEngineType::GLES:
        default:
            ALOGD("RenderEngine with GLES Backend");
+1 −0
Original line number Diff line number Diff line
@@ -746,6 +746,7 @@ void GLESRenderEngine::bindExternalTextureBuffer(uint32_t texName, const sp<Grap
}

void GLESRenderEngine::cacheExternalTextureBuffer(const sp<GraphicBuffer>& buffer) {
    ATRACE_CALL();
    mImageManager->cacheAsync(buffer, nullptr);
}

+27 −1
Original line number Diff line number Diff line
@@ -267,7 +267,8 @@ SkiaGLRenderEngine::SkiaGLRenderEngine(const RenderEngineCreationArgs& args, EGL
        mPlaceholderSurface(placeholder),
        mProtectedEGLContext(protectedContext),
        mProtectedPlaceholderSurface(protectedPlaceholder),
        mUseColorManagement(args.useColorManagement) {
        mUseColorManagement(args.useColorManagement),
        mRenderEngineType(args.renderEngineType) {
    sk_sp<const GrGLInterface> glInterface(GrGLCreateNativeInterface());
    LOG_ALWAYS_FATAL_IF(!glInterface.get());

@@ -453,7 +454,30 @@ static bool needsLinearEffect(const mat4& colorTransform, ui::Dataspace sourceDa
    return colorTransform != mat4() || needsToneMapping(sourceDataspace, destinationDataspace);
}

void SkiaGLRenderEngine::cacheExternalTextureBuffer(const sp<GraphicBuffer>& buffer) {
    // Only run this if RE is running on its own thread. This way the access to GL
    // operations is guaranteed to be happening on the same thread.
    if (mRenderEngineType != RenderEngineType::SKIA_GL_THREADED) {
        return;
    }
    ATRACE_CALL();

    std::lock_guard<std::mutex> lock(mRenderingMutex);
    auto iter = mTextureCache.find(buffer->getId());
    if (iter != mTextureCache.end()) {
        ALOGV("Texture already exists in cache.");
        return;
    } else {
        std::shared_ptr<AutoBackendTexture::LocalRef> imageTextureRef =
                std::make_shared<AutoBackendTexture::LocalRef>();
        imageTextureRef->setTexture(
                new AutoBackendTexture(mGrContext.get(), buffer->toAHardwareBuffer(), false));
        mTextureCache.insert({buffer->getId(), imageTextureRef});
    }
}

void SkiaGLRenderEngine::unbindExternalTextureBuffer(uint64_t bufferId) {
    ATRACE_CALL();
    std::lock_guard<std::mutex> lock(mRenderingMutex);
    mTextureCache.erase(bufferId);
    mProtectedTextureCache.erase(bufferId);
@@ -523,11 +547,13 @@ status_t SkiaGLRenderEngine::drawLayers(const DisplaySettings& display,
        auto iter = cache.find(buffer->getId());
        if (iter != cache.end()) {
            ALOGV("Cache hit!");
            ATRACE_NAME("Cache hit");
            surfaceTextureRef = iter->second;
        }
    }

    if (surfaceTextureRef == nullptr || surfaceTextureRef->getTexture() == nullptr) {
        ATRACE_NAME("Cache miss");
        surfaceTextureRef = std::make_shared<AutoBackendTexture::LocalRef>();
        surfaceTextureRef->setTexture(
                new AutoBackendTexture(grContext.get(), buffer->toAHardwareBuffer(), true));
+5 −0
Original line number Diff line number Diff line
@@ -50,6 +50,7 @@ public:
                       EGLSurface protectedPlaceholder);
    ~SkiaGLRenderEngine() override EXCLUDES(mRenderingMutex);

    void cacheExternalTextureBuffer(const sp<GraphicBuffer>& buffer) override;
    void unbindExternalTextureBuffer(uint64_t bufferId) override;
    status_t drawLayers(const DisplaySettings& display,
                        const std::vector<const LayerSettings*>& layers,
@@ -128,6 +129,10 @@ private:
    bool mInProtectedContext = false;
    // Object to capture commands send to Skia.
    std::unique_ptr<SkiaCapture> mCapture;

    // Keep this information as a local variable to determine whether the access of the GL
    // operations is working on the same threads.
    const RenderEngineType mRenderEngineType = RenderEngineType::SKIA_GL;
};

} // namespace skia
+0 −16
Original line number Diff line number Diff line
@@ -62,22 +62,6 @@ TEST_F(RenderEngineThreadedTest, deleteTextures) {
    mThreadedRE->deleteTextures(1, &texName);
}

TEST_F(RenderEngineThreadedTest, cacheExternalTextureBuffer_nullptr) {
    EXPECT_CALL(*mRenderEngine, cacheExternalTextureBuffer(Eq(nullptr)));
    mThreadedRE->cacheExternalTextureBuffer(nullptr);
}

TEST_F(RenderEngineThreadedTest, cacheExternalTextureBuffer_withBuffer) {
    sp<GraphicBuffer> buf = new GraphicBuffer();
    EXPECT_CALL(*mRenderEngine, cacheExternalTextureBuffer(buf));
    mThreadedRE->cacheExternalTextureBuffer(buf);
}

TEST_F(RenderEngineThreadedTest, unbindExternalTextureBuffer) {
    EXPECT_CALL(*mRenderEngine, unbindExternalTextureBuffer(0x0));
    mThreadedRE->unbindExternalTextureBuffer(0x0);
}

TEST_F(RenderEngineThreadedTest, getMaxTextureSize_returns20) {
    size_t size = 20;
    EXPECT_CALL(*mRenderEngine, getMaxTextureSize()).WillOnce(Return(size));
Loading