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

#include "src/gpu/ganesh/ops/GrMeshDrawOp.h"

#include "src/gpu/ganesh/GrOpFlushState.h"
#include "src/gpu/ganesh/GrOpsRenderPass.h"
#include "src/gpu/ganesh/GrRecordingContextPriv.h"
#include "src/gpu/ganesh/GrResourceProvider.h"

GrMeshDrawOp::GrMeshDrawOp(uint32_t classID) : INHERITED(classID) {}

void GrMeshDrawOp::onPrepare(GrOpFlushState* state) { this->onPrepareDraws(state); }

void GrMeshDrawOp::createProgramInfo(GrMeshDrawTarget* target) {
    this->createProgramInfo(&target->caps(),
                            target->allocator(),
                            target->writeView(),
                            target->usesMSAASurface(),
                            target->detachAppliedClip(),
                            target->dstProxyView(),
                            target->renderPassBarriers(),
                            target->colorLoadOp());
}

bool GrMeshDrawOp::CombinedQuadCountWillOverflow(GrAAType aaType,
                                                 bool willBeUpgradedToAA,
                                                 int combinedQuadCount) {
    bool willBeAA = (aaType == GrAAType::kCoverage) || willBeUpgradedToAA;

    return combinedQuadCount > (willBeAA ? GrResourceProvider::MaxNumAAQuads()
                                         : GrResourceProvider::MaxNumNonAAQuads());
}

// This onPrepareDraws implementation assumes the derived Op only has a single programInfo -
// which is the majority of the cases.
void GrMeshDrawOp::onPrePrepareDraws(GrRecordingContext* context,
                                     const GrSurfaceProxyView& writeView,
                                     GrAppliedClip* clip,
                                     const GrDstProxyView& dstProxyView,
                                     GrXferBarrierFlags renderPassXferBarriers,
                                     GrLoadOp colorLoadOp) {
    SkArenaAlloc* arena = context->priv().recordTimeAllocator();

    // http://skbug.com/12201 -- DDL does not yet support DMSAA.
    bool usesMSAASurface = writeView.asRenderTargetProxy()->numSamples() > 1;

    // This is equivalent to a GrOpFlushState::detachAppliedClip
    GrAppliedClip appliedClip = clip ? std::move(*clip) : GrAppliedClip::Disabled();

    this->createProgramInfo(context->priv().caps(), arena, writeView, usesMSAASurface,
                            std::move(appliedClip), dstProxyView, renderPassXferBarriers,
                            colorLoadOp);

    // TODO: at this point we've created both the program info and desc in the recording context's
    // arena. In the DDL case, it would be cool if 'recordProgramInfo' could return the
    // pre-existing versions if the program has already been seen. We could then return the
    // memory for the current copy to the arena.
    context->priv().recordProgramInfo(this->programInfo());
}

//////////////////////////////////////////////////////////////////////////////

GrMeshDrawOp::PatternHelper::PatternHelper(GrMeshDrawTarget* target, GrPrimitiveType primitiveType,
                                           size_t vertexStride, sk_sp<const GrBuffer> indexBuffer,
                                           int verticesPerRepetition, int indicesPerRepetition,
                                           int repeatCount, int maxRepetitions) {
    this->init(target, primitiveType, vertexStride, std::move(indexBuffer), verticesPerRepetition,
               indicesPerRepetition, repeatCount, maxRepetitions);
}

void GrMeshDrawOp::PatternHelper::init(GrMeshDrawTarget* target, GrPrimitiveType primitiveType,
                                       size_t vertexStride, sk_sp<const GrBuffer> indexBuffer,
                                       int verticesPerRepetition, int indicesPerRepetition,
                                       int repeatCount, int maxRepetitions) {
    SkASSERT(target);
    if (!indexBuffer) {
        return;
    }
    sk_sp<const GrBuffer> vertexBuffer;
    int firstVertex;
    int vertexCount = verticesPerRepetition * repeatCount;
    fVertices = target->makeVertexSpace(vertexStride, vertexCount, &vertexBuffer, &firstVertex);
    if (!fVertices) {
        SkDebugf("Vertices could not be allocated for patterned rendering.");
        return;
    }
    SkASSERT(vertexBuffer);
    fMesh = target->allocMesh();
    fPrimitiveType = primitiveType;

    SkASSERT(maxRepetitions ==
             static_cast<int>(indexBuffer->size() / (sizeof(uint16_t) * indicesPerRepetition)));
    fMesh->setIndexedPatterned(std::move(indexBuffer), indicesPerRepetition, repeatCount,
                               maxRepetitions, std::move(vertexBuffer), verticesPerRepetition,
                               firstVertex);
}

void GrMeshDrawOp::PatternHelper::recordDraw(GrMeshDrawTarget* target,
                                             const GrGeometryProcessor* gp) const {
    target->recordDraw(gp, fMesh, 1, fPrimitiveType);
}

void GrMeshDrawOp::PatternHelper::recordDraw(
        GrMeshDrawTarget* target,
        const GrGeometryProcessor* gp,
        const GrSurfaceProxy* const primProcProxies[]) const {
    target->recordDraw(gp, fMesh, 1, primProcProxies, fPrimitiveType);
}

//////////////////////////////////////////////////////////////////////////////

GrMeshDrawOp::QuadHelper::QuadHelper(GrMeshDrawTarget* target,
                                     size_t vertexStride,
                                     int quadsToDraw) {
    sk_sp<const GrGpuBuffer> indexBuffer = target->resourceProvider()->refNonAAQuadIndexBuffer();
    if (!indexBuffer) {
        SkDebugf("Could not get quad index buffer.");
        return;
    }
    this->init(target, GrPrimitiveType::kTriangles, vertexStride, std::move(indexBuffer),
               GrResourceProvider::NumVertsPerNonAAQuad(),
               GrResourceProvider::NumIndicesPerNonAAQuad(), quadsToDraw,
               GrResourceProvider::MaxNumNonAAQuads());
}
