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

Commit 14100ac9 authored by Chris Craik's avatar Chris Craik
Browse files

Glop support for custom textured UVs, simplify drawBitmap(src,dst)

Front load the scaling-to-support-shaders to record time.

Change-Id: I861c82d9d16d3c5e063cf87230127eed0b3f9b54
parent cdd35e67
Loading
Loading
Loading
Loading
+1 −3
Original line number Diff line number Diff line
@@ -713,9 +713,7 @@ public:
            mBitmap(bitmap), mSrc(srcLeft, srcTop, srcRight, srcBottom) {}

    virtual void applyDraw(OpenGLRenderer& renderer, Rect& dirty) override {
        renderer.drawBitmap(mBitmap, mSrc.left, mSrc.top, mSrc.right, mSrc.bottom,
                mLocalBounds.left, mLocalBounds.top, mLocalBounds.right, mLocalBounds.bottom,
                mPaint);
        renderer.drawBitmap(mBitmap, mSrc, mLocalBounds, mPaint);
    }

    virtual void output(int level, uint32_t logFlags) const override {
+26 −1
Original line number Diff line number Diff line
@@ -258,7 +258,8 @@ void DisplayListRenderer::drawBitmap(const SkBitmap& bitmap, float srcLeft, floa
        float srcRight, float srcBottom, float dstLeft, float dstTop,
        float dstRight, float dstBottom, const SkPaint* paint) {
    if (srcLeft == 0 && srcTop == 0
            && srcRight == bitmap.width() && srcBottom == bitmap.height()
            && srcRight == bitmap.width()
            && srcBottom == bitmap.height()
            && (srcBottom - srcTop == dstBottom - dstTop)
            && (srcRight - srcLeft == dstRight - dstLeft)) {
        // transform simple rect to rect drawing case into position bitmap ops, since they merge
@@ -269,6 +270,30 @@ void DisplayListRenderer::drawBitmap(const SkBitmap& bitmap, float srcLeft, floa
    } else {
        paint = refPaint(paint);

        if (paint && paint->getShader()) {
            float scaleX = (dstRight - dstLeft) / (srcRight - srcLeft);
            float scaleY = (dstBottom - dstTop) / (srcBottom - srcTop);
            if (!MathUtils::areEqual(scaleX, 1.0f) || !MathUtils::areEqual(scaleY, 1.0f)) {
                // Apply the scale transform on the canvas, so that the shader
                // effectively calculates positions relative to src rect space

                save(SkCanvas::kMatrix_SaveFlag);
                translate(dstLeft, dstTop);
                scale(scaleX, scaleY);

                dstLeft = 0.0f;
                dstTop = 0.0f;
                dstRight = srcRight - srcLeft;
                dstBottom = srcBottom - srcTop;

                addDrawOp(new (alloc()) DrawBitmapRectOp(refBitmap(&bitmap),
                        srcLeft, srcTop, srcRight, srcBottom,
                        dstLeft, dstTop, dstRight, dstBottom, paint));
                restore();
                return;
            }
        }

        addDrawOp(new (alloc()) DrawBitmapRectOp(refBitmap(&bitmap),
                srcLeft, srcTop, srcRight, srcBottom,
                dstLeft, dstTop, dstRight, dstBottom, paint));
+31 −16
Original line number Diff line number Diff line
@@ -32,7 +32,7 @@ namespace android {
namespace uirenderer {

#define TRIGGER_STAGE(stageFlag) \
    LOG_ALWAYS_FATAL_IF(stageFlag & mStageFlags, "Stage %d cannot be run twice"); \
    LOG_ALWAYS_FATAL_IF((stageFlag) & mStageFlags, "Stage %d cannot be run twice", (stageFlag)); \
    mStageFlags = static_cast<StageFlags>(mStageFlags | (stageFlag))

#define REQUIRE_STAGES(requiredFlags) \
@@ -40,10 +40,10 @@ namespace uirenderer {
            "not prepared for current stage")

static void setUnitQuadTextureCoords(Rect uvs, TextureVertex* quadVertex) {
    TextureVertex::setUV(quadVertex++, uvs.left, uvs.top);
    TextureVertex::setUV(quadVertex++, uvs.right, uvs.top);
    TextureVertex::setUV(quadVertex++, uvs.left, uvs.bottom);
    TextureVertex::setUV(quadVertex++, uvs.right, uvs.bottom);
    quadVertex[0] = {0, 0, uvs.left, uvs.top};
    quadVertex[1] = {1, 0, uvs.right, uvs.top};
    quadVertex[2] = {0, 1, uvs.left, uvs.bottom};
    quadVertex[3] = {1, 1, uvs.right, uvs.bottom};
}

GlopBuilder::GlopBuilder(RenderState& renderState, Caches& caches, Glop* outGlop)
@@ -74,25 +74,40 @@ GlopBuilder& GlopBuilder::setMeshUnitQuad() {
}

GlopBuilder& GlopBuilder::setMeshTexturedUnitQuad(const UvMapper* uvMapper) {
    if (uvMapper) {
        // can't use unit quad VBO, so build UV vertices manually
        return setMeshTexturedUvQuad(uvMapper, Rect(0, 0, 1, 1));
    }

    TRIGGER_STAGE(kMeshStage);

    mOutGlop->mesh.vertexFlags = kTextureCoord_Attrib;
    mOutGlop->mesh.primitiveMode = GL_TRIANGLE_STRIP;
    mOutGlop->mesh.vertexBufferObject = mRenderState.meshState().getUnitQuadVBO();
    mOutGlop->mesh.vertices = nullptr;
    mOutGlop->mesh.texCoordOffset = (GLvoid*) kMeshTextureOffset;
    mOutGlop->mesh.indexBufferObject = 0;
    mOutGlop->mesh.indices = nullptr;
    mOutGlop->mesh.elementCount = 4;
    mOutGlop->mesh.stride = kTextureVertexStride;
    mDescription.hasTexture = true;
    return *this;
}

GlopBuilder& GlopBuilder::setMeshTexturedUvQuad(const UvMapper* uvMapper, Rect uvs) {
    TRIGGER_STAGE(kMeshStage);

    mOutGlop->mesh.vertexFlags = kTextureCoord_Attrib;
    mOutGlop->mesh.primitiveMode = GL_TRIANGLE_STRIP;

    if (CC_UNLIKELY(uvMapper)) {
        Rect uvs(0, 0, 1, 1);
        uvMapper->map(uvs);
    }
    setUnitQuadTextureCoords(uvs, &mOutGlop->mesh.mappedVertices[0]);

    mOutGlop->mesh.vertexBufferObject = 0;
        mOutGlop->mesh.vertices = &mOutGlop->mesh.mappedVertices[0];
    mOutGlop->mesh.vertices = &mOutGlop->mesh.mappedVertices[0].x;
    mOutGlop->mesh.texCoordOffset = &mOutGlop->mesh.mappedVertices[0].u;
    } else {
        // standard UV coordinates, use regular unit quad VBO
        mOutGlop->mesh.vertexBufferObject = mRenderState.meshState().getUnitQuadVBO();
        mOutGlop->mesh.vertices = nullptr;
        mOutGlop->mesh.texCoordOffset = (GLvoid*) kMeshTextureOffset;
    }
    mOutGlop->mesh.indexBufferObject = 0;
    mOutGlop->mesh.indices = nullptr;
    mOutGlop->mesh.elementCount = 4;
+1 −0
Original line number Diff line number Diff line
@@ -40,6 +40,7 @@ public:

    GlopBuilder& setMeshUnitQuad();
    GlopBuilder& setMeshTexturedUnitQuad(const UvMapper* uvMapper);
    GlopBuilder& setMeshTexturedUvQuad(const UvMapper* uvMapper, const Rect uvs);
    GlopBuilder& setMeshVertexBuffer(const VertexBuffer& vertexBuffer, bool shadowInterp);
    GlopBuilder& setMeshIndexedQuads(void* vertexData, int quadCount);
    GlopBuilder& setMeshTexturedIndexedQuads(TextureVertex* vertexData, int elementCount); // TODO: take quadCount
+38 −41
Original line number Diff line number Diff line
@@ -2185,26 +2185,43 @@ void OpenGLRenderer::drawBitmapMesh(const SkBitmap* bitmap, int meshWidth, int m
    mDirty = true;
}

void OpenGLRenderer::drawBitmap(const SkBitmap* bitmap,
         float srcLeft, float srcTop, float srcRight, float srcBottom,
         float dstLeft, float dstTop, float dstRight, float dstBottom,
         const SkPaint* paint) {
    if (quickRejectSetupScissor(dstLeft, dstTop, dstRight, dstBottom)) {
void OpenGLRenderer::drawBitmap(const SkBitmap* bitmap, Rect src, Rect dst, const SkPaint* paint) {
    if (quickRejectSetupScissor(dst)) {
        return;
    }

    mCaches.textureState().activateTexture(0);
    Texture* texture = getTexture(bitmap);
    if (!texture) return;
    const AutoTexture autoCleanup(texture);

    if (USE_GLOPS) {
        Rect uv(fmax(0.0f, src.left / texture->width),
                fmax(0.0f, src.top / texture->height),
                fmin(1.0f, src.right / texture->width),
                fmin(1.0f, src.bottom / texture->height));

        bool isAlpha8Texture = bitmap->colorType() == kAlpha_8_SkColorType;
        Glop glop;
        GlopBuilder aBuilder(mRenderState, mCaches, &glop);
        aBuilder.setMeshTexturedUvQuad(texture->uvMapper, uv)
                .setFillTexturePaint(*texture, isAlpha8Texture, paint, currentSnapshot()->alpha)
                .setTransform(currentSnapshot()->getOrthoMatrix(), *currentTransform(), false)
                .setModelViewMapUnitToRectSnap(dst)
                .setRoundRectClipState(currentSnapshot()->roundRectClipState)
                .build();
        renderGlop(glop);
        return;
    }

    mCaches.textureState().activateTexture(0);

    const float width = texture->width;
    const float height = texture->height;

    float u1 = fmax(0.0f, srcLeft / width);
    float v1 = fmax(0.0f, srcTop / height);
    float u2 = fmin(1.0f, srcRight / width);
    float v2 = fmin(1.0f, srcBottom / height);
    float u1 = fmax(0.0f, src.left / width);
    float v1 = fmax(0.0f, src.top / height);
    float u2 = fmin(1.0f, src.right / width);
    float v2 = fmin(1.0f, src.bottom / height);

    getMapper(texture).map(u1, v1, u2, v2);

@@ -2213,25 +2230,21 @@ void OpenGLRenderer::drawBitmap(const SkBitmap* bitmap,

    texture->setWrap(GL_CLAMP_TO_EDGE, true);

    float scaleX = (dstRight - dstLeft) / (srcRight - srcLeft);
    float scaleY = (dstBottom - dstTop) / (srcBottom - srcTop);
    float scaleX = (dst.right - dst.left) / (src.right - src.left);
    float scaleY = (dst.bottom - dst.top) / (src.bottom - src.top);

    bool scaled = scaleX != 1.0f || scaleY != 1.0f;
    // Apply a scale transform on the canvas only when a shader is in use
    // Skia handles the ratio between the dst and src rects as a scale factor
    // when a shader is set
    bool useScaleTransform = getShader(paint) && scaled;
    bool ignoreTransform = false;

    if (CC_LIKELY(currentTransform()->isPureTranslate() && !useScaleTransform)) {
        float x = (int) floorf(dstLeft + currentTransform()->getTranslateX() + 0.5f);
        float y = (int) floorf(dstTop + currentTransform()->getTranslateY() + 0.5f);
    if (CC_LIKELY(currentTransform()->isPureTranslate())) {
        float x = (int) floorf(dst.left + currentTransform()->getTranslateX() + 0.5f);
        float y = (int) floorf(dst.top + currentTransform()->getTranslateY() + 0.5f);

        dstRight = x + (dstRight - dstLeft);
        dstBottom = y + (dstBottom - dstTop);
        dst.right = x + (dst.right - dst.left);
        dst.bottom = y + (dst.bottom - dst.top);

        dstLeft = x;
        dstTop = y;
        dst.left = x;
        dst.top = y;

        texture->setFilter(scaled ? PaintUtils::getFilter(paint) : GL_NEAREST, true);
        ignoreTransform = true;
@@ -2239,34 +2252,18 @@ void OpenGLRenderer::drawBitmap(const SkBitmap* bitmap,
        texture->setFilter(PaintUtils::getFilter(paint), true);
    }

    if (CC_UNLIKELY(useScaleTransform)) {
        save(SkCanvas::kMatrix_SaveFlag);
        translate(dstLeft, dstTop);
        scale(scaleX, scaleY);

        dstLeft = 0.0f;
        dstTop = 0.0f;

        dstRight = srcRight - srcLeft;
        dstBottom = srcBottom - srcTop;
    }

    if (CC_UNLIKELY(bitmap->colorType() == kAlpha_8_SkColorType)) {
        drawAlpha8TextureMesh(dstLeft, dstTop, dstRight, dstBottom,
        drawAlpha8TextureMesh(dst.left, dst.top, dst.right, dst.bottom,
                texture->id, paint,
                &mMeshVertices[0].x, &mMeshVertices[0].u,
                GL_TRIANGLE_STRIP, kUnitQuadCount, ignoreTransform);
    } else {
        drawTextureMesh(dstLeft, dstTop, dstRight, dstBottom,
        drawTextureMesh(dst.left, dst.top, dst.right, dst.bottom,
                texture->id, paint, texture->blend,
                &mMeshVertices[0].x, &mMeshVertices[0].u,
                GL_TRIANGLE_STRIP, kUnitQuadCount, false, ignoreTransform);
    }

    if (CC_UNLIKELY(useScaleTransform)) {
        restore();
    }

    resetDrawTextureTexCoords(0.0f, 0.0f, 1.0f, 1.0f);

    mDirty = true;
Loading