| Index: src/gpu/instanced/GLInstancedRendering.cpp
 | 
| diff --git a/src/gpu/instanced/GLInstancedRendering.cpp b/src/gpu/instanced/GLInstancedRendering.cpp
 | 
| deleted file mode 100644
 | 
| index 7df39f07df15de889149110bb2889a9019764181..0000000000000000000000000000000000000000
 | 
| --- a/src/gpu/instanced/GLInstancedRendering.cpp
 | 
| +++ /dev/null
 | 
| @@ -1,301 +0,0 @@
 | 
| -/*
 | 
| - * 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 "GLInstancedRendering.h"
 | 
| -
 | 
| -#include "GrResourceProvider.h"
 | 
| -#include "gl/GrGLGpu.h"
 | 
| -#include "instanced/InstanceProcessor.h"
 | 
| -
 | 
| -#define GL_CALL(X) GR_GL_CALL(this->glGpu()->glInterface(), X)
 | 
| -
 | 
| -namespace gr_instanced {
 | 
| -
 | 
| -class GLInstancedRendering::GLBatch : public InstancedRendering::Batch {
 | 
| -public:
 | 
| -    DEFINE_BATCH_CLASS_ID
 | 
| -
 | 
| -    GLBatch(GLInstancedRendering* instRendering) : INHERITED(ClassID(), instRendering) {}
 | 
| -    int numGLCommands() const { return 1 + fNumChangesInGeometry; }
 | 
| -
 | 
| -private:
 | 
| -    int fEmulatedBaseInstance;
 | 
| -    int fGLDrawCmdsIdx;
 | 
| -
 | 
| -    friend class GLInstancedRendering;
 | 
| -
 | 
| -    typedef Batch INHERITED;
 | 
| -};
 | 
| -
 | 
| -GLInstancedRendering* GLInstancedRendering::CreateIfSupported(GrGLGpu* gpu) {
 | 
| -#ifndef SK_BUILD_FOR_MAC
 | 
| -    // Only whitelisting on Mac for now. Once we've been able to work through the various issues on
 | 
| -    // other platforms we can enable more generally.
 | 
| -    return nullptr;
 | 
| -#endif
 | 
| -    const GrGLCaps& glCaps = gpu->glCaps();
 | 
| -    AntialiasMode lastSupportedAAMode;
 | 
| -    if (!glCaps.vertexArrayObjectSupport() ||
 | 
| -        !glCaps.drawIndirectSupport() ||
 | 
| -        !InstanceProcessor::IsSupported(*glCaps.glslCaps(), glCaps, &lastSupportedAAMode)) {
 | 
| -        return nullptr;
 | 
| -    }
 | 
| -    return new GLInstancedRendering(gpu, lastSupportedAAMode);
 | 
| -}
 | 
| -
 | 
| -GLInstancedRendering::GLInstancedRendering(GrGLGpu* gpu, AntialiasMode lastSupportedAAMode)
 | 
| -    : INHERITED(gpu, lastSupportedAAMode, gpu->glCaps().canDrawIndirectToFloat()),
 | 
| -      fVertexArrayID(0),
 | 
| -      fGLDrawCmdsInfo(0),
 | 
| -      fInstanceAttribsBufferUniqueId(SK_InvalidUniqueID) {
 | 
| -}
 | 
| -
 | 
| -GLInstancedRendering::~GLInstancedRendering() {
 | 
| -    if (fVertexArrayID) {
 | 
| -        GL_CALL(DeleteVertexArrays(1, &fVertexArrayID));
 | 
| -        this->glGpu()->notifyVertexArrayDelete(fVertexArrayID);
 | 
| -    }
 | 
| -}
 | 
| -
 | 
| -inline GrGLGpu* GLInstancedRendering::glGpu() const {
 | 
| -    return static_cast<GrGLGpu*>(this->gpu());
 | 
| -}
 | 
| -
 | 
| -InstancedRendering::Batch* GLInstancedRendering::createBatch() {
 | 
| -    return new GLBatch(this);
 | 
| -}
 | 
| -
 | 
| -void GLInstancedRendering::onBeginFlush(GrResourceProvider* rp) {
 | 
| -    // Count what there is to draw.
 | 
| -    BatchList::Iter iter;
 | 
| -    iter.init(this->trackedBatches(), BatchList::Iter::kHead_IterStart);
 | 
| -    int numGLInstances = 0;
 | 
| -    int numGLDrawCmds = 0;
 | 
| -    while (Batch* b = iter.get()) {
 | 
| -        GLBatch* batch = static_cast<GLBatch*>(b);
 | 
| -        iter.next();
 | 
| -
 | 
| -        numGLInstances += batch->fNumDraws;
 | 
| -        numGLDrawCmds += batch->numGLCommands();
 | 
| -    }
 | 
| -    if (!numGLDrawCmds) {
 | 
| -        return;
 | 
| -    }
 | 
| -    SkASSERT(numGLInstances);
 | 
| -
 | 
| -    // Lazily create a vertex array object.
 | 
| -    if (!fVertexArrayID) {
 | 
| -        GL_CALL(GenVertexArrays(1, &fVertexArrayID));
 | 
| -        if (!fVertexArrayID) {
 | 
| -            return;
 | 
| -        }
 | 
| -        this->glGpu()->bindVertexArray(fVertexArrayID);
 | 
| -
 | 
| -        // Attach our index buffer to the vertex array.
 | 
| -        GL_CALL(BindBuffer(GR_GL_ELEMENT_ARRAY_BUFFER,
 | 
| -                           static_cast<const GrGLBuffer*>(this->indexBuffer())->bufferID()));
 | 
| -
 | 
| -        // Set up the non-instanced attribs.
 | 
| -        this->glGpu()->bindBuffer(kVertex_GrBufferType,
 | 
| -                                  static_cast<const GrGLBuffer*>(this->vertexBuffer()));
 | 
| -        GL_CALL(EnableVertexAttribArray((int)Attrib::kShapeCoords));
 | 
| -        GL_CALL(VertexAttribPointer((int)Attrib::kShapeCoords, 2, GR_GL_FLOAT, GR_GL_FALSE,
 | 
| -                                    sizeof(ShapeVertex), (void*) offsetof(ShapeVertex, fX)));
 | 
| -        GL_CALL(EnableVertexAttribArray((int)Attrib::kVertexAttrs));
 | 
| -        GL_CALL(VertexAttribIPointer((int)Attrib::kVertexAttrs, 1, GR_GL_INT, sizeof(ShapeVertex),
 | 
| -                                     (void*) offsetof(ShapeVertex, fAttrs)));
 | 
| -
 | 
| -        SkASSERT(SK_InvalidUniqueID == fInstanceAttribsBufferUniqueId);
 | 
| -    }
 | 
| -
 | 
| -    // Create and map instance and draw-indirect buffers.
 | 
| -    SkASSERT(!fInstanceBuffer);
 | 
| -    fInstanceBuffer.reset(static_cast<GrGLBuffer*>(
 | 
| -        rp->createBuffer(sizeof(Instance) * numGLInstances, kVertex_GrBufferType,
 | 
| -                         kDynamic_GrAccessPattern, GrResourceProvider::kNoPendingIO_Flag)));
 | 
| -    if (!fInstanceBuffer) {
 | 
| -        return;
 | 
| -    }
 | 
| -
 | 
| -    SkASSERT(!fDrawIndirectBuffer);
 | 
| -    fDrawIndirectBuffer.reset(static_cast<GrGLBuffer*>(
 | 
| -        rp->createBuffer(sizeof(GrGLDrawElementsIndirectCommand) * numGLDrawCmds,
 | 
| -                         kDrawIndirect_GrBufferType, kDynamic_GrAccessPattern,
 | 
| -                         GrResourceProvider::kNoPendingIO_Flag)));
 | 
| -    if (!fDrawIndirectBuffer) {
 | 
| -        return;
 | 
| -    }
 | 
| -
 | 
| -    Instance* glMappedInstances = static_cast<Instance*>(fInstanceBuffer->map());
 | 
| -    int glInstancesIdx = 0;
 | 
| -
 | 
| -    auto* glMappedCmds = static_cast<GrGLDrawElementsIndirectCommand*>(fDrawIndirectBuffer->map());
 | 
| -    int glDrawCmdsIdx = 0;
 | 
| -
 | 
| -    bool baseInstanceSupport = this->glGpu()->glCaps().baseInstanceSupport();
 | 
| -
 | 
| -    if (GR_GL_LOG_INSTANCED_BATCHES || !baseInstanceSupport) {
 | 
| -        fGLDrawCmdsInfo.reset(numGLDrawCmds);
 | 
| -    }
 | 
| -
 | 
| -    // Generate the instance and draw-indirect buffer contents based on the tracked batches.
 | 
| -    iter.init(this->trackedBatches(), BatchList::Iter::kHead_IterStart);
 | 
| -    while (Batch* b = iter.get()) {
 | 
| -        GLBatch* batch = static_cast<GLBatch*>(b);
 | 
| -        iter.next();
 | 
| -
 | 
| -        batch->fEmulatedBaseInstance = baseInstanceSupport ? 0 : glInstancesIdx;
 | 
| -        batch->fGLDrawCmdsIdx = glDrawCmdsIdx;
 | 
| -
 | 
| -        const Batch::Draw* draw = batch->fHeadDraw;
 | 
| -        SkASSERT(draw);
 | 
| -        do {
 | 
| -            int instanceCount = 0;
 | 
| -            IndexRange geometry = draw->fGeometry;
 | 
| -            SkASSERT(!geometry.isEmpty());
 | 
| -
 | 
| -            do {
 | 
| -                glMappedInstances[glInstancesIdx + instanceCount++] = draw->fInstance;
 | 
| -                draw = draw->fNext;
 | 
| -            } while (draw && draw->fGeometry == geometry);
 | 
| -
 | 
| -            GrGLDrawElementsIndirectCommand& glCmd = glMappedCmds[glDrawCmdsIdx];
 | 
| -            glCmd.fCount = geometry.fCount;
 | 
| -            glCmd.fInstanceCount = instanceCount;
 | 
| -            glCmd.fFirstIndex = geometry.fStart;
 | 
| -            glCmd.fBaseVertex = 0;
 | 
| -            glCmd.fBaseInstance = baseInstanceSupport ? glInstancesIdx : 0;
 | 
| -
 | 
| -            if (GR_GL_LOG_INSTANCED_BATCHES || !baseInstanceSupport) {
 | 
| -                fGLDrawCmdsInfo[glDrawCmdsIdx].fInstanceCount = instanceCount;
 | 
| -#if GR_GL_LOG_INSTANCED_BATCHES
 | 
| -                fGLDrawCmdsInfo[glDrawCmdsIdx].fGeometry = geometry;
 | 
| -#endif
 | 
| -            }
 | 
| -
 | 
| -            glInstancesIdx += instanceCount;
 | 
| -            ++glDrawCmdsIdx;
 | 
| -        } while (draw);
 | 
| -    }
 | 
| -
 | 
| -    SkASSERT(glDrawCmdsIdx == numGLDrawCmds);
 | 
| -    fDrawIndirectBuffer->unmap();
 | 
| -
 | 
| -    SkASSERT(glInstancesIdx == numGLInstances);
 | 
| -    fInstanceBuffer->unmap();
 | 
| -}
 | 
| -
 | 
| -void GLInstancedRendering::onDraw(const GrPipeline& pipeline, const InstanceProcessor& instProc,
 | 
| -                                  const Batch* baseBatch) {
 | 
| -    if (!fDrawIndirectBuffer) {
 | 
| -        return; // beginFlush was not successful.
 | 
| -    }
 | 
| -    if (!this->glGpu()->flushGLState(pipeline, instProc)) {
 | 
| -        return;
 | 
| -    }
 | 
| -
 | 
| -    this->glGpu()->bindBuffer(kDrawIndirect_GrBufferType, fDrawIndirectBuffer.get());
 | 
| -
 | 
| -    const GrGLCaps& glCaps = this->glGpu()->glCaps();
 | 
| -    const GLBatch* batch = static_cast<const GLBatch*>(baseBatch);
 | 
| -    int numCommands = batch->numGLCommands();
 | 
| -
 | 
| -#if GR_GL_LOG_INSTANCED_BATCHES
 | 
| -    SkASSERT(fGLDrawCmdsInfo);
 | 
| -    SkDebugf("Instanced batch: [");
 | 
| -    for (int i = 0; i < numCommands; ++i) {
 | 
| -        int glCmdIdx = batch->fGLDrawCmdsIdx + i;
 | 
| -        SkDebugf("%s%i * %s", (i ? ",  " : ""), fGLDrawCmdsInfo[glCmdIdx].fInstanceCount,
 | 
| -                 InstanceProcessor::GetNameOfIndexRange(fGLDrawCmdsInfo[glCmdIdx].fGeometry));
 | 
| -    }
 | 
| -    SkDebugf("]\n");
 | 
| -#else
 | 
| -    SkASSERT(SkToBool(fGLDrawCmdsInfo) == !glCaps.baseInstanceSupport());
 | 
| -#endif
 | 
| -
 | 
| -    if (1 == numCommands || !glCaps.baseInstanceSupport() || !glCaps.multiDrawIndirectSupport()) {
 | 
| -        int emulatedBaseInstance = batch->fEmulatedBaseInstance;
 | 
| -        for (int i = 0; i < numCommands; ++i) {
 | 
| -            int glCmdIdx = batch->fGLDrawCmdsIdx + i;
 | 
| -            this->flushInstanceAttribs(emulatedBaseInstance);
 | 
| -            GL_CALL(DrawElementsIndirect(GR_GL_TRIANGLES, GR_GL_UNSIGNED_BYTE,
 | 
| -                                         (GrGLDrawElementsIndirectCommand*) nullptr + glCmdIdx));
 | 
| -            if (!glCaps.baseInstanceSupport()) {
 | 
| -                emulatedBaseInstance += fGLDrawCmdsInfo[glCmdIdx].fInstanceCount;
 | 
| -            }
 | 
| -        }
 | 
| -    } else {
 | 
| -        int glCmdsIdx = batch->fGLDrawCmdsIdx;
 | 
| -        this->flushInstanceAttribs(batch->fEmulatedBaseInstance);
 | 
| -        GL_CALL(MultiDrawElementsIndirect(GR_GL_TRIANGLES, GR_GL_UNSIGNED_BYTE,
 | 
| -                                          (GrGLDrawElementsIndirectCommand*) nullptr + glCmdsIdx,
 | 
| -                                          numCommands, 0));
 | 
| -    }
 | 
| -}
 | 
| -
 | 
| -void GLInstancedRendering::flushInstanceAttribs(int baseInstance) {
 | 
| -    SkASSERT(fVertexArrayID);
 | 
| -    this->glGpu()->bindVertexArray(fVertexArrayID);
 | 
| -
 | 
| -    SkASSERT(fInstanceBuffer);
 | 
| -    if (fInstanceAttribsBufferUniqueId != fInstanceBuffer->getUniqueID() ||
 | 
| -        fInstanceAttribsBaseInstance != baseInstance) {
 | 
| -        Instance* offsetInBuffer = (Instance*) nullptr + baseInstance;
 | 
| -
 | 
| -        this->glGpu()->bindBuffer(kVertex_GrBufferType, fInstanceBuffer.get());
 | 
| -
 | 
| -        // Info attrib.
 | 
| -        GL_CALL(EnableVertexAttribArray((int)Attrib::kInstanceInfo));
 | 
| -        GL_CALL(VertexAttribIPointer((int)Attrib::kInstanceInfo, 1, GR_GL_UNSIGNED_INT,
 | 
| -                                     sizeof(Instance), &offsetInBuffer->fInfo));
 | 
| -        GL_CALL(VertexAttribDivisor((int)Attrib::kInstanceInfo, 1));
 | 
| -
 | 
| -        // Shape matrix attrib.
 | 
| -        GL_CALL(EnableVertexAttribArray((int)Attrib::kShapeMatrixX));
 | 
| -        GL_CALL(EnableVertexAttribArray((int)Attrib::kShapeMatrixY));
 | 
| -        GL_CALL(VertexAttribPointer((int)Attrib::kShapeMatrixX, 3, GR_GL_FLOAT, GR_GL_FALSE,
 | 
| -                                    sizeof(Instance), &offsetInBuffer->fShapeMatrix2x3[0]));
 | 
| -        GL_CALL(VertexAttribPointer((int)Attrib::kShapeMatrixY, 3, GR_GL_FLOAT, GR_GL_FALSE,
 | 
| -                                    sizeof(Instance), &offsetInBuffer->fShapeMatrix2x3[3]));
 | 
| -        GL_CALL(VertexAttribDivisor((int)Attrib::kShapeMatrixX, 1));
 | 
| -        GL_CALL(VertexAttribDivisor((int)Attrib::kShapeMatrixY, 1));
 | 
| -
 | 
| -        // Color attrib.
 | 
| -        GL_CALL(EnableVertexAttribArray((int)Attrib::kColor));
 | 
| -        GL_CALL(VertexAttribPointer((int)Attrib::kColor, 4, GR_GL_UNSIGNED_BYTE, GR_GL_TRUE,
 | 
| -                                    sizeof(Instance), &offsetInBuffer->fColor));
 | 
| -        GL_CALL(VertexAttribDivisor((int)Attrib::kColor, 1));
 | 
| -
 | 
| -        // Local rect attrib.
 | 
| -        GL_CALL(EnableVertexAttribArray((int)Attrib::kLocalRect));
 | 
| -        GL_CALL(VertexAttribPointer((int)Attrib::kLocalRect, 4, GR_GL_FLOAT, GR_GL_FALSE,
 | 
| -                                    sizeof(Instance), &offsetInBuffer->fLocalRect));
 | 
| -        GL_CALL(VertexAttribDivisor((int)Attrib::kLocalRect, 1));
 | 
| -
 | 
| -        fInstanceAttribsBufferUniqueId = fInstanceBuffer->getUniqueID();
 | 
| -        fInstanceAttribsBaseInstance = baseInstance;
 | 
| -    }
 | 
| -}
 | 
| -
 | 
| -void GLInstancedRendering::onEndFlush() {
 | 
| -    fInstanceBuffer.reset();
 | 
| -    fDrawIndirectBuffer.reset();
 | 
| -    fGLDrawCmdsInfo.reset(0);
 | 
| -}
 | 
| -
 | 
| -void GLInstancedRendering::onResetGpuResources(ResetType resetType) {
 | 
| -    if (fVertexArrayID && ResetType::kDestroy == resetType) {
 | 
| -        GL_CALL(DeleteVertexArrays(1, &fVertexArrayID));
 | 
| -        this->glGpu()->notifyVertexArrayDelete(fVertexArrayID);
 | 
| -    }
 | 
| -    fVertexArrayID = 0;
 | 
| -    fInstanceBuffer.reset();
 | 
| -    fDrawIndirectBuffer.reset();
 | 
| -    fInstanceAttribsBufferUniqueId = SK_InvalidUniqueID;
 | 
| -}
 | 
| -
 | 
| -}
 | 
| 
 |