/*
 * Copyright 2016 Google Inc.
 *
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file.
 */

#include "InstancedRendering.h"

#include "GrBatchFlushState.h"
#include "GrCaps.h"
#include "GrPipeline.h"
#include "GrResourceProvider.h"
#include "instanced/InstanceProcessor.h"

namespace gr_instanced {

InstancedRendering::InstancedRendering(GrGpu* gpu)
    : fGpu(SkRef(gpu)),
      fState(State::kRecordingDraws),
      fDrawPool(1024 * sizeof(Batch::Draw), 1024 * sizeof(Batch::Draw)) {
}

GrDrawBatch* InstancedRendering::recordRect(const SkRect& rect, const SkMatrix& viewMatrix,
                                            GrColor color, bool antialias,
                                            const GrInstancedPipelineInfo& info, bool* useHWAA) {
    return this->recordShape(ShapeType::kRect, rect, viewMatrix, color, rect, antialias, info,
                             useHWAA);
}

GrDrawBatch* InstancedRendering::recordRect(const SkRect& rect, const SkMatrix& viewMatrix,
                                            GrColor color, const SkRect& localRect, bool antialias,
                                            const GrInstancedPipelineInfo& info, bool* useHWAA) {
    return this->recordShape(ShapeType::kRect, rect, viewMatrix, color, localRect, antialias, info,
                             useHWAA);
}

GrDrawBatch* InstancedRendering::recordRect(const SkRect& rect, const SkMatrix& viewMatrix,
                                            GrColor color, const SkMatrix& localMatrix,
                                            bool antialias, const GrInstancedPipelineInfo& info,
                                            bool* useHWAA) {
    if (localMatrix.hasPerspective()) {
        return nullptr; // Perspective is not yet supported in the local matrix.
    }
    if (Batch* batch = this->recordShape(ShapeType::kRect, rect, viewMatrix, color, rect, antialias,
                                         info, useHWAA)) {
        batch->getSingleInstance().fInfo |= kLocalMatrix_InfoFlag;
        batch->appendParamsTexel(localMatrix.getScaleX(), localMatrix.getSkewX(),
                                 localMatrix.getTranslateX());
        batch->appendParamsTexel(localMatrix.getSkewY(), localMatrix.getScaleY(),
                                 localMatrix.getTranslateY());
        batch->fInfo.fHasLocalMatrix = true;
        return batch;
    }
    return nullptr;
}

GrDrawBatch* InstancedRendering::recordOval(const SkRect& oval, const SkMatrix& viewMatrix,
                                            GrColor color, bool antialias,
                                            const GrInstancedPipelineInfo& info, bool* useHWAA) {
    return this->recordShape(ShapeType::kOval, oval, viewMatrix, color, oval, antialias, info,
                             useHWAA);
}

GrDrawBatch* InstancedRendering::recordRRect(const SkRRect& rrect, const SkMatrix& viewMatrix,
                                             GrColor color, bool antialias,
                                             const GrInstancedPipelineInfo& info, bool* useHWAA) {
    if (Batch* batch = this->recordShape(GetRRectShapeType(rrect), rrect.rect(), viewMatrix, color,
                                         rrect.rect(), antialias, info, useHWAA)) {
        batch->appendRRectParams(rrect);
        return batch;
    }
    return nullptr;
}

GrDrawBatch* InstancedRendering::recordDRRect(const SkRRect& outer, const SkRRect& inner,
                                              const SkMatrix& viewMatrix, GrColor color,
                                              bool antialias, const GrInstancedPipelineInfo& info,
                                              bool* useHWAA) {
    if (inner.getType() > SkRRect::kSimple_Type) {
       return nullptr; // Complex inner round rects are not yet supported.
    }
    if (SkRRect::kEmpty_Type == inner.getType()) {
        return this->recordRRect(outer, viewMatrix, color, antialias, info, useHWAA);
    }
    if (Batch* batch = this->recordShape(GetRRectShapeType(outer), outer.rect(), viewMatrix, color,
                                         outer.rect(), antialias, info, useHWAA)) {
        batch->appendRRectParams(outer);
        ShapeType innerShapeType = GetRRectShapeType(inner);
        batch->fInfo.fInnerShapeTypes |= GetShapeFlag(innerShapeType);
        batch->getSingleInstance().fInfo |= ((int)innerShapeType << kInnerShapeType_InfoBit);
        batch->appendParamsTexel(inner.rect().asScalars(), 4);
        batch->appendRRectParams(inner);
        return batch;
    }
    return nullptr;
}

InstancedRendering::Batch* InstancedRendering::recordShape(ShapeType type, const SkRect& bounds,
                                                           const SkMatrix& viewMatrix,
                                                           GrColor color, const SkRect& localRect,
                                                           bool antialias,
                                                           const GrInstancedPipelineInfo& info,
                                                           bool* useHWAA) {
    SkASSERT(State::kRecordingDraws == fState);

    if (info.fIsRenderingToFloat && fGpu->caps()->avoidInstancedDrawsToFPTargets()) {
        return nullptr;
    }

    AntialiasMode antialiasMode;
    if (!this->selectAntialiasMode(viewMatrix, antialias, info, useHWAA, &antialiasMode)) {
        return nullptr;
    }

    Batch* batch = this->createBatch();
    batch->fInfo.fAntialiasMode = antialiasMode;
    batch->fInfo.fShapeTypes = GetShapeFlag(type);
    batch->fInfo.fCannotDiscard = !info.fCanDiscard;

    Instance& instance = batch->getSingleInstance();
    instance.fInfo = (int)type << kShapeType_InfoBit;

    Batch::HasAABloat aaBloat = (antialiasMode == AntialiasMode::kCoverage)
                                ? Batch::HasAABloat::kYes
                                : Batch::HasAABloat::kNo;
    Batch::IsZeroArea zeroArea = (bounds.isEmpty()) ? Batch::IsZeroArea::kYes
                                                    : Batch::IsZeroArea::kNo;

    // The instanced shape renderer draws rectangles of [-1, -1, +1, +1], so we find the matrix that
    // will map this rectangle to the same device coordinates as "viewMatrix * bounds".
    float sx = 0.5f * bounds.width();
    float sy = 0.5f * bounds.height();
    float tx = sx + bounds.fLeft;
    float ty = sy + bounds.fTop;
    if (!viewMatrix.hasPerspective()) {
        float* m = instance.fShapeMatrix2x3;
        m[0] = viewMatrix.getScaleX() * sx;
        m[1] = viewMatrix.getSkewX() * sy;
        m[2] = viewMatrix.getTranslateX() +
               viewMatrix.getScaleX() * tx + viewMatrix.getSkewX() * ty;

        m[3] = viewMatrix.getSkewY() * sx;
        m[4] = viewMatrix.getScaleY() * sy;
        m[5] = viewMatrix.getTranslateY() +
               viewMatrix.getSkewY() * tx + viewMatrix.getScaleY() * ty;

        // Since 'm' is a 2x3 matrix that maps the rect [-1, +1] into the shape's device-space quad,
        // it's quite simple to find the bounding rectangle:
        float devBoundsHalfWidth = fabsf(m[0]) + fabsf(m[1]);
        float devBoundsHalfHeight = fabsf(m[3]) + fabsf(m[4]);
        SkRect batchBounds;
        batchBounds.fLeft = m[2] - devBoundsHalfWidth;
        batchBounds.fRight = m[2] + devBoundsHalfWidth;
        batchBounds.fTop = m[5] - devBoundsHalfHeight;
        batchBounds.fBottom = m[5] + devBoundsHalfHeight;
        batch->setBounds(batchBounds, aaBloat, zeroArea);

        // TODO: Is this worth the CPU overhead?
        batch->fInfo.fNonSquare =
            fabsf(devBoundsHalfHeight - devBoundsHalfWidth) > 0.5f || // Early out.
            fabs(m[0] * m[3] + m[1] * m[4]) > 1e-3f || // Skew?
            fabs(m[0] * m[0] + m[1] * m[1] - m[3] * m[3] - m[4] * m[4]) > 1e-2f; // Diff. lengths?
    } else {
        SkMatrix shapeMatrix(viewMatrix);
        shapeMatrix.preTranslate(tx, ty);
        shapeMatrix.preScale(sx, sy);
        instance.fInfo |= kPerspective_InfoFlag;

        float* m = instance.fShapeMatrix2x3;
        m[0] = SkScalarToFloat(shapeMatrix.getScaleX());
        m[1] = SkScalarToFloat(shapeMatrix.getSkewX());
        m[2] = SkScalarToFloat(shapeMatrix.getTranslateX());
        m[3] = SkScalarToFloat(shapeMatrix.getSkewY());
        m[4] = SkScalarToFloat(shapeMatrix.getScaleY());
        m[5] = SkScalarToFloat(shapeMatrix.getTranslateY());

        // Send the perspective column as a param.
        batch->appendParamsTexel(shapeMatrix[SkMatrix::kMPersp0], shapeMatrix[SkMatrix::kMPersp1],
                                 shapeMatrix[SkMatrix::kMPersp2]);
        batch->fInfo.fHasPerspective = true;

        batch->setBounds(bounds, aaBloat, zeroArea);
        batch->fInfo.fNonSquare = true;
    }

    instance.fColor = color;

    const float* rectAsFloats = localRect.asScalars(); // Ensure SkScalar == float.
    memcpy(&instance.fLocalRect, rectAsFloats, 4 * sizeof(float));

    batch->fPixelLoad = batch->bounds().height() * batch->bounds().width();
    return batch;
}

inline bool InstancedRendering::selectAntialiasMode(const SkMatrix& viewMatrix, bool antialias,
                                                    const GrInstancedPipelineInfo& info,
                                                    bool* useHWAA, AntialiasMode* antialiasMode) {
    SkASSERT(!info.fColorDisabled || info.fDrawingShapeToStencil);
    SkASSERT(!info.fIsMixedSampled || info.fIsMultisampled);
    SkASSERT(GrCaps::InstancedSupport::kNone != fGpu->caps()->instancedSupport());

    if (!info.fIsMultisampled || fGpu->caps()->multisampleDisableSupport()) {
        if (!antialias) {
            if (info.fDrawingShapeToStencil && !info.fCanDiscard) {
                // We can't draw to the stencil buffer without discard (or sample mask if MSAA).
                return false;
            }
            *antialiasMode = AntialiasMode::kNone;
            *useHWAA = false;
            return true;
        }

        if (info.canUseCoverageAA() && viewMatrix.preservesRightAngles()) {
            *antialiasMode = AntialiasMode::kCoverage;
            *useHWAA = false;
            return true;
        }
    }

    if (info.fIsMultisampled &&
        fGpu->caps()->instancedSupport() >= GrCaps::InstancedSupport::kMultisampled) {
        if (!info.fIsMixedSampled || info.fColorDisabled) {
            *antialiasMode = AntialiasMode::kMSAA;
            *useHWAA = true;
            return true;
        }
        if (fGpu->caps()->instancedSupport() >= GrCaps::InstancedSupport::kMixedSampled) {
            *antialiasMode = AntialiasMode::kMixedSamples;
            *useHWAA = true;
            return true;
        }
    }

    return false;
}

InstancedRendering::Batch::Batch(uint32_t classID, InstancedRendering* ir)
    : INHERITED(classID),
      fInstancedRendering(ir),
      fIsTracked(false),
      fNumDraws(1),
      fNumChangesInGeometry(0) {
    fHeadDraw = fTailDraw = (Draw*)fInstancedRendering->fDrawPool.allocate(sizeof(Draw));
#ifdef SK_DEBUG
    fHeadDraw->fGeometry = {-1, 0};
#endif
    fHeadDraw->fNext = nullptr;
}

InstancedRendering::Batch::~Batch() {
    if (fIsTracked) {
        fInstancedRendering->fTrackedBatches.remove(this);
    }

    Draw* draw = fHeadDraw;
    while (draw) {
        Draw* next = draw->fNext;
        fInstancedRendering->fDrawPool.release(draw);
        draw = next;
    }
}

void InstancedRendering::Batch::appendRRectParams(const SkRRect& rrect) {
    SkASSERT(!fIsTracked);
    switch (rrect.getType()) {
        case SkRRect::kSimple_Type: {
            const SkVector& radii = rrect.getSimpleRadii();
            this->appendParamsTexel(radii.x(), radii.y(), rrect.width(), rrect.height());
            return;
        }
        case SkRRect::kNinePatch_Type: {
            float twoOverW = 2 / rrect.width();
            float twoOverH = 2 / rrect.height();
            const SkVector& radiiTL = rrect.radii(SkRRect::kUpperLeft_Corner);
            const SkVector& radiiBR = rrect.radii(SkRRect::kLowerRight_Corner);
            this->appendParamsTexel(radiiTL.x() * twoOverW, radiiBR.x() * twoOverW,
                                    radiiTL.y() * twoOverH, radiiBR.y() * twoOverH);
            return;
        }
        case SkRRect::kComplex_Type: {
            /**
             * The x and y radii of each arc are stored in separate vectors,
             * in the following order:
             *
             *        __x1 _ _ _ x3__
             *    y1 |               | y2
             *
             *       |               |
             *
             *    y3 |__   _ _ _   __| y4
             *          x2       x4
             *
             */
            float twoOverW = 2 / rrect.width();
            float twoOverH = 2 / rrect.height();
            const SkVector& radiiTL = rrect.radii(SkRRect::kUpperLeft_Corner);
            const SkVector& radiiTR = rrect.radii(SkRRect::kUpperRight_Corner);
            const SkVector& radiiBR = rrect.radii(SkRRect::kLowerRight_Corner);
            const SkVector& radiiBL = rrect.radii(SkRRect::kLowerLeft_Corner);
            this->appendParamsTexel(radiiTL.x() * twoOverW, radiiBL.x() * twoOverW,
                                    radiiTR.x() * twoOverW, radiiBR.x() * twoOverW);
            this->appendParamsTexel(radiiTL.y() * twoOverH, radiiTR.y() * twoOverH,
                                    radiiBL.y() * twoOverH, radiiBR.y() * twoOverH);
            return;
        }
        default: return;
    }
}

void InstancedRendering::Batch::appendParamsTexel(const SkScalar* vals, int count) {
    SkASSERT(!fIsTracked);
    SkASSERT(count <= 4 && count >= 0);
    const float* valsAsFloats = vals; // Ensure SkScalar == float.
    memcpy(&fParams.push_back(), valsAsFloats, count * sizeof(float));
    fInfo.fHasParams = true;
}

void InstancedRendering::Batch::appendParamsTexel(SkScalar x, SkScalar y, SkScalar z, SkScalar w) {
    SkASSERT(!fIsTracked);
    ParamsTexel& texel = fParams.push_back();
    texel.fX = SkScalarToFloat(x);
    texel.fY = SkScalarToFloat(y);
    texel.fZ = SkScalarToFloat(z);
    texel.fW = SkScalarToFloat(w);
    fInfo.fHasParams = true;
}

void InstancedRendering::Batch::appendParamsTexel(SkScalar x, SkScalar y, SkScalar z) {
    SkASSERT(!fIsTracked);
    ParamsTexel& texel = fParams.push_back();
    texel.fX = SkScalarToFloat(x);
    texel.fY = SkScalarToFloat(y);
    texel.fZ = SkScalarToFloat(z);
    fInfo.fHasParams = true;
}

void InstancedRendering::Batch::computePipelineOptimizations(GrInitInvariantOutput* color,
                                                            GrInitInvariantOutput* coverage,
                                                            GrBatchToXPOverrides* overrides) const {
    color->setKnownFourComponents(this->getSingleInstance().fColor);

    if (AntialiasMode::kCoverage == fInfo.fAntialiasMode ||
        (AntialiasMode::kNone == fInfo.fAntialiasMode &&
         !fInfo.isSimpleRects() && fInfo.fCannotDiscard)) {
        coverage->setUnknownSingleComponent();
    } else {
        coverage->setKnownSingleComponent(255);
    }
}

void InstancedRendering::Batch::initBatchTracker(const GrXPOverridesForBatch& overrides) {
    Draw& draw = this->getSingleDraw(); // This will assert if we have > 1 command.
    SkASSERT(draw.fGeometry.isEmpty());
    SkASSERT(SkIsPow2(fInfo.fShapeTypes));
    SkASSERT(!fIsTracked);

    if (kRect_ShapeFlag == fInfo.fShapeTypes) {
        draw.fGeometry = InstanceProcessor::GetIndexRangeForRect(fInfo.fAntialiasMode);
    } else if (kOval_ShapeFlag == fInfo.fShapeTypes) {
        draw.fGeometry = InstanceProcessor::GetIndexRangeForOval(fInfo.fAntialiasMode,
                                                                 this->bounds());
    } else {
        draw.fGeometry = InstanceProcessor::GetIndexRangeForRRect(fInfo.fAntialiasMode);
    }

    if (!fParams.empty()) {
        SkASSERT(fInstancedRendering->fParams.count() < (int)kParamsIdx_InfoMask); // TODO: cleaner.
        this->getSingleInstance().fInfo |= fInstancedRendering->fParams.count();
        fInstancedRendering->fParams.push_back_n(fParams.count(), fParams.begin());
    }

    GrColor overrideColor;
    if (overrides.getOverrideColorIfSet(&overrideColor)) {
        SkASSERT(State::kRecordingDraws == fInstancedRendering->fState);
        this->getSingleInstance().fColor = overrideColor;
    }
    fInfo.fUsesLocalCoords = overrides.readsLocalCoords();
    fInfo.fCannotTweakAlphaForCoverage = !overrides.canTweakAlphaForCoverage();

    fInstancedRendering->fTrackedBatches.addToTail(this);
    fIsTracked = true;
}

bool InstancedRendering::Batch::onCombineIfPossible(GrBatch* other, const GrCaps& caps) {
    Batch* that = static_cast<Batch*>(other);
    SkASSERT(fInstancedRendering == that->fInstancedRendering);
    SkASSERT(fTailDraw);
    SkASSERT(that->fTailDraw);

    if (!BatchInfo::CanCombine(fInfo, that->fInfo) ||
        !GrPipeline::CanCombine(*this->pipeline(), this->bounds(),
                                *that->pipeline(), that->bounds(), caps)) {
        return false;
    }

    BatchInfo combinedInfo = fInfo | that->fInfo;
    if (!combinedInfo.isSimpleRects()) {
        // This threshold was chosen with the "shapes_mixed" bench on a MacBook with Intel graphics.
        // There seems to be a wide range where it doesn't matter if we combine or not. What matters
        // is that the itty bitty rects combine with other shapes and the giant ones don't.
        constexpr SkScalar kMaxPixelsToGeneralizeRects = 256 * 256;
        if (fInfo.isSimpleRects() && fPixelLoad > kMaxPixelsToGeneralizeRects) {
            return false;
        }
        if (that->fInfo.isSimpleRects() && that->fPixelLoad > kMaxPixelsToGeneralizeRects) {
            return false;
        }
    }

    this->joinBounds(*that);
    fInfo = combinedInfo;
    fPixelLoad += that->fPixelLoad;

    // Adopt the other batch's draws.
    fNumDraws += that->fNumDraws;
    fNumChangesInGeometry += that->fNumChangesInGeometry;
    if (fTailDraw->fGeometry != that->fHeadDraw->fGeometry) {
        ++fNumChangesInGeometry;
    }
    fTailDraw->fNext = that->fHeadDraw;
    fTailDraw = that->fTailDraw;

    that->fHeadDraw = that->fTailDraw = nullptr;

    return true;
}

void InstancedRendering::beginFlush(GrResourceProvider* rp) {
    SkASSERT(State::kRecordingDraws == fState);
    fState = State::kFlushing;

    if (fTrackedBatches.isEmpty()) {
        return;
    }

    if (!fVertexBuffer) {
        fVertexBuffer.reset(InstanceProcessor::FindOrCreateVertexBuffer(fGpu));
        if (!fVertexBuffer) {
            return;
        }
    }

    if (!fIndexBuffer) {
      fIndexBuffer.reset(InstanceProcessor::FindOrCreateIndex8Buffer(fGpu));
        if (!fIndexBuffer) {
            return;
        }
    }

    if (!fParams.empty()) {
        fParamsBuffer.reset(rp->createBuffer(fParams.count() * sizeof(ParamsTexel),
                                             kTexel_GrBufferType, kDynamic_GrAccessPattern,
                                             GrResourceProvider::kNoPendingIO_Flag |
                                             GrResourceProvider::kRequireGpuMemory_Flag,
                                             fParams.begin()));
        if (!fParamsBuffer) {
            return;
        }
    }

    this->onBeginFlush(rp);
}

void InstancedRendering::Batch::onDraw(GrBatchFlushState* state) {
    SkASSERT(State::kFlushing == fInstancedRendering->fState);
    SkASSERT(state->gpu() == fInstancedRendering->gpu());

    state->gpu()->handleDirtyContext();
    if (GrXferBarrierType barrierType = this->pipeline()->xferBarrierType(*state->gpu()->caps())) {
        state->gpu()->xferBarrier(this->pipeline()->getRenderTarget(), barrierType);
    }

    InstanceProcessor instProc(fInfo, fInstancedRendering->fParamsBuffer);
    fInstancedRendering->onDraw(*this->pipeline(), instProc, this);
}

void InstancedRendering::endFlush() {
    // The caller is expected to delete all tracked batches (i.e. batches whose initBatchTracker
    // method has been called) before ending the flush.
    SkASSERT(fTrackedBatches.isEmpty());
    fParams.reset();
    fParamsBuffer.reset();
    this->onEndFlush();
    fState = State::kRecordingDraws;
    // Hold on to the shape coords and index buffers.
}

void InstancedRendering::resetGpuResources(ResetType resetType) {
    fVertexBuffer.reset();
    fIndexBuffer.reset();
    fParamsBuffer.reset();
    this->onResetGpuResources(resetType);
}

}
