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

Commit b7d34b64 authored by Derek Sollenberger's avatar Derek Sollenberger
Browse files

Refactor pin/unpinImages to work across pipelines.

Test: existing CTS tests still pass
Change-Id: Ib2607e9853396bad42f298829b5c5da0d210af32
parent 3d36fac2
Loading
Loading
Loading
Loading
+3 −5
Original line number Original line Diff line number Diff line
@@ -25,6 +25,7 @@
#include "RecordedOp.h"
#include "RecordedOp.h"
#include "RenderNode.h"
#include "RenderNode.h"
#include "VectorDrawable.h"
#include "VectorDrawable.h"
#include "renderthread/CanvasContext.h"


namespace android {
namespace android {
namespace uirenderer {
namespace uirenderer {
@@ -105,11 +106,8 @@ void DisplayList::updateChildren(std::function<void(RenderNode*)> updateFn) {


bool DisplayList::prepareListAndChildren(TreeInfo& info, bool functorsNeedLayer,
bool DisplayList::prepareListAndChildren(TreeInfo& info, bool functorsNeedLayer,
        std::function<void(RenderNode*, TreeInfo&, bool)> childFn) {
        std::function<void(RenderNode*, TreeInfo&, bool)> childFn) {
    TextureCache& cache = Caches::getInstance().textureCache;
    info.prepareTextures = info.canvasContext.pinImages(bitmapResources);
    for (auto& bitmapResource : bitmapResources) {

        void* ownerToken = &info.canvasContext;
        info.prepareTextures = cache.prefetchAndMarkInUse(ownerToken, bitmapResource.get());
    }
    for (auto&& op : children) {
    for (auto&& op : children) {
        RenderNode* childNode = op->renderNode;
        RenderNode* childNode = op->renderNode;
        info.damageAccumulator->pushTransform(&op->localMatrix);
        info.damageAccumulator->pushTransform(&op->localMatrix);
+9 −44
Original line number Original line Diff line number Diff line
@@ -20,7 +20,7 @@
#include "VectorDrawable.h"
#include "VectorDrawable.h"


#include <SkImagePriv.h>
#include <SkImagePriv.h>
#include <SkMutex.h>



namespace android {
namespace android {
namespace uirenderer {
namespace uirenderer {
@@ -40,7 +40,7 @@ void SkiaDisplayList::syncContents() {
}
}


bool SkiaDisplayList::reuseDisplayList(RenderNode* node, renderthread::CanvasContext* context) {
bool SkiaDisplayList::reuseDisplayList(RenderNode* node, renderthread::CanvasContext* context) {
    reset(context ? context->getGrContext() : nullptr, SkRect::MakeEmpty());
    reset(SkRect::MakeEmpty());
    node->attachAvailableList(this);
    node->attachAvailableList(this);
    return true;
    return true;
}
}
@@ -53,9 +53,12 @@ void SkiaDisplayList::updateChildren(std::function<void(RenderNode*)> updateFn)


bool SkiaDisplayList::prepareListAndChildren(TreeInfo& info, bool functorsNeedLayer,
bool SkiaDisplayList::prepareListAndChildren(TreeInfo& info, bool functorsNeedLayer,
        std::function<void(RenderNode*, TreeInfo&, bool)> childFn) {
        std::function<void(RenderNode*, TreeInfo&, bool)> childFn) {
    // force all mutable images to be pinned in the GPU cache for the duration
    // If the prepare tree is triggered by the UI thread then we must force all
    // of this frame
    // mutable images to be pinned in the GPU cache until the next UI thread
    pinImages(info.canvasContext.getGrContext());
    // draw
    if (info.mode == TreeInfo::MODE_FULL) {
        info.prepareTextures = info.canvasContext.pinImages(mMutableImages);
    }


    for (auto& child : mChildNodes) {
    for (auto& child : mChildNodes) {
        RenderNode* childNode = child.getRenderNode();
        RenderNode* childNode = child.getRenderNode();
@@ -78,45 +81,7 @@ bool SkiaDisplayList::prepareListAndChildren(TreeInfo& info, bool functorsNeedLa
    return isDirty;
    return isDirty;
}
}


static std::vector<sk_sp<SkImage>> gPinnedImages;
void SkiaDisplayList::reset(SkRect bounds) {
static SkBaseMutex gLock;

void SkiaDisplayList::pinImages(GrContext* context) {
    if (mPinnedImages) return;
    for (SkImage* image : mMutableImages) {
        SkImage_pinAsTexture(image, context);
    }
    mPinnedImages = true;
}

void SkiaDisplayList::unpinImages(GrContext* context) {
    if (!mPinnedImages) return;
    if (context) {
        for (SkImage* image : mMutableImages) {
            SkImage_unpinAsTexture(image, context);
        }
    } else {
        gLock.acquire();
        for (SkImage* image : mMutableImages) {
            gPinnedImages.emplace_back(sk_ref_sp(image));
        }
        gLock.release();
    }
    mPinnedImages = false;
}

void SkiaDisplayList::cleanupImages(GrContext* context) {
    gLock.acquire();
    for (auto& image : gPinnedImages) {
        SkImage_unpinAsTexture(image.get(), context);
    }
    gPinnedImages.clear();
    gLock.release();
}

void SkiaDisplayList::reset(GrContext* context, SkRect bounds) {
    unpinImages(context);
    SkASSERT(!mPinnedImages);
    mIsProjectionReceiver = false;
    mIsProjectionReceiver = false;


    mDrawable->reset(bounds);
    mDrawable->reset(bounds);
+1 −19
Original line number Original line Diff line number Diff line
@@ -51,7 +51,7 @@ public:
     * constructed with the provided bounds.  The reuse avoids any overhead
     * constructed with the provided bounds.  The reuse avoids any overhead
     * associated with destroying the SkLiteDL as well as the deques and vectors.
     * associated with destroying the SkLiteDL as well as the deques and vectors.
     */
     */
    void reset(GrContext* context, SkRect bounds);
    void reset(SkRect bounds);


    /**
    /**
     * Use the linear allocator to create any SkDrawables needed by the display
     * Use the linear allocator to create any SkDrawables needed by the display
@@ -118,21 +118,6 @@ public:
     */
     */
    void updateChildren(std::function<void(RenderNode*)> updateFn) override;
    void updateChildren(std::function<void(RenderNode*)> updateFn) override;


    /**
     * Pin/Unpin any mutable images to the GPU cache. A pinned images is
     * guaranteed to be remain in the cache until it has been unpinned which
     * we leverage to avoid making a CPU copy of the pixels.
     */
    void pinImages(GrContext* context);
    void unpinImages(GrContext* context);

    /**
     * If a SkiaDisplayList is deleted on the UI thread we cache a list of any
     * images that need unpinned from the GPU cache and call this function on
     * a subsequent frame to perform that cleanup.
     */
    static void cleanupImages(GrContext* context);

    /**
    /**
     * We use std::deque here because (1) we need to iterate through these
     * We use std::deque here because (1) we need to iterate through these
     * elements and (2) mDrawable holds pointers to the elements, so they cannot
     * elements and (2) mDrawable holds pointers to the elements, so they cannot
@@ -145,9 +130,6 @@ public:
    sk_sp<SkLiteDL> mDrawable;
    sk_sp<SkLiteDL> mDrawable;


    bool mIsProjectionReceiver = false;
    bool mIsProjectionReceiver = false;

private:
    bool mPinnedImages = false;
};
};


}; // namespace skiapipeline
}; // namespace skiapipeline
+16 −3
Original line number Original line Diff line number Diff line
@@ -46,6 +46,22 @@ void SkiaPipeline::onDestroyHardwareResources() {
    // which will flush temporary resources over time.
    // which will flush temporary resources over time.
}
}


bool SkiaPipeline::pinImages(std::vector<SkImage*>& mutableImages) {
    for (SkImage* image : mutableImages) {
        mPinnedImages.emplace_back(sk_ref_sp(image));
        // TODO: return false if texture creation fails (see b/32691999)
        SkImage_pinAsTexture(image, mRenderThread.getGrContext());
    }
    return true;
}

void SkiaPipeline::unpinImages() {
    for (auto& image : mPinnedImages) {
        SkImage_unpinAsTexture(image.get(), mRenderThread.getGrContext());
    }
    mPinnedImages.clear();
}

void SkiaPipeline::renderLayers(const FrameBuilder::LightGeometry& lightGeometry,
void SkiaPipeline::renderLayers(const FrameBuilder::LightGeometry& lightGeometry,
        LayerUpdateQueue* layerUpdateQueue, bool opaque,
        LayerUpdateQueue* layerUpdateQueue, bool opaque,
        const BakedOpRenderer::LightInfo& lightInfo) {
        const BakedOpRenderer::LightInfo& lightInfo) {
@@ -154,9 +170,6 @@ void SkiaPipeline::renderFrame(const LayerUpdateQueue& layers, const SkRect& cli
        const std::vector<sp<RenderNode>>& nodes, bool opaque, const Rect &contentDrawBounds,
        const std::vector<sp<RenderNode>>& nodes, bool opaque, const Rect &contentDrawBounds,
        sk_sp<SkSurface> surface) {
        sk_sp<SkSurface> surface) {


    // unpin all mutable images that were attached to nodes deleted while on the UI thread
    SkiaDisplayList::cleanupImages(surface->getCanvas()->getGrContext());

    // draw all layers up front
    // draw all layers up front
    renderLayersImpl(layers, opaque);
    renderLayersImpl(layers, opaque);


+5 −0
Original line number Original line Diff line number Diff line
@@ -34,6 +34,10 @@ public:


    void onDestroyHardwareResources() override;
    void onDestroyHardwareResources() override;


    bool pinImages(std::vector<SkImage*>& mutableImages) override;
    bool pinImages(LsaVector<sk_sp<Bitmap>>& images) override { return false; }
    void unpinImages() override;

    void renderLayers(const FrameBuilder::LightGeometry& lightGeometry,
    void renderLayers(const FrameBuilder::LightGeometry& lightGeometry,
            LayerUpdateQueue* layerUpdateQueue, bool opaque,
            LayerUpdateQueue* layerUpdateQueue, bool opaque,
            const BakedOpRenderer::LightInfo& lightInfo) override;
            const BakedOpRenderer::LightInfo& lightInfo) override;
@@ -101,6 +105,7 @@ protected:


private:
private:
    TaskManager mTaskManager;
    TaskManager mTaskManager;
    std::vector<sk_sp<SkImage>> mPinnedImages;
    static float mLightRadius;
    static float mLightRadius;
    static uint8_t mAmbientShadowAlpha;
    static uint8_t mAmbientShadowAlpha;
    static uint8_t mSpotShadowAlpha;
    static uint8_t mSpotShadowAlpha;
Loading