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

#ifndef GrGLOpsRenderPass_DEFINED
#define GrGLOpsRenderPass_DEFINED

#include "src/gpu/ganesh/GrOpsRenderPass.h"

#include "src/gpu/ganesh/GrOpFlushState.h"
#include "src/gpu/ganesh/gl/GrGLGpu.h"
#include "src/gpu/ganesh/gl/GrGLRenderTarget.h"

class GrGLGpu;
class GrGLRenderTarget;

class GrGLOpsRenderPass : public GrOpsRenderPass {
/**
 * We do not actually buffer up draws or do any work in the this class for GL. Instead commands
 * are immediately sent to the gpu to execute. Thus all the commands in this class are simply
 * pass through functions to corresponding calls in the GrGLGpu class.
 */
public:
    GrGLOpsRenderPass(GrGLGpu* gpu) : fGpu(gpu) {}

    void inlineUpload(GrOpFlushState* state, GrDeferredTextureUploadFn& upload) override {
        state->doUpload(upload);
    }

    void set(GrRenderTarget*, bool useMSAASurface, const SkIRect& contentBounds, GrSurfaceOrigin,
             const LoadAndStoreInfo&, const StencilLoadAndStoreInfo&);

    void reset() {
        fRenderTarget = nullptr;
    }

private:
    GrGpu* gpu() override { return fGpu; }

    void bindInstanceBuffer(const GrBuffer*, int baseInstance);
    void bindVertexBuffer(const GrBuffer*, int baseVertex);

    const void* offsetForBaseIndex(int baseIndex) const {
        if (!fIndexPointer) {
            // nullptr != 0. Adding an offset to a nullptr is undefined.
            return (void*)(baseIndex * sizeof(uint16_t));
        }
        return fIndexPointer + baseIndex;
    }

    // Ideally we load and store DMSAA only within the content bounds of our render pass, but if
    // the caps don't allow for partial framebuffer blits, we resolve the full target.
    // We resolve the same bounds during load and store both because if we have to do a full size
    // resolve at the end, the full DMSAA attachment needs to have valid content.
    GrNativeRect dmsaaLoadStoreBounds() const;

    void onBegin() override;
    void onEnd() override;
    bool onBindPipeline(const GrProgramInfo& programInfo, const SkRect& drawBounds) override;
    void onSetScissorRect(const SkIRect& scissor) override;
    bool onBindTextures(const GrGeometryProcessor&,
                        const GrSurfaceProxy* const geomProcTextures[],
                        const GrPipeline&) override;
    void onBindBuffers(sk_sp<const GrBuffer> indexBuffer, sk_sp<const GrBuffer> instanceBuffer,
                       sk_sp<const GrBuffer> vertexBuffer, GrPrimitiveRestart) override;
    void onDraw(int vertexCount, int baseVertex) override;
    void onDrawIndexed(int indexCount, int baseIndex, uint16_t minIndexValue,
                       uint16_t maxIndexValue, int baseVertex) override;
    void onDrawInstanced(int instanceCount, int baseInstance, int vertexCount,
                         int baseVertex) override;
    void onDrawIndexedInstanced(int indexCount, int baseIndex, int instanceCount, int baseInstance,
                                int baseVertex) override;
    void onDrawIndirect(const GrBuffer* drawIndirectBuffer, size_t offset, int drawCount) override;
    void multiDrawArraysANGLEOrWebGL(const GrBuffer* drawIndirectBuffer, size_t offset,
                                     int drawCount);
    void onDrawIndexedIndirect(const GrBuffer* drawIndirectBuffer, size_t offset,
                               int drawCount) override;
    void multiDrawElementsANGLEOrWebGL(const GrBuffer* drawIndirectBuffer, size_t offset,
                                       int drawCount);
    void onClear(const GrScissorState& scissor, std::array<float, 4> color) override;
    void onClearStencilClip(const GrScissorState& scissor, bool insideStencilMask) override;

    GrGLGpu* const fGpu;

    bool fUseMultisampleFBO;
    SkIRect fContentBounds;
    LoadAndStoreInfo fColorLoadAndStoreInfo;
    StencilLoadAndStoreInfo fStencilLoadAndStoreInfo;

    // Per-pipeline state.
    GrPrimitiveType fPrimitiveType;
    GrGLAttribArrayState* fAttribArrayState = nullptr;

    // If using an index buffer, this gets set during onBindBuffers. It is either the CPU address of
    // the indices, or nullptr if they reside physically in GPU memory.
    const uint16_t* fIndexPointer;

    // This tracks whether or not we bound the respective buffers during the bindBuffers call.
    SkDEBUGCODE(bool fDidBindVertexBuffer = false;)
    SkDEBUGCODE(bool fDidBindInstanceBuffer = false;)

    using INHERITED = GrOpsRenderPass;
};

#endif
