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

Commit 18d61067 authored by TreeHugger Robot's avatar TreeHugger Robot Committed by Android (Google) Code Review
Browse files

Merge "Cleanup AutoBackendTexture to make it more difficult to leak resources" into sc-dev

parents 4de5bbe7 d8fdae33
Loading
Loading
Loading
Loading
+14 −4
Original line number Diff line number Diff line
@@ -29,7 +29,8 @@ namespace renderengine {
namespace skia {

AutoBackendTexture::AutoBackendTexture(GrDirectContext* context, AHardwareBuffer* buffer,
                                       bool isRender) {
                                       bool isOutputBuffer)
      : mIsOutputBuffer(isOutputBuffer) {
    ATRACE_CALL();
    AHardwareBuffer_Desc desc;
    AHardwareBuffer_describe(buffer, &desc);
@@ -40,8 +41,12 @@ AutoBackendTexture::AutoBackendTexture(GrDirectContext* context, AHardwareBuffer
            GrAHardwareBufferUtils::MakeBackendTexture(context, buffer, desc.width, desc.height,
                                                       &mDeleteProc, &mUpdateProc, &mImageCtx,
                                                       createProtectedImage, backendFormat,
                                                       isRender);
                                                       isOutputBuffer);
    mColorType = GrAHardwareBufferUtils::GetSkColorTypeFromBufferFormat(desc.format);
    ALOGE_IF(!mBackendTexture.isValid(),
             "Failed to create a valid texture. [%p]:[%d,%d] isProtected:%d isWriteable:%d "
             "format:%d",
             this, desc.width, desc.height, isOutputBuffer, createProtectedImage, desc.format);
}

void AutoBackendTexture::unref(bool releaseLocalResources) {
@@ -92,13 +97,16 @@ sk_sp<SkImage> AutoBackendTexture::makeImage(ui::Dataspace dataspace, SkAlphaTyp

    mImage = image;
    mDataspace = dataspace;
    LOG_ALWAYS_FATAL_IF(mImage == nullptr, "Unable to generate SkImage from buffer");
    LOG_ALWAYS_FATAL_IF(mImage == nullptr,
                        "Unable to generate SkImage. isTextureValid:%d dataspace:%d",
                        mBackendTexture.isValid(), dataspace);
    return mImage;
}

sk_sp<SkSurface> AutoBackendTexture::getOrCreateSurface(ui::Dataspace dataspace,
                                                        GrDirectContext* context) {
    ATRACE_CALL();
    LOG_ALWAYS_FATAL_IF(!mIsOutputBuffer, "You can't generate a SkSurface for a read-only texture");
    if (!mSurface.get() || mDataspace != dataspace) {
        sk_sp<SkSurface> surface =
                SkSurface::MakeFromBackendTexture(context, mBackendTexture,
@@ -113,7 +121,9 @@ sk_sp<SkSurface> AutoBackendTexture::getOrCreateSurface(ui::Dataspace dataspace,
    }

    mDataspace = dataspace;
    LOG_ALWAYS_FATAL_IF(mSurface == nullptr, "Unable to generate SkSurface");
    LOG_ALWAYS_FATAL_IF(mSurface == nullptr,
                        "Unable to generate SkSurface. isTextureValid:%d dataspace:%d",
                        mBackendTexture.isValid(), dataspace);
    return mSurface;
}

+25 −20
Original line number Diff line number Diff line
@@ -41,34 +41,42 @@ public:
    // of shared ownership with Skia objects, so we wrap it here instead.
    class LocalRef {
    public:
        LocalRef(AutoBackendTexture* texture) { setTexture(texture); }

        ~LocalRef() {
            // Destroying the texture is the same as setting it to null
            setTexture(nullptr);
        LocalRef(GrDirectContext* context, AHardwareBuffer* buffer, bool isOutputBuffer) {
            mTexture = new AutoBackendTexture(context, buffer, isOutputBuffer);
            mTexture->ref();
        }

        AutoBackendTexture* getTexture() const { return mTexture; }

        DISALLOW_COPY_AND_ASSIGN(LocalRef);

    private:
        // Sets the texture to locally ref-track.
        void setTexture(AutoBackendTexture* texture) {
        ~LocalRef() {
            if (mTexture != nullptr) {
                mTexture->unref(true);
            }
        }

            mTexture = texture;
            if (mTexture != nullptr) {
                mTexture->ref();
        // Makes a new SkImage from the texture content.
        // As SkImages are immutable but buffer content is not, we create
        // a new SkImage every time.
        sk_sp<SkImage> makeImage(ui::Dataspace dataspace, SkAlphaType alphaType,
                                 GrDirectContext* context) {
            return mTexture->makeImage(dataspace, alphaType, context);
        }

        // Makes a new SkSurface from the texture content, if needed.
        sk_sp<SkSurface> getOrCreateSurface(ui::Dataspace dataspace, GrDirectContext* context) {
            return mTexture->getOrCreateSurface(dataspace, context);
        }

        DISALLOW_COPY_AND_ASSIGN(LocalRef);

    private:
        AutoBackendTexture* mTexture = nullptr;
    };

private:
    // Creates a GrBackendTexture whose contents come from the provided buffer.
    AutoBackendTexture(GrDirectContext* context, AHardwareBuffer* buffer, bool isRender);
    AutoBackendTexture(GrDirectContext* context, AHardwareBuffer* buffer, bool isOutputBuffer);

    // The only way to invoke dtor is with unref, when mUsageCount is 0.
    ~AutoBackendTexture() {}

    void ref() { mUsageCount++; }

@@ -85,10 +93,6 @@ public:
    // Makes a new SkSurface from the texture content, if needed.
    sk_sp<SkSurface> getOrCreateSurface(ui::Dataspace dataspace, GrDirectContext* context);

private:
    // The only way to invoke dtor is with unref, when mUsageCount is 0.
    ~AutoBackendTexture() {}

    GrBackendTexture mBackendTexture;
    GrAHardwareBufferUtils::DeleteImageProc mDeleteProc;
    GrAHardwareBufferUtils::UpdateImageProc mUpdateProc;
@@ -99,6 +103,7 @@ private:

    int mUsageCount = 0;

    const bool mIsOutputBuffer;
    sk_sp<SkImage> mImage = nullptr;
    sk_sp<SkSurface> mSurface = nullptr;
    ui::Dataspace mDataspace = ui::Dataspace::UNKNOWN;
+17 −16
Original line number Diff line number Diff line
@@ -508,9 +508,9 @@ void SkiaGLRenderEngine::mapExternalTextureBuffer(const sp<GraphicBuffer>& buffe

    if (const auto& iter = cache.find(buffer->getId()); iter == cache.end()) {
        std::shared_ptr<AutoBackendTexture::LocalRef> imageTextureRef =
                std::make_shared<AutoBackendTexture::LocalRef>(
                        new AutoBackendTexture(grContext.get(), buffer->toAHardwareBuffer(),
                                               isRenderable));
                std::make_shared<AutoBackendTexture::LocalRef>(grContext.get(),
                                                               buffer->toAHardwareBuffer(),
                                                               isRenderable);
        cache.insert({buffer->getId(), imageTextureRef});
    }
    // restore the original state of the protected context if necessary
@@ -669,15 +669,17 @@ status_t SkiaGLRenderEngine::drawLayers(const DisplaySettings& display,
    if (const auto& it = cache.find(buffer->getBuffer()->getId()); it != cache.end()) {
        surfaceTextureRef = it->second;
    } else {
        surfaceTextureRef = std::make_shared<AutoBackendTexture::LocalRef>(
                new AutoBackendTexture(grContext.get(), buffer->getBuffer()->toAHardwareBuffer(),
                                       true));
        surfaceTextureRef =
                std::make_shared<AutoBackendTexture::LocalRef>(grContext.get(),
                                                               buffer->getBuffer()
                                                                       ->toAHardwareBuffer(),
                                                               true);
    }

    const ui::Dataspace dstDataspace =
            mUseColorManagement ? display.outputDataspace : ui::Dataspace::UNKNOWN;
    sk_sp<SkSurface> dstSurface =
            surfaceTextureRef->getTexture()->getOrCreateSurface(dstDataspace, grContext.get());
            surfaceTextureRef->getOrCreateSurface(dstDataspace, grContext.get());

    SkCanvas* dstCanvas = mCapture->tryCapture(dstSurface.get());
    if (dstCanvas == nullptr) {
@@ -889,16 +891,15 @@ status_t SkiaGLRenderEngine::drawLayers(const DisplaySettings& display,
                // it. If we're using skia, we're guaranteed to run on a dedicated GPU thread so if
                // we didn't find anything in the cache then we intentionally did not cache this
                // buffer's resources.
                imageTextureRef = std::make_shared<AutoBackendTexture::LocalRef>(
                        new AutoBackendTexture(grContext.get(),
                imageTextureRef = std::make_shared<
                        AutoBackendTexture::LocalRef>(grContext.get(),
                                                      item.buffer->getBuffer()->toAHardwareBuffer(),
                                               false));
                                                      false);
            }

            sk_sp<SkImage> image =
                    imageTextureRef->getTexture()->makeImage(layerDataspace,
                                                             item.usePremultipliedAlpha
                                                                     ? kPremul_SkAlphaType
                    imageTextureRef->makeImage(layerDataspace,
                                               item.usePremultipliedAlpha ? kPremul_SkAlphaType
                                                                          : kUnpremul_SkAlphaType,
                                               grContext.get());