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

Commit b20dbf6c authored by Chris Craik's avatar Chris Craik Committed by Android (Google) Code Review
Browse files

Merge "Finish shadow support in new reorderer/renderer"

parents 1ca1860f 98787e6c
Loading
Loading
Loading
Loading
+3 −1
Original line number Diff line number Diff line
@@ -206,7 +206,9 @@ LOCAL_MODULE := hwui_unit_tests
LOCAL_MODULE_TAGS := tests
LOCAL_SHARED_LIBRARIES := $(hwui_shared_libraries)
LOCAL_STATIC_LIBRARIES := libhwui_static_null_gpu
LOCAL_CFLAGS := $(hwui_cflags)
LOCAL_CFLAGS := \
        $(hwui_cflags) \
        -DHWUI_NULL_GPU

LOCAL_SRC_FILES += \
    unit_tests/CanvasStateTests.cpp \
+25 −18
Original line number Diff line number Diff line
@@ -35,11 +35,11 @@ OffscreenBuffer* BakedOpRenderer::startTemporaryLayer(uint32_t width, uint32_t h
    LOG_ALWAYS_FATAL_IF(mRenderTarget.offscreenBuffer, "already has layer...");

    OffscreenBuffer* buffer = mRenderState.layerPool().get(mRenderState, width, height);
    startRepaintLayer(buffer);
    startRepaintLayer(buffer, Rect(width, height));
    return buffer;
}

void BakedOpRenderer::startRepaintLayer(OffscreenBuffer* offscreenBuffer) {
void BakedOpRenderer::startRepaintLayer(OffscreenBuffer* offscreenBuffer, const Rect& repaintRect) {
    LOG_ALWAYS_FATAL_IF(mRenderTarget.offscreenBuffer, "already has layer...");

    mRenderTarget.offscreenBuffer = offscreenBuffer;
@@ -55,12 +55,10 @@ void BakedOpRenderer::startRepaintLayer(OffscreenBuffer* offscreenBuffer) {
    LOG_ALWAYS_FATAL_IF(glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE,
            "framebuffer incomplete!");

    // Clear the FBO
    mRenderState.scissor().setEnabled(false);
    glClear(GL_COLOR_BUFFER_BIT);

    // Change the viewport & ortho projection
    setViewport(offscreenBuffer->viewportWidth, offscreenBuffer->viewportHeight);

    clearColorBuffer(repaintRect);
}

void BakedOpRenderer::endLayer() {
@@ -74,16 +72,13 @@ void BakedOpRenderer::endLayer() {
    mRenderTarget.frameBufferId = -1;
}

void BakedOpRenderer::startFrame(uint32_t width, uint32_t height) {
void BakedOpRenderer::startFrame(uint32_t width, uint32_t height, const Rect& repaintRect) {
    mRenderState.bindFramebuffer(0);
    setViewport(width, height);
    mCaches.clearGarbage();

    if (!mOpaque) {
        // TODO: partial invalidate!
        mRenderState.scissor().setEnabled(false);
        glClear(GL_COLOR_BUFFER_BIT);
        mHasDrawn = true;
        clearColorBuffer(repaintRect);
    }
}

@@ -113,6 +108,20 @@ void BakedOpRenderer::setViewport(uint32_t width, uint32_t height) {
    mRenderState.blend().syncEnabled();
}

void BakedOpRenderer::clearColorBuffer(const Rect& rect) {
    if (Rect(mRenderTarget.viewportWidth, mRenderTarget.viewportHeight).contains(rect)) {
        // Full viewport is being cleared - disable scissor
        mRenderState.scissor().setEnabled(false);
    } else {
        // Requested rect is subset of viewport - scissor to it to avoid over-clearing
        mRenderState.scissor().setEnabled(true);
        mRenderState.scissor().set(rect.left, mRenderTarget.viewportHeight - rect.bottom,
                rect.getWidth(), rect.getHeight());
    }
    glClear(GL_COLOR_BUFFER_BIT);
    if (!mRenderTarget.frameBufferId) mHasDrawn = true;
}

Texture* BakedOpRenderer::getTexture(const SkBitmap* bitmap) {
    Texture* texture = mRenderState.assetAtlas().getEntryTexture(bitmap);
    if (!texture) {
@@ -136,7 +145,7 @@ void BakedOpRenderer::renderGlop(const BakedOpState& state, const Glop& glop) {
        mRenderTarget.offscreenBuffer->region.orSelf(dirty);
    }
    mRenderState.render(glop, mRenderTarget.orthoMatrix);
    mHasDrawn = true;
    if (!mRenderTarget.frameBufferId) mHasDrawn = true;
}

////////////////////////////////////////////////////////////////////////////////
@@ -217,7 +226,7 @@ static void renderShadow(BakedOpRenderer& renderer, const BakedOpState& state, f
    paint.setAntiAlias(true); // want to use AlphaVertex

    // The caller has made sure casterAlpha > 0.
    uint8_t ambientShadowAlpha = 128u; //TODO: mAmbientShadowAlpha;
    uint8_t ambientShadowAlpha = renderer.getLightInfo().ambientShadowAlpha;
    if (CC_UNLIKELY(Properties::overrideAmbientShadowStrength >= 0)) {
        ambientShadowAlpha = Properties::overrideAmbientShadowStrength;
    }
@@ -227,7 +236,7 @@ static void renderShadow(BakedOpRenderer& renderer, const BakedOpState& state, f
                paint, VertexBufferRenderFlags::ShadowInterp);
    }

    uint8_t spotShadowAlpha = 128u; //TODO: mSpotShadowAlpha;
    uint8_t spotShadowAlpha = renderer.getLightInfo().spotShadowAlpha;
    if (CC_UNLIKELY(Properties::overrideSpotShadowStrength >= 0)) {
        spotShadowAlpha = Properties::overrideSpotShadowStrength;
    }
@@ -240,12 +249,10 @@ static void renderShadow(BakedOpRenderer& renderer, const BakedOpState& state, f

void BakedOpDispatcher::onShadowOp(BakedOpRenderer& renderer, const ShadowOp& op, const BakedOpState& state) {
    TessellationCache::vertexBuffer_pair_t buffers;
    Vector3 lightCenter = { 300, 300, 300 }; // TODO!
    float lightRadius = 150; // TODO!

    renderer.caches().tessellationCache.getShadowBuffers(&state.computedState.transform,
            op.localClipRect, op.casterAlpha >= 1.0f, op.casterPath,
            &op.shadowMatrixXY, &op.shadowMatrixZ, lightCenter, lightRadius,
            &op.shadowMatrixXY, &op.shadowMatrixZ,
            op.lightCenter, renderer.getLightInfo().lightRadius,
            buffers);

    renderShadow(renderer, state, op.casterAlpha, buffers.first, buffers.second);
+18 −4
Original line number Diff line number Diff line
@@ -39,27 +39,39 @@ class RenderState;
 */
class BakedOpRenderer {
public:
    BakedOpRenderer(Caches& caches, RenderState& renderState, bool opaque)
    /**
     * Position agnostic shadow lighting info. Used with all shadow ops in scene.
     */
    struct LightInfo {
        float lightRadius = 0;
        uint8_t ambientShadowAlpha = 0;
        uint8_t spotShadowAlpha = 0;
    };

    BakedOpRenderer(Caches& caches, RenderState& renderState, bool opaque, const LightInfo& lightInfo)
            : mRenderState(renderState)
            , mCaches(caches)
            , mOpaque(opaque) {
            , mOpaque(opaque)
            , mLightInfo(lightInfo) {
    }

    RenderState& renderState() { return mRenderState; }
    Caches& caches() { return mCaches; }

    void startFrame(uint32_t width, uint32_t height);
    void startFrame(uint32_t width, uint32_t height, const Rect& repaintRect);
    void endFrame();
    OffscreenBuffer* startTemporaryLayer(uint32_t width, uint32_t height);
    void startRepaintLayer(OffscreenBuffer* offscreenBuffer);
    void startRepaintLayer(OffscreenBuffer* offscreenBuffer, const Rect& repaintRect);
    void endLayer();

    Texture* getTexture(const SkBitmap* bitmap);
    const LightInfo& getLightInfo() { return mLightInfo; }

    void renderGlop(const BakedOpState& state, const Glop& glop);
    bool didDraw() { return mHasDrawn; }
private:
    void setViewport(uint32_t width, uint32_t height);
    void clearColorBuffer(const Rect& clearRect);

    RenderState& mRenderState;
    Caches& mCaches;
@@ -75,6 +87,8 @@ private:
        uint32_t viewportHeight = 0;
        Matrix4 orthoMatrix;
    } mRenderTarget;

    const LightInfo mLightInfo;
};

/**
+46 −16
Original line number Diff line number Diff line
@@ -18,6 +18,7 @@

#include "LayerUpdateQueue.h"
#include "RenderNode.h"
#include "renderstate/OffscreenBufferPool.h"
#include "utils/FatVector.h"
#include "utils/PaintUtils.h"

@@ -207,9 +208,10 @@ private:
};

OpReorderer::LayerReorderer::LayerReorderer(uint32_t width, uint32_t height,
        const BeginLayerOp* beginLayerOp, RenderNode* renderNode)
        const Rect& repaintRect, const BeginLayerOp* beginLayerOp, RenderNode* renderNode)
        : width(width)
        , height(height)
        , repaintRect(repaintRect)
        , offscreenBuffer(renderNode ? renderNode->getLayer() : nullptr)
        , beginLayerOp(beginLayerOp)
        , renderNode(renderNode) {}
@@ -309,15 +311,19 @@ void OpReorderer::LayerReorderer::dump() const {

OpReorderer::OpReorderer(const LayerUpdateQueue& layers, const SkRect& clip,
        uint32_t viewportWidth, uint32_t viewportHeight,
        const std::vector< sp<RenderNode> >& nodes)
        const std::vector< sp<RenderNode> >& nodes, const Vector3& lightCenter)
        : mCanvasState(*this) {
    ATRACE_NAME("prepare drawing commands");
    mLayerReorderers.emplace_back(viewportWidth, viewportHeight);
    mLayerStack.push_back(0);

    mLayerReorderers.reserve(layers.entries().size());
    mLayerStack.reserve(layers.entries().size());

    // Prepare to defer Fbo0
    mLayerReorderers.emplace_back(viewportWidth, viewportHeight, Rect(clip));
    mLayerStack.push_back(0);
    mCanvasState.initializeSaveStack(viewportWidth, viewportHeight,
            clip.fLeft, clip.fTop, clip.fRight, clip.fBottom,
            Vector3());
            lightCenter);

    // Render all layers to be updated, in order. Defer in reverse order, so that they'll be
    // updated in the order they're passed in (mLayerReorderers are issued to Renderer in reverse)
@@ -325,7 +331,8 @@ OpReorderer::OpReorderer(const LayerUpdateQueue& layers, const SkRect& clip,
        RenderNode* layerNode = layers.entries()[i].renderNode;
        const Rect& layerDamage = layers.entries()[i].damage;

        saveForLayer(layerNode->getWidth(), layerNode->getHeight(), nullptr, layerNode);
        saveForLayer(layerNode->getWidth(), layerNode->getHeight(),
                layerDamage, nullptr, layerNode);
        mCanvasState.writableSnapshot()->setClip(
                layerDamage.left, layerDamage.top, layerDamage.right, layerDamage.bottom);

@@ -345,14 +352,17 @@ OpReorderer::OpReorderer(const LayerUpdateQueue& layers, const SkRect& clip,
    }
}

OpReorderer::OpReorderer(int viewportWidth, int viewportHeight, const DisplayList& displayList)
OpReorderer::OpReorderer(int viewportWidth, int viewportHeight, const DisplayList& displayList,
        const Vector3& lightCenter)
        : mCanvasState(*this) {
    ATRACE_NAME("prepare drawing commands");
    mLayerReorderers.emplace_back(viewportWidth, viewportHeight);
    // Prepare to defer Fbo0
    mLayerReorderers.emplace_back(viewportWidth, viewportHeight,
            Rect(viewportWidth, viewportHeight));
    mLayerStack.push_back(0);

    mCanvasState.initializeSaveStack(viewportWidth, viewportHeight,
            0, 0, viewportWidth, viewportHeight, Vector3());
            0, 0, viewportWidth, viewportHeight, lightCenter);

    deferImpl(displayList);
}

@@ -508,7 +518,8 @@ void OpReorderer::deferShadow(const RenderNodeOp& casterNodeOp) {
    }

    ShadowOp* shadowOp = new (mAllocator) ShadowOp(casterNodeOp, casterAlpha, casterPath,
            mCanvasState.getLocalClipBounds());
            mCanvasState.getLocalClipBounds(),
            mCanvasState.currentSnapshot()->getRelativeLightCenter());
    BakedOpState* bakedOpState = BakedOpState::tryShadowOpConstruct(
            mAllocator, *mCanvasState.currentSnapshot(), shadowOp);
    if (CC_LIKELY(bakedOpState)) {
@@ -589,17 +600,36 @@ void OpReorderer::onSimpleRectsOp(const SimpleRectsOp& op) {
    currentLayer().deferUnmergeableOp(mAllocator, bakedStateOp, OpBatchType::Vertices);
}

void OpReorderer::saveForLayer(uint32_t layerWidth, uint32_t layerHeight,
void OpReorderer::saveForLayer(uint32_t layerWidth, uint32_t layerHeight, const Rect& repaintRect,
        const BeginLayerOp* beginLayerOp, RenderNode* renderNode) {

    auto previous = mCanvasState.currentSnapshot();
    mCanvasState.save(SkCanvas::kClip_SaveFlag | SkCanvas::kMatrix_SaveFlag);
    mCanvasState.writableSnapshot()->transform->loadIdentity();
    mCanvasState.writableSnapshot()->initializeViewport(layerWidth, layerHeight);
    mCanvasState.writableSnapshot()->roundRectClipState = nullptr;

    Vector3 lightCenter = previous->getRelativeLightCenter();
    if (renderNode) {
        Matrix4& inverse = renderNode->getLayer()->inverseTransformInWindow;
        inverse.mapPoint3d(lightCenter);
    } else {
        // Combine all transforms used to present saveLayer content:
        // parent content transform * canvas transform * bounds offset
        Matrix4 contentTransform(*previous->transform);
        contentTransform.multiply(beginLayerOp->localMatrix);
        contentTransform.translate(beginLayerOp->unmappedBounds.left, beginLayerOp->unmappedBounds.top);

        // inverse the total transform, to map light center into layer-relative space
        Matrix4 inverse;
        inverse.loadInverse(contentTransform);
        inverse.mapPoint3d(lightCenter);
    }
    mCanvasState.writableSnapshot()->setRelativeLightCenter(lightCenter);

    // create a new layer, and push its index on the stack
    mLayerStack.push_back(mLayerReorderers.size());
    mLayerReorderers.emplace_back(layerWidth, layerHeight, beginLayerOp, renderNode);
    mLayerReorderers.emplace_back(layerWidth, layerHeight, repaintRect, beginLayerOp, renderNode);
}

void OpReorderer::restoreForLayer() {
@@ -612,7 +642,7 @@ void OpReorderer::restoreForLayer() {
void OpReorderer::onBeginLayerOp(const BeginLayerOp& op) {
    const uint32_t layerWidth = (uint32_t) op.unmappedBounds.getWidth();
    const uint32_t layerHeight = (uint32_t) op.unmappedBounds.getHeight();
    saveForLayer(layerWidth, layerHeight, &op, nullptr);
    saveForLayer(layerWidth, layerHeight, Rect(layerWidth, layerHeight), &op, nullptr);
}

void OpReorderer::onEndLayerOp(const EndLayerOp& /* ignored */) {
+11 −9
Original line number Diff line number Diff line
@@ -67,13 +67,13 @@ class OpReorderer : public CanvasStateClient {
    class LayerReorderer {
    public:
        // Create LayerReorderer for Fbo0
        LayerReorderer(uint32_t width, uint32_t height)
                : LayerReorderer(width, height, nullptr, nullptr) {};
        LayerReorderer(uint32_t width, uint32_t height, const Rect& repaintRect)
                : LayerReorderer(width, height, repaintRect, nullptr, nullptr) {};

        // Create LayerReorderer for an offscreen layer, where beginLayerOp is present for a
        // saveLayer, renderNode is present for a HW layer.
        LayerReorderer(uint32_t width, uint32_t height,
                const BeginLayerOp* beginLayerOp, RenderNode* renderNode);
                const Rect& repaintRect, const BeginLayerOp* beginLayerOp, RenderNode* renderNode);

        // iterate back toward target to see if anything drawn since should overlap the new op
        // if no target, merging ops still iterate to find similar batch to insert after
@@ -101,6 +101,7 @@ class OpReorderer : public CanvasStateClient {

        const uint32_t width;
        const uint32_t height;
        const Rect repaintRect;
        OffscreenBuffer* offscreenBuffer;
        const BeginLayerOp* beginLayerOp;
        const RenderNode* renderNode;
@@ -116,14 +117,15 @@ class OpReorderer : public CanvasStateClient {

        // Maps batch ids to the most recent *non-merging* batch of that id
        OpBatch* mBatchLookup[OpBatchType::Count] = { nullptr };

    };

public:
    OpReorderer(const LayerUpdateQueue& layers, const SkRect& clip,
            uint32_t viewportWidth, uint32_t viewportHeight,
            const std::vector< sp<RenderNode> >& nodes);
            const std::vector< sp<RenderNode> >& nodes, const Vector3& lightCenter);

    OpReorderer(int viewportWidth, int viewportHeight, const DisplayList& displayList);
    OpReorderer(int viewportWidth, int viewportHeight, const DisplayList& displayList,
            const Vector3& lightCenter);

    virtual ~OpReorderer() {}

@@ -153,7 +155,7 @@ public:
            LayerReorderer& layer = mLayerReorderers[i];
            if (layer.renderNode) {
                // cached HW layer - can't skip layer if empty
                renderer.startRepaintLayer(layer.offscreenBuffer);
                renderer.startRepaintLayer(layer.offscreenBuffer, layer.repaintRect);
                layer.replayBakedOpsImpl((void*)&renderer, receivers);
                renderer.endLayer();
            } else if (!layer.empty()) { // save layer - skip entire layer if empty
@@ -164,7 +166,7 @@ public:
        }

        const LayerReorderer& fbo0 = mLayerReorderers[0];
        renderer.startFrame(fbo0.width, fbo0.height);
        renderer.startFrame(fbo0.width, fbo0.height, fbo0.repaintRect);
        fbo0.replayBakedOpsImpl((void*)&renderer, receivers);
        renderer.endFrame();
    }
@@ -188,7 +190,7 @@ private:
        Positive
    };
    void saveForLayer(uint32_t layerWidth, uint32_t layerHeight,
            const BeginLayerOp* beginLayerOp, RenderNode* renderNode);
            const Rect& repaintRect, const BeginLayerOp* beginLayerOp, RenderNode* renderNode);
    void restoreForLayer();

    LayerReorderer& currentLayer() { return mLayerReorderers[mLayerStack.back()]; }
Loading