Esempio n. 1
0
void GrGpu::releaseReservedVertexSpace() {
    const GeometrySrcState& geoSrc = this->getGeomSrc();
    GrAssert(kReserved_GeometrySrcType == geoSrc.fVertexSrc);
    size_t bytes = geoSrc.fVertexCount * VertexSize(geoSrc.fVertexLayout);
    fVertexPool->putBack(bytes);
    --fVertexPoolUseCnt;
}
Esempio n. 2
0
void GrDrawTarget::drawNonIndexed(GrPrimitiveType type,
                                  int startVertex,
                                  int vertexCount) {
#if GR_DEBUG
    GeometrySrcState& geoSrc = fGeoSrcStateStack.back();
    int maxVertex = startVertex + vertexCount;
    int maxValidVertex;
    switch (geoSrc.fVertexSrc) {
        case kNone_GeometrySrcType:
            GrCrash("Attempting to draw non-indexed geom without vertex src.");
        case kReserved_GeometrySrcType: // fallthrough
        case kArray_GeometrySrcType:
            maxValidVertex = geoSrc.fVertexCount;
            break;
        case kBuffer_GeometrySrcType:
            maxValidVertex = geoSrc.fVertexBuffer->sizeInBytes() /
            VertexSize(geoSrc.fVertexLayout);
            break;
    }
    if (maxVertex > maxValidVertex) {
        GrCrash("Non-indexed drawing outside valid vertex range.");
    }
#endif
    if (vertexCount > 0) {
        this->onDrawNonIndexed(type, startVertex, vertexCount);
    }
}
Esempio n. 3
0
    void VertexArray::RegisterToGPU()
    {
        glDeleteVertexArrays(1, &mVAO);
        glGenVertexArrays(1, &mVAO);
        mVBO.Init();

        mVertexSize = VertexSize();

        Bind();
        {
            mVBO.Bind();

            int offset = 0;
            for(const VertexAttribDef &attrib : mVertAttribs)
            {
                glEnableVertexAttribArray(attrib.index);
                glVertexAttribPointer(
                    attrib.index,
                    attrib.size,
                    attrib.type,
                    attrib.normalized,
                    mVertexSize,
                    (void*)offset);
                offset += attrib.SizeInBytes();
            }

        }
        UnBind();
    }
Esempio n. 4
0
Mesh::Mesh(const void *vertex_data, int count, int vertex_size,
           const Attribute *format, vec3 *max_position, vec3 *min_position)
    : vertex_size_(vertex_size),
      bone_transforms_(nullptr),
      bone_global_transforms_(nullptr) {
  set_format(format);
  GL_CALL(glGenBuffers(1, &vbo_));
  GL_CALL(glBindBuffer(GL_ARRAY_BUFFER, vbo_));
  GL_CALL(glBufferData(GL_ARRAY_BUFFER, count * vertex_size, vertex_data,
                       GL_STATIC_DRAW));

  // Determine the min and max position
  if (max_position && min_position) {
    max_position_ = *max_position;
    min_position_ = *min_position;
  } else {
    auto data = static_cast<const float *>(vertex_data);
    const Attribute *attribute = format;
    data += VertexSize(attribute, kPosition3f) / sizeof(float);
    int step = vertex_size / sizeof(float);
    min_position_ = vec3(data);
    max_position_ = min_position_;
    for (int vertex = 1; vertex < count; vertex++) {
      data += step;
      min_position_ = vec3::Min(min_position_, vec3(data));
      max_position_ = vec3::Max(max_position_, vec3(data));
    }
  }
}
Esempio n. 5
0
void GrGpu::releaseVertexArray() {
    // if vertex source was array, we stowed data in the pool
    const GeometrySrcState& geoSrc = this->getGeomSrc();
    GrAssert(kArray_GeometrySrcType == geoSrc.fVertexSrc);
    size_t bytes = geoSrc.fVertexCount * VertexSize(geoSrc.fVertexLayout);
    fVertexPool->putBack(bytes);
    --fVertexPoolUseCnt;
}
Esempio n. 6
0
bool GrDrawTarget::checkDraw(GrPrimitiveType type, int startVertex,
                             int startIndex, int vertexCount,
                             int indexCount) const {
    const GrDrawState& drawState = this->getDrawState();
#if GR_DEBUG
    const GeometrySrcState& geoSrc = fGeoSrcStateStack.back();
    int maxVertex = startVertex + vertexCount;
    int maxValidVertex;
    switch (geoSrc.fVertexSrc) {
        case kNone_GeometrySrcType:
            GrCrash("Attempting to draw without vertex src.");
        case kReserved_GeometrySrcType: // fallthrough
        case kArray_GeometrySrcType:
            maxValidVertex = geoSrc.fVertexCount;
            break;
        case kBuffer_GeometrySrcType:
            maxValidVertex = geoSrc.fVertexBuffer->sizeInBytes() / VertexSize(geoSrc.fVertexLayout);
            break;
    }
    if (maxVertex > maxValidVertex) {
        GrCrash("Drawing outside valid vertex range.");
    }
    if (indexCount > 0) {
        int maxIndex = startIndex + indexCount;
        int maxValidIndex;
        switch (geoSrc.fIndexSrc) {
            case kNone_GeometrySrcType:
                GrCrash("Attempting to draw indexed geom without index src.");
            case kReserved_GeometrySrcType: // fallthrough
            case kArray_GeometrySrcType:
                maxValidIndex = geoSrc.fIndexCount;
                break;
            case kBuffer_GeometrySrcType:
                maxValidIndex = geoSrc.fIndexBuffer->sizeInBytes() / sizeof(uint16_t);
                break;
        }
        if (maxIndex > maxValidIndex) {
            GrCrash("Index reads outside valid index range.");
        }
    }

    GrAssert(NULL != drawState.getRenderTarget());
    for (int s = 0; s < GrDrawState::kNumStages; ++s) {
        if (drawState.isStageEnabled(s)) {
            const GrEffect* effect = drawState.getStage(s).getEffect();
            int numTextures = effect->numTextures();
            for (int t = 0; t < numTextures; ++t) {
                GrTexture* texture = effect->texture(t);
                GrAssert(texture->asRenderTarget() != drawState.getRenderTarget());
            }
        }
    }
#endif
    if (NULL == drawState.getRenderTarget()) {
        return false;
    }
    return true;
}
Esempio n. 7
0
void GrInOrderDrawBuffer::releaseVertexArray() {
    GeometryPoolState& poolState = fGeoPoolStateStack.back();
    const GeometrySrcState& geoSrc = this->getGeomSrc(); 
    
    size_t reservedVertexBytes = VertexSize(geoSrc.fVertexLayout) * 
    geoSrc.fVertexCount;
    fVertexPool.putBack(reservedVertexBytes - poolState.fUsedPoolVertexBytes);
    
    poolState.fUsedPoolVertexBytes = 0;
}
Esempio n. 8
0
void GrInOrderDrawBuffer::releaseReservedVertexSpace() {
    GeometryPoolState& poolState = fGeoPoolStateStack.back();
    const GeometrySrcState& geoSrc = this->getGeomSrc(); 
    
    GrAssert(kReserved_GeometrySrcType == geoSrc.fVertexSrc);
    
    size_t reservedVertexBytes = VertexSize(geoSrc.fVertexLayout) * 
                                 geoSrc.fVertexCount;
    fVertexPool.putBack(reservedVertexBytes - 
                        poolState.fUsedPoolVertexBytes);
    poolState.fUsedPoolVertexBytes = 0;
    poolState.fPoolVertexBuffer = 0;
}
Esempio n. 9
0
void GrInOrderDrawBuffer::onDrawNonIndexed(GrPrimitiveType primitiveType,
                                           int startVertex,
                                           int vertexCount) {
    if (!vertexCount) {
        return;
    }

    fCurrQuad = 0;

    GeometryPoolState& poolState = fGeoPoolStateStack.back();

    Draw& draw = fDraws.push_back();
    draw.fPrimitiveType = primitiveType;
    draw.fStartVertex   = startVertex;
    draw.fStartIndex    = 0;
    draw.fVertexCount   = vertexCount;
    draw.fIndexCount    = 0;

    draw.fClipChanged = this->needsNewClip();
    if (draw.fClipChanged) {
        this->pushClip();
    }

    draw.fStateChanged = this->needsNewState();
    if (draw.fStateChanged) {
        this->pushState();
    }

    draw.fVertexLayout = this->getGeomSrc().fVertexLayout;
    switch (this->getGeomSrc().fVertexSrc) {
    case kBuffer_GeometrySrcType:
        draw.fVertexBuffer = this->getGeomSrc().fVertexBuffer;
        break;
    case kReserved_GeometrySrcType: // fallthrough
    case kArray_GeometrySrcType: {
        size_t vertexBytes = (vertexCount + startVertex) *
                             VertexSize(this->getGeomSrc().fVertexLayout);
        poolState.fUsedPoolVertexBytes = 
                            GrMax(poolState.fUsedPoolVertexBytes, vertexBytes);
        draw.fVertexBuffer = poolState.fPoolVertexBuffer;
        draw.fStartVertex += poolState.fPoolStartVertex;
        break;
    }
    default:
        GrCrash("unknown geom src type");
    }
    draw.fVertexBuffer->ref();
    draw.fIndexBuffer = NULL;
}
Esempio n. 10
0
void SphereMaterial::CreateVertexBuffer(ID3D11Device* device, Vertex::PosSize* vertices, UINT vertexCount, ID3D11Buffer** vertexBuffer) const
{
	D3D11_BUFFER_DESC vertexBufferDesc;
	ZeroMemory(&vertexBufferDesc, sizeof(vertexBufferDesc));
	vertexBufferDesc.ByteWidth = VertexSize() * vertexCount;
	vertexBufferDesc.Usage = D3D11_USAGE_IMMUTABLE;
	vertexBufferDesc.BindFlags = D3D11_BIND_VERTEX_BUFFER;

	D3D11_SUBRESOURCE_DATA vertexSubResourceData;
	ZeroMemory(&vertexSubResourceData, sizeof(vertexSubResourceData));
	vertexSubResourceData.pSysMem = vertices;
	if (FAILED(device->CreateBuffer(&vertexBufferDesc, &vertexSubResourceData, vertexBuffer)))
	{

	}
}
Esempio n. 11
0
void GrInOrderDrawBuffer::onDrawNonIndexed(GrPrimitiveType primitiveType,
                                           int startVertex,
                                           int vertexCount) {
    if (!vertexCount) {
        return;
    }

    this->resetDrawTracking();

    GeometryPoolState& poolState = fGeoPoolStateStack.back();
    if (this->needsNewClip()) {
        this->recordClip();
    }
    if (this->needsNewState()) {
        this->recordState();
    }

    Draw* draw = this->recordDraw();
    draw->fPrimitiveType = primitiveType;
    draw->fStartVertex   = startVertex;
    draw->fStartIndex    = 0;
    draw->fVertexCount   = vertexCount;
    draw->fIndexCount    = 0;

    draw->fVertexLayout = this->getVertexLayout();
    switch (this->getGeomSrc().fVertexSrc) {
    case kBuffer_GeometrySrcType:
        draw->fVertexBuffer = this->getGeomSrc().fVertexBuffer;
        break;
    case kReserved_GeometrySrcType: // fallthrough
    case kArray_GeometrySrcType: {
        size_t vertexBytes = (vertexCount + startVertex) *
                             VertexSize(draw->fVertexLayout);
        poolState.fUsedPoolVertexBytes =
                            GrMax(poolState.fUsedPoolVertexBytes, vertexBytes);
        draw->fVertexBuffer = poolState.fPoolVertexBuffer;
        draw->fStartVertex += poolState.fPoolStartVertex;
        break;
    }
    default:
        GrCrash("unknown geom src type");
    }
    draw->fVertexBuffer->ref();
    draw->fIndexBuffer = NULL;
}
Esempio n. 12
0
void GrInOrderDrawBuffer::releaseReservedVertexSpace() {
    GeometryPoolState& poolState = fGeoPoolStateStack.back();
    const GeometrySrcState& geoSrc = this->getGeomSrc(); 
    
    GrAssert(kReserved_GeometrySrcType == geoSrc.fVertexSrc);

    // When the caller reserved vertex buffer space we gave it back a pointer
    // provided by the vertex buffer pool. At each draw we tracked the largest
    // offset into the pool's pointer that was referenced. Now we return to the
    // pool any portion at the tail of the allocation that no draw referenced.
    size_t reservedVertexBytes = VertexSize(geoSrc.fVertexLayout) *
                                 geoSrc.fVertexCount;
    fVertexPool.putBack(reservedVertexBytes - 
                        poolState.fUsedPoolVertexBytes);
    poolState.fUsedPoolVertexBytes = 0;
    poolState.fPoolVertexBuffer = NULL;
    poolState.fPoolStartVertex = 0;
}
Esempio n. 13
0
void GrInOrderDrawBuffer::geometrySourceWillPop(
                                        const GeometrySrcState& restoredState) {
    GrAssert(fGeoPoolStateStack.count() > 1);
    fGeoPoolStateStack.pop_back();
    GeometryPoolState& poolState = fGeoPoolStateStack.back();
    // we have to assume that any slack we had in our vertex/index data
    // is now unreleasable because data may have been appended later in the
    // pool.
    if (kReserved_GeometrySrcType == restoredState.fVertexSrc ||
        kArray_GeometrySrcType == restoredState.fVertexSrc) {
        poolState.fUsedPoolVertexBytes = 
            VertexSize(restoredState.fVertexLayout) * 
            restoredState.fVertexCount;
    }
    if (kReserved_GeometrySrcType == restoredState.fIndexSrc ||
        kArray_GeometrySrcType == restoredState.fIndexSrc) {
        poolState.fUsedPoolVertexBytes = sizeof(uint16_t) * 
                                         restoredState.fIndexCount;
    }
}
Esempio n. 14
0
bool GrGpu::acquireGeometryHelper(GrVertexLayout vertexLayout,
                                  void**         vertices,
                                  void**         indices) {
    GrAssert(!fReservedGeometry.fLocked);
    size_t reservedVertexSpace = 0;

    if (fReservedGeometry.fVertexCount) {
        GrAssert(NULL != vertices);

        this->prepareVertexPool();

        *vertices = fVertexPool->makeSpace(vertexLayout,
                                           fReservedGeometry.fVertexCount,
                                           &fCurrPoolVertexBuffer,
                                           &fCurrPoolStartVertex);
        if (NULL == *vertices) {
            return false;
        }
        reservedVertexSpace = VertexSize(vertexLayout) *
                              fReservedGeometry.fVertexCount;
    }
    if (fReservedGeometry.fIndexCount) {
        GrAssert(NULL != indices);

        this->prepareIndexPool();

        *indices = fIndexPool->makeSpace(fReservedGeometry.fIndexCount,
                                         &fCurrPoolIndexBuffer,
                                         &fCurrPoolStartIndex);
        if (NULL == *indices) {
            fVertexPool->putBack(reservedVertexSpace);
            fCurrPoolVertexBuffer = NULL;
            return false;
        }
    }
    return true;
}
Esempio n. 15
0
	size_t VertexBufferInstance::GetSize() const
	{
		return Count() * VertexSize();
	}
Esempio n. 16
0
void GrInOrderDrawBuffer::drawRect(const GrRect& rect,
                                   const GrMatrix* matrix,
                                   StageBitfield stageEnableBitfield,
                                   const GrRect* srcRects[],
                                   const GrMatrix* srcMatrices[]) {

    GrAssert(!(NULL == fQuadIndexBuffer && fCurrQuad));
    GrAssert(!(fDraws.empty() && fCurrQuad));
    GrAssert(!(0 != fMaxQuads && NULL == fQuadIndexBuffer));

    // if we have a quad IB then either append to the previous run of
    // rects or start a new run
    if (fMaxQuads) {

        bool appendToPreviousDraw = false;
        GrVertexLayout layout = GetRectVertexLayout(stageEnableBitfield, srcRects);
        AutoReleaseGeometry geo(this, layout, 4, 0);
        AutoViewMatrixRestore avmr(this);
        GrMatrix combinedMatrix = this->getViewMatrix();
        this->setViewMatrix(GrMatrix::I());
        if (NULL != matrix) {
            combinedMatrix.preConcat(*matrix);
        }

        SetRectVertices(rect, &combinedMatrix, srcRects, srcMatrices, layout, geo.vertices());

        // we don't want to miss an opportunity to batch rects together
        // simply because the clip has changed if the clip doesn't affect
        // the rect.
        bool disabledClip = false;
        if (this->isClipState() && fClip.isRect()) {

            GrRect clipRect = fClip.getRect(0);
            // If the clip rect touches the edge of the viewport, extended it
            // out (close) to infinity to avoid bogus intersections.
            // We might consider a more exact clip to viewport if this
            // conservative test fails.
            const GrRenderTarget* target = this->getRenderTarget();
            if (0 >= clipRect.fLeft) {
                clipRect.fLeft = GR_ScalarMin;
            }
            if (target->width() <= clipRect.fRight) {
                clipRect.fRight = GR_ScalarMax;
            }
            if (0 >= clipRect.top()) {
                clipRect.fTop = GR_ScalarMin;
            }
            if (target->height() <= clipRect.fBottom) {
                clipRect.fBottom = GR_ScalarMax;
            }
            int stride = VertexSize(layout);
            bool insideClip = true;
            for (int v = 0; v < 4; ++v) {
                const GrPoint& p = *GetVertexPoint(geo.vertices(), v, stride);
                if (!clipRect.contains(p)) {
                    insideClip = false;
                    break;
                }
            }
            if (insideClip) {
                this->disableState(kClip_StateBit);
                disabledClip = true;
            }
        }
        if (!needsNewClip() && !needsNewState() && fCurrQuad > 0 &&
            fCurrQuad < fMaxQuads && layout == fLastRectVertexLayout) {

            int vsize = VertexSize(layout);

            Draw& lastDraw = fDraws.back();

            GrAssert(lastDraw.fIndexBuffer == fQuadIndexBuffer);
            GrAssert(kTriangles_PrimitiveType == lastDraw.fPrimitiveType);
            GrAssert(0 == lastDraw.fVertexCount % 4);
            GrAssert(0 == lastDraw.fIndexCount % 6);
            GrAssert(0 == lastDraw.fStartIndex);

            GeometryPoolState& poolState = fGeoPoolStateStack.back();
            bool clearSinceLastDraw =
                            fClears.count() && 
                            fClears.back().fBeforeDrawIdx == fDraws.count();

            appendToPreviousDraw =  
                !clearSinceLastDraw &&
                lastDraw.fVertexBuffer == poolState.fPoolVertexBuffer &&
                (fCurrQuad * 4 + lastDraw.fStartVertex) == poolState.fPoolStartVertex;

            if (appendToPreviousDraw) {
                lastDraw.fVertexCount += 4;
                lastDraw.fIndexCount += 6;
                fCurrQuad += 1;
                // we reserved above, so we should be the first
                // use of this vertex reserveation.
                GrAssert(0 == poolState.fUsedPoolVertexBytes);
                poolState.fUsedPoolVertexBytes = 4 * vsize;
            }
        }
        if (!appendToPreviousDraw) {
            this->setIndexSourceToBuffer(fQuadIndexBuffer);
            drawIndexed(kTriangles_PrimitiveType, 0, 0, 4, 6);
            fCurrQuad = 1;
            fLastRectVertexLayout = layout;
        }
        if (disabledClip) {
            this->enableState(kClip_StateBit);
        }
    } else {
        INHERITED::drawRect(rect, matrix, stageEnableBitfield, srcRects, srcMatrices);
    }
}
Esempio n. 17
0
void GrDrawTarget::VertexLayoutUnitTest() {
    // not necessarily exhaustive
    static bool run;
    if (!run) {
        run = true;
        for (int s = 0; s < kNumStages; ++s) {

            GrAssert(!VertexUsesStage(s, 0));
            GrAssert(-1 == VertexStageCoordOffset(s, 0));
            GrVertexLayout stageMask = 0;
            for (int t = 0; t < kMaxTexCoords; ++t) {
                stageMask |= StageTexCoordVertexLayoutBit(s,t);
            }
            GrAssert(1 == kMaxTexCoords || !check_layout(stageMask));
            GrAssert(stage_tex_coord_mask(s) == stageMask);
            stageMask |= StagePosAsTexCoordVertexLayoutBit(s);
            GrAssert(stage_mask(s) == stageMask);
            GrAssert(!check_layout(stageMask));
        }
        for (int t = 0; t < kMaxTexCoords; ++t) {
            GrVertexLayout tcMask = 0;
            GrAssert(!VertexUsesTexCoordIdx(t, 0));
            for (int s = 0; s < kNumStages; ++s) {
                tcMask |= StageTexCoordVertexLayoutBit(s,t);
                GrAssert(VertexUsesStage(s, tcMask));
                GrAssert(sizeof(GrPoint) == VertexStageCoordOffset(s, tcMask));
                GrAssert(VertexUsesTexCoordIdx(t, tcMask));
                GrAssert(2*sizeof(GrPoint) == VertexSize(tcMask));
                GrAssert(t == VertexTexCoordsForStage(s, tcMask));
                for (int s2 = s + 1; s2 < kNumStages; ++s2) {
                    GrAssert(-1 == VertexStageCoordOffset(s2, tcMask));
                    GrAssert(!VertexUsesStage(s2, tcMask));
                    GrAssert(-1 == VertexTexCoordsForStage(s2, tcMask));

                #if GR_DEBUG
                    GrVertexLayout posAsTex = tcMask | StagePosAsTexCoordVertexLayoutBit(s2);
                #endif
                    GrAssert(0 == VertexStageCoordOffset(s2, posAsTex));
                    GrAssert(VertexUsesStage(s2, posAsTex));
                    GrAssert(2*sizeof(GrPoint) == VertexSize(posAsTex));
                    GrAssert(-1 == VertexTexCoordsForStage(s2, posAsTex));
                    GrAssert(-1 == VertexEdgeOffset(posAsTex));
                }
                GrAssert(-1 == VertexEdgeOffset(tcMask));
                GrAssert(-1 == VertexColorOffset(tcMask));
                GrAssert(-1 == VertexCoverageOffset(tcMask));
            #if GR_DEBUG
                GrVertexLayout withColor = tcMask | kColor_VertexLayoutBit;
            #endif
                GrAssert(-1 == VertexCoverageOffset(withColor));
                GrAssert(2*sizeof(GrPoint) == VertexColorOffset(withColor));
                GrAssert(2*sizeof(GrPoint) + sizeof(GrColor) == VertexSize(withColor));
            #if GR_DEBUG
                GrVertexLayout withEdge = tcMask | kEdge_VertexLayoutBit;
            #endif
                GrAssert(-1 == VertexColorOffset(withEdge));
                GrAssert(2*sizeof(GrPoint) == VertexEdgeOffset(withEdge));
                GrAssert(4*sizeof(GrPoint) == VertexSize(withEdge));
            #if GR_DEBUG
                GrVertexLayout withColorAndEdge = withColor | kEdge_VertexLayoutBit;
            #endif
                GrAssert(2*sizeof(GrPoint) == VertexColorOffset(withColorAndEdge));
                GrAssert(2*sizeof(GrPoint) + sizeof(GrColor) == VertexEdgeOffset(withColorAndEdge));
                GrAssert(4*sizeof(GrPoint) + sizeof(GrColor) == VertexSize(withColorAndEdge));
            #if GR_DEBUG
                GrVertexLayout withCoverage = tcMask | kCoverage_VertexLayoutBit;
            #endif
                GrAssert(-1 == VertexColorOffset(withCoverage));
                GrAssert(2*sizeof(GrPoint) == VertexCoverageOffset(withCoverage));
                GrAssert(2*sizeof(GrPoint) + sizeof(GrColor) == VertexSize(withCoverage));
            #if GR_DEBUG
                GrVertexLayout withCoverageAndColor = tcMask | kCoverage_VertexLayoutBit |
                                                      kColor_VertexLayoutBit;
            #endif
                GrAssert(2*sizeof(GrPoint) == VertexColorOffset(withCoverageAndColor));
                GrAssert(2*sizeof(GrPoint) + sizeof(GrColor) == VertexCoverageOffset(withCoverageAndColor));
                GrAssert(2*sizeof(GrPoint) + 2 * sizeof(GrColor) == VertexSize(withCoverageAndColor));
            }
            GrAssert(tex_coord_idx_mask(t) == tcMask);
            GrAssert(check_layout(tcMask));

            int stageOffsets[kNumStages];
            int colorOffset;
            int edgeOffset;
            int coverageOffset;
            int size;
            size = VertexSizeAndOffsetsByStage(tcMask, stageOffsets, &colorOffset,
                                               &coverageOffset, &edgeOffset);
            GrAssert(2*sizeof(GrPoint) == size);
            GrAssert(-1 == colorOffset);
            GrAssert(-1 == coverageOffset);
            GrAssert(-1 == edgeOffset);
            for (int s = 0; s < kNumStages; ++s) {
                GrAssert(VertexUsesStage(s, tcMask));
                GrAssert(sizeof(GrPoint) == stageOffsets[s]);
                GrAssert(sizeof(GrPoint) == VertexStageCoordOffset(s, tcMask));
            }
        }
    }
}
Esempio n. 18
0
void GrInOrderDrawBuffer::drawRect(const GrRect& rect,
                                   const SkMatrix* matrix,
                                   const GrRect* srcRects[],
                                   const SkMatrix* srcMatrices[]) {

    GrAssert(!(NULL == fQuadIndexBuffer && fCurrQuad));
    GrAssert(!(fDraws.empty() && fCurrQuad));
    GrAssert(!(0 != fMaxQuads && NULL == fQuadIndexBuffer));

    GrDrawState* drawState = this->drawState();

    // if we have a quad IB then either append to the previous run of
    // rects or start a new run
    if (fMaxQuads) {

        bool appendToPreviousDraw = false;
        GrVertexLayout layout = GetRectVertexLayout(srcRects);

        // Batching across colors means we move the draw color into the
        // rect's vertex colors to allow greater batching (a lot of rects
        // in a row differing only in color is a common occurence in tables).
        bool batchAcrossColors = true;
        if (!this->getCaps().dualSourceBlendingSupport()) {
            for (int s = 0; s < GrDrawState::kNumStages; ++s) {
                if (this->getDrawState().isStageEnabled(s)) {
                    // We disable batching across colors when there is a texture
                    // present because (by pushing the the color to the vertices)
                    // Ganesh loses track of the rect's opacity. This, in turn, can
                    // cause some of the blending optimizations to be disabled. This
                    // becomes a huge problem on some of the smaller devices where
                    // shader derivatives and dual source blending aren't supported.
                    // In those cases paths are often drawn to a texture and then
                    // drawn as a texture (using this method). Because dual source
                    // blending is disabled (and the blend optimizations are short
                    // circuited) some of the more esoteric blend modes can no longer
                    // be supported.
                    // TODO: add tracking of batchAcrossColors's opacity
                    batchAcrossColors = false;
                    break;
                }
            }
        }

        if (batchAcrossColors) {
            layout |= kColor_VertexLayoutBit;
        }

        AutoReleaseGeometry geo(this, layout, 4, 0);
        if (!geo.succeeded()) {
            GrPrintf("Failed to get space for vertices!\n");
            return;
        }
        SkMatrix combinedMatrix = drawState->getViewMatrix();
        // We go to device space so that matrix changes allow us to concat
        // rect draws. When the caller has provided explicit source rects
        // then we don't want to modify the stages' matrices. Otherwise
        // we have to account for the view matrix change in the stage
        // matrices.
        uint32_t explicitCoordMask = 0;
        if (srcRects) {
            for (int s = 0; s < GrDrawState::kNumStages; ++s) {
                if (srcRects[s]) {
                    explicitCoordMask |= (1 << s);
                }
            }
        }
        GrDrawState::AutoDeviceCoordDraw adcd(this->drawState(), explicitCoordMask);
        if (!adcd.succeeded()) {
            return;
        }
        if (NULL != matrix) {
            combinedMatrix.preConcat(*matrix);
        }

        SetRectVertices(rect, &combinedMatrix, srcRects, srcMatrices,
                        this->getDrawState().getColor(), layout, geo.vertices());

        // Now that the paint's color is stored in the vertices set it to
        // white so that the following code can batch all the rects regardless
        // of paint color
        GrDrawState::AutoColorRestore acr(this->drawState(),
                                          batchAcrossColors ? SK_ColorWHITE
                                                            : this->getDrawState().getColor());

        // we don't want to miss an opportunity to batch rects together
        // simply because the clip has changed if the clip doesn't affect
        // the rect.
        bool disabledClip = false;

        if (drawState->isClipState()) {

            GrRect devClipRect;
            bool isIntersectionOfRects = false;

            fClip->fClipStack->getConservativeBounds(-fClip->fOrigin.fX,
                                                     -fClip->fOrigin.fY,
                                                     drawState->getRenderTarget()->width(),
                                                     drawState->getRenderTarget()->height(),
                                                     &devClipRect,
                                                     &isIntersectionOfRects);

            if (isIntersectionOfRects) {
                // If the clip rect touches the edge of the viewport, extended it
                // out (close) to infinity to avoid bogus intersections.
                // We might consider a more exact clip to viewport if this
                // conservative test fails.
                const GrRenderTarget* target = drawState->getRenderTarget();
                if (0 >= devClipRect.fLeft) {
                    devClipRect.fLeft = SK_ScalarMin;
                }
                if (target->width() <= devClipRect.fRight) {
                    devClipRect.fRight = SK_ScalarMax;
                }
                if (0 >= devClipRect.top()) {
                    devClipRect.fTop = SK_ScalarMin;
                }
                if (target->height() <= devClipRect.fBottom) {
                    devClipRect.fBottom = SK_ScalarMax;
                }
                int stride = VertexSize(layout);
                bool insideClip = true;
                for (int v = 0; v < 4; ++v) {
                    const GrPoint& p = *GetVertexPoint(geo.vertices(), v, stride);
                    if (!devClipRect.contains(p)) {
                        insideClip = false;
                        break;
                    }
                }
                if (insideClip) {
                    drawState->disableState(GrDrawState::kClip_StateBit);
                    disabledClip = true;
                }
            }
        }

        if (!this->needsNewClip() &&
            !this->needsNewState() &&
            fCurrQuad > 0 &&
            fCurrQuad < fMaxQuads &&
            layout == fLastRectVertexLayout) {

            int vsize = VertexSize(layout);

            Draw& lastDraw = fDraws.back();

            GrAssert(lastDraw.fIndexBuffer == fQuadIndexBuffer);
            GrAssert(kTriangles_GrPrimitiveType == lastDraw.fPrimitiveType);
            GrAssert(0 == lastDraw.fVertexCount % 4);
            GrAssert(0 == lastDraw.fIndexCount % 6);
            GrAssert(0 == lastDraw.fStartIndex);

            GeometryPoolState& poolState = fGeoPoolStateStack.back();

            appendToPreviousDraw =
                kDraw_Cmd == fCmds.back() &&
                lastDraw.fVertexBuffer == poolState.fPoolVertexBuffer &&
                (fCurrQuad * 4 + lastDraw.fStartVertex) == poolState.fPoolStartVertex;

            if (appendToPreviousDraw) {
                lastDraw.fVertexCount += 4;
                lastDraw.fIndexCount += 6;
                fCurrQuad += 1;
                // we reserved above, so we should be the first
                // use of this vertex reservation.
                GrAssert(0 == poolState.fUsedPoolVertexBytes);
                poolState.fUsedPoolVertexBytes = 4 * vsize;
            }
        }
        if (!appendToPreviousDraw) {
            this->setIndexSourceToBuffer(fQuadIndexBuffer);
            this->drawIndexed(kTriangles_GrPrimitiveType, 0, 0, 4, 6);
            fCurrQuad = 1;
            fLastRectVertexLayout = layout;
        }
        if (disabledClip) {
            drawState->enableState(GrDrawState::kClip_StateBit);
        }
        fInstancedDrawTracker.reset();
    } else {
        INHERITED::drawRect(rect, matrix, srcRects, srcMatrices);
    }
}
Esempio n. 19
0
void GrDrawTarget::VertexLayoutUnitTest() {
    // Ensure that our globals mask arrays are correct
    GrVertexLayout stageTexCoordMasks[GrDrawState::kNumStages];
    GrVertexLayout texCoordMasks[GrDrawState::kMaxTexCoords];
    gen_mask_arrays(stageTexCoordMasks, texCoordMasks);
    for (int s = 0; s < GrDrawState::kNumStages; ++s) {
        GrAssert(stageTexCoordMasks[s] == gStageTexCoordMasks[s]);
    }
    for (int t = 0; t < GrDrawState::kMaxTexCoords; ++t) {
        GrAssert(texCoordMasks[t] == gTexCoordMasks[t]);
    }

    // not necessarily exhaustive
    static bool run;
    if (!run) {
        run = true;
        for (int s = 0; s < GrDrawState::kNumStages; ++s) {

            GrVertexLayout stageMask = 0;
            for (int t = 0; t < GrDrawState::kMaxTexCoords; ++t) {
                stageMask |= StageTexCoordVertexLayoutBit(s,t);
            }
            GrAssert(1 == GrDrawState::kMaxTexCoords ||
                     !check_layout(stageMask));
            GrAssert(gStageTexCoordMasks[s] == stageMask);
            GrAssert(!check_layout(stageMask));
        }
        for (int t = 0; t < GrDrawState::kMaxTexCoords; ++t) {
            GrVertexLayout tcMask = 0;
            GrAssert(!VertexUsesTexCoordIdx(t, 0));
            for (int s = 0; s < GrDrawState::kNumStages; ++s) {
                tcMask |= StageTexCoordVertexLayoutBit(s,t);
                GrAssert(sizeof(GrPoint) == VertexStageCoordOffset(s, tcMask));
                GrAssert(VertexUsesTexCoordIdx(t, tcMask));
                GrAssert(2*sizeof(GrPoint) == VertexSize(tcMask));
                GrAssert(t == VertexTexCoordsForStage(s, tcMask));
                for (int s2 = s + 1; s2 < GrDrawState::kNumStages; ++s2) {
                    GrAssert(-1 == VertexTexCoordsForStage(s2, tcMask));

                #if GR_DEBUG
                    GrVertexLayout posAsTex = tcMask;
                #endif
                    GrAssert(0 == VertexStageCoordOffset(s2, posAsTex));
                    GrAssert(2*sizeof(GrPoint) == VertexSize(posAsTex));
                    GrAssert(-1 == VertexTexCoordsForStage(s2, posAsTex));
                    GrAssert(-1 == VertexEdgeOffset(posAsTex));
                }
                GrAssert(-1 == VertexEdgeOffset(tcMask));
                GrAssert(-1 == VertexColorOffset(tcMask));
                GrAssert(-1 == VertexCoverageOffset(tcMask));
            #if GR_DEBUG
                GrVertexLayout withColor = tcMask | kColor_VertexLayoutBit;
            #endif
                GrAssert(-1 == VertexCoverageOffset(withColor));
                GrAssert(2*sizeof(GrPoint) == VertexColorOffset(withColor));
                GrAssert(2*sizeof(GrPoint) + sizeof(GrColor) == VertexSize(withColor));
            #if GR_DEBUG
                GrVertexLayout withEdge = tcMask | kEdge_VertexLayoutBit;
            #endif
                GrAssert(-1 == VertexColorOffset(withEdge));
                GrAssert(2*sizeof(GrPoint) == VertexEdgeOffset(withEdge));
                GrAssert(4*sizeof(GrPoint) == VertexSize(withEdge));
            #if GR_DEBUG
                GrVertexLayout withColorAndEdge = withColor | kEdge_VertexLayoutBit;
            #endif
                GrAssert(2*sizeof(GrPoint) == VertexColorOffset(withColorAndEdge));
                GrAssert(2*sizeof(GrPoint) + sizeof(GrColor) == VertexEdgeOffset(withColorAndEdge));
                GrAssert(4*sizeof(GrPoint) + sizeof(GrColor) == VertexSize(withColorAndEdge));
            #if GR_DEBUG
                GrVertexLayout withCoverage = tcMask | kCoverage_VertexLayoutBit;
            #endif
                GrAssert(-1 == VertexColorOffset(withCoverage));
                GrAssert(2*sizeof(GrPoint) == VertexCoverageOffset(withCoverage));
                GrAssert(2*sizeof(GrPoint) + sizeof(GrColor) == VertexSize(withCoverage));
            #if GR_DEBUG
                GrVertexLayout withCoverageAndColor = tcMask | kCoverage_VertexLayoutBit |
                                                      kColor_VertexLayoutBit;
            #endif
                GrAssert(2*sizeof(GrPoint) == VertexColorOffset(withCoverageAndColor));
                GrAssert(2*sizeof(GrPoint) + sizeof(GrColor) == VertexCoverageOffset(withCoverageAndColor));
                GrAssert(2*sizeof(GrPoint) + 2 * sizeof(GrColor) == VertexSize(withCoverageAndColor));
            }
            GrAssert(gTexCoordMasks[t] == tcMask);
            GrAssert(check_layout(tcMask));

            int stageOffsets[GrDrawState::kNumStages];
            int colorOffset;
            int edgeOffset;
            int coverageOffset;
            int size;
            size = VertexSizeAndOffsetsByStage(tcMask,
                                               stageOffsets, &colorOffset,
                                               &coverageOffset, &edgeOffset);
            GrAssert(2*sizeof(GrPoint) == size);
            GrAssert(-1 == colorOffset);
            GrAssert(-1 == coverageOffset);
            GrAssert(-1 == edgeOffset);
            for (int s = 0; s < GrDrawState::kNumStages; ++s) {
                GrAssert(sizeof(GrPoint) == stageOffsets[s]);
                GrAssert(sizeof(GrPoint) == VertexStageCoordOffset(s, tcMask));
            }
        }
    }
}
Esempio n. 20
0
bool GrDrawTarget::checkDraw(GrPrimitiveType type, int startVertex,
                             int startIndex, int vertexCount,
                             int indexCount) const {
#if GR_DEBUG
    const GeometrySrcState& geoSrc = fGeoSrcStateStack.back();
    int maxVertex = startVertex + vertexCount;
    int maxValidVertex;
    switch (geoSrc.fVertexSrc) {
        case kNone_GeometrySrcType:
            GrCrash("Attempting to draw without vertex src.");
        case kReserved_GeometrySrcType: // fallthrough
        case kArray_GeometrySrcType:
            maxValidVertex = geoSrc.fVertexCount;
            break;
        case kBuffer_GeometrySrcType:
            maxValidVertex = geoSrc.fVertexBuffer->sizeInBytes() /
                             VertexSize(geoSrc.fVertexLayout);
            break;
    }
    if (maxVertex > maxValidVertex) {
        GrCrash("Drawing outside valid vertex range.");
    }
    if (indexCount > 0) {
        int maxIndex = startIndex + indexCount;
        int maxValidIndex;
        switch (geoSrc.fIndexSrc) {
            case kNone_GeometrySrcType:
                GrCrash("Attempting to draw indexed geom without index src.");
            case kReserved_GeometrySrcType: // fallthrough
            case kArray_GeometrySrcType:
                maxValidIndex = geoSrc.fIndexCount;
                break;
            case kBuffer_GeometrySrcType:
                maxValidIndex = geoSrc.fIndexBuffer->sizeInBytes() / sizeof(uint16_t);
                break;
        }
        if (maxIndex > maxValidIndex) {
            GrCrash("Index reads outside valid index range.");
        }
    }

    GrAssert(NULL != this->getDrawState().getRenderTarget());
    for (int i = 0; i < GrDrawState::kNumStages; ++i) {
        if (this->getDrawState().getTexture(i)) {
            GrAssert(this->getDrawState().getTexture(i)->asRenderTarget() != 
                     this->getDrawState().getRenderTarget());
        }
    }
#endif
    const GrDrawState& drawState = this->getDrawState();
    if (NULL == drawState.getRenderTarget()) {
        return false;
    }
    if (GrPixelConfigIsUnpremultiplied(drawState.getRenderTarget()->config())) {
        if (kOne_BlendCoeff != drawState.getSrcBlendCoeff() ||
            kZero_BlendCoeff != drawState.getDstBlendCoeff()) {
            return false;
        }
    }
    for (int s = 0; s < GrDrawState::kNumStages; ++s) {
        // We don't support using unpremultiplied textures with filters (other
        // than nearest). Alpha-premulling is not distributive WRT to filtering.
        // We'd have to filter each texel before filtering. We could do this for
        // our custom filters but we would also have to disable bilerp and do
        // a custom bilerp in the shader. Until Skia itself supports unpremul
        // configs there is no pressure to implement this.
        if (this->isStageEnabled(s) &&
            GrPixelConfigIsUnpremultiplied(drawState.getTexture(s)->config()) &&
            GrSamplerState::kNearest_Filter !=
            drawState.getSampler(s).getFilter()) {
            return false;
        }
    }
    return true;
}
Esempio n. 21
0
void GrInOrderDrawBuffer::drawIndexedInstances(GrPrimitiveType type,
                                               int instanceCount,
                                               int verticesPerInstance,
                                               int indicesPerInstance) {
    if (!verticesPerInstance || !indicesPerInstance) {
        return;
    }

    const GeometrySrcState& geomSrc = this->getGeomSrc();

    // we only attempt to concat the case when reserved verts are used with
    // an index buffer.
    if (kReserved_GeometrySrcType == geomSrc.fVertexSrc &&
        kBuffer_GeometrySrcType == geomSrc.fIndexSrc) {

        Draw* draw = NULL;
        // if the last draw used the same indices/vertices per shape then we
        // may be able to append to it.
        if (verticesPerInstance == fInstancedDrawTracker.fVerticesPerInstance &&
            indicesPerInstance == fInstancedDrawTracker.fIndicesPerInstance) {
            GrAssert(fDraws.count());
            draw = &fDraws.back();
        }

        bool clipChanged = this->needsNewClip();
        bool stateChanged = this->needsNewState();
        if (clipChanged) {
            this->pushClip();
        }
        if (stateChanged) {
            this->pushState();
        }

        GeometryPoolState& poolState = fGeoPoolStateStack.back();
        const GrVertexBuffer* vertexBuffer = poolState.fPoolVertexBuffer;

        // Check whether the draw is compatible with this draw in order to
        // append
        if (NULL == draw ||
            clipChanged ||
            stateChanged ||
            draw->fIndexBuffer != geomSrc.fIndexBuffer ||
            draw->fPrimitiveType != type ||
            draw->fVertexBuffer != vertexBuffer) {

            draw = &fDraws.push_back();
            draw->fClipChanged = clipChanged;
            draw->fStateChanged = stateChanged;
            draw->fIndexBuffer = geomSrc.fIndexBuffer;
            geomSrc.fIndexBuffer->ref();
            draw->fVertexBuffer = vertexBuffer;
            vertexBuffer->ref();
            draw->fPrimitiveType = type;
            draw->fStartIndex = 0;
            draw->fIndexCount = 0;
            draw->fStartVertex = poolState.fPoolStartVertex;
            draw->fVertexCount = 0;
            draw->fVertexLayout = geomSrc.fVertexLayout;
        } else {
            GrAssert(!(draw->fIndexCount % indicesPerInstance));
            GrAssert(!(draw->fVertexCount % verticesPerInstance));
            GrAssert(poolState.fPoolStartVertex == draw->fStartVertex +
                                                   draw->fVertexCount);
        }

        // how many instances can be in a single draw
        int maxInstancesPerDraw = this->indexCountInCurrentSource() /
                                  indicesPerInstance;
        if (!maxInstancesPerDraw) {
            return;
        }
        // how many instances should be concat'ed onto draw
        int instancesToConcat = maxInstancesPerDraw - draw->fVertexCount /
                                                      verticesPerInstance;
        if (maxInstancesPerDraw > instanceCount) {
            maxInstancesPerDraw = instanceCount;
            if (instancesToConcat > instanceCount) {
                instancesToConcat = instanceCount;
            }
        }

        // update the amount of reserved data actually referenced in draws
        size_t vertexBytes = instanceCount * verticesPerInstance *
                             VertexSize(draw->fVertexLayout);
        poolState.fUsedPoolVertexBytes =
                            GrMax(poolState.fUsedPoolVertexBytes, vertexBytes);

        while (instanceCount) {
            if (!instancesToConcat) {
                int startVertex = draw->fStartVertex + draw->fVertexCount;
                draw = &fDraws.push_back();
                draw->fClipChanged = false;
                draw->fStateChanged = false;
                draw->fIndexBuffer = geomSrc.fIndexBuffer;
                geomSrc.fIndexBuffer->ref();
                draw->fVertexBuffer = vertexBuffer;
                vertexBuffer->ref();
                draw->fPrimitiveType = type;
                draw->fStartIndex = 0;
                draw->fStartVertex = startVertex;
                draw->fVertexCount = 0;
                draw->fVertexLayout = geomSrc.fVertexLayout;
                instancesToConcat = maxInstancesPerDraw;
            }
            draw->fVertexCount += instancesToConcat * verticesPerInstance;
            draw->fIndexCount += instancesToConcat * indicesPerInstance;
            instanceCount -= instancesToConcat;
            instancesToConcat = 0;
        }

        // update draw tracking for next draw
        fCurrQuad = 0;
        fInstancedDrawTracker.fVerticesPerInstance = verticesPerInstance;
        fInstancedDrawTracker.fIndicesPerInstance = indicesPerInstance;
    } else {
        this->INHERITED::drawIndexedInstances(type,
                                              instanceCount,
                                              verticesPerInstance,
                                              indicesPerInstance);
    }

}