void GrInOrderDrawBuffer::onDraw(const DrawInfo& info) { GeometryPoolState& poolState = fGeoPoolStateStack.back(); const GrDrawState& drawState = this->getDrawState(); AutoClipReenable acr; if (drawState.isClipState() && info.getDevBounds() && this->quickInsideClip(*info.getDevBounds())) { acr.set(this->drawState()); } this->recordClipIfNecessary(); this->recordStateIfNecessary(); const GrVertexBuffer* vb; if (kBuffer_GeometrySrcType == this->getGeomSrc().fVertexSrc) { vb = this->getGeomSrc().fVertexBuffer; } else { vb = poolState.fPoolVertexBuffer; } const GrIndexBuffer* ib = NULL; if (info.isIndexed()) { if (kBuffer_GeometrySrcType == this->getGeomSrc().fIndexSrc) { ib = this->getGeomSrc().fIndexBuffer; } else { ib = poolState.fPoolIndexBuffer; } } Draw* draw; if (info.isInstanced()) { int instancesConcated = this->concatInstancedDraw(info); if (info.instanceCount() > instancesConcated) { draw = GrNEW_APPEND_TO_RECORDER(fCmdBuffer, Draw, (info, vb, ib)); draw->fInfo.adjustInstanceCount(-instancesConcated); } else { return; } } else { draw = GrNEW_APPEND_TO_RECORDER(fCmdBuffer, Draw, (info, vb, ib)); } this->recordTraceMarkersIfNecessary(); // Adjust the starting vertex and index when we are using reserved or array sources to // compensate for the fact that the data was inserted into a larger vb/ib owned by the pool. if (kBuffer_GeometrySrcType != this->getGeomSrc().fVertexSrc) { size_t bytes = (info.vertexCount() + info.startVertex()) * drawState.getVertexStride(); poolState.fUsedPoolVertexBytes = SkTMax(poolState.fUsedPoolVertexBytes, bytes); draw->fInfo.adjustStartVertex(poolState.fPoolStartVertex); } if (info.isIndexed() && kBuffer_GeometrySrcType != this->getGeomSrc().fIndexSrc) { size_t bytes = (info.indexCount() + info.startIndex()) * sizeof(uint16_t); poolState.fUsedPoolIndexBytes = SkTMax(poolState.fUsedPoolIndexBytes, bytes); draw->fInfo.adjustStartIndex(poolState.fPoolStartIndex); } }
void GrGpuGL::setupGeometry(const DrawInfo& info, int* startIndexOffset) { int newColorOffset; int newCoverageOffset; int newTexCoordOffsets[GrDrawState::kMaxTexCoords]; int newEdgeOffset; GrVertexLayout currLayout = this->getVertexLayout(); GrGLsizei newStride = GrDrawState::VertexSizeAndOffsetsByIdx(currLayout, newTexCoordOffsets, &newColorOffset, &newCoverageOffset, &newEdgeOffset); int oldColorOffset; int oldCoverageOffset; int oldTexCoordOffsets[GrDrawState::kMaxTexCoords]; int oldEdgeOffset; GrGLsizei oldStride = GrDrawState::VertexSizeAndOffsetsByIdx(fHWGeometryState.fVertexLayout, oldTexCoordOffsets, &oldColorOffset, &oldCoverageOffset, &oldEdgeOffset); int extraVertexOffset; this->setBuffers(info.isIndexed(), &extraVertexOffset, startIndexOffset); GrGLenum scalarType; bool texCoordNorm; if (currLayout & GrDrawState::kTextFormat_VertexLayoutBit) { scalarType = TEXT_COORDS_GL_TYPE; texCoordNorm = SkToBool(TEXT_COORDS_ARE_NORMALIZED); } else { scalarType = GR_GL_FLOAT; texCoordNorm = false; } size_t vertexOffset = (info.startVertex() + extraVertexOffset) * newStride; // all the Pointers must be set if any of these are true bool allOffsetsChange = fHWGeometryState.fArrayPtrsDirty || vertexOffset != fHWGeometryState.fVertexOffset || newStride != oldStride; // position and tex coord offsets change if above conditions are true // or the type/normalization changed based on text vs nontext type coords. bool posAndTexChange = allOffsetsChange || (((TEXT_COORDS_GL_TYPE != GR_GL_FLOAT) || TEXT_COORDS_ARE_NORMALIZED) && (GrDrawState::kTextFormat_VertexLayoutBit & (fHWGeometryState.fVertexLayout ^ currLayout))); if (posAndTexChange) { int idx = GrGLProgram::PositionAttributeIdx(); GL_CALL(VertexAttribPointer(idx, 2, scalarType, false, newStride, (GrGLvoid*)vertexOffset)); fHWGeometryState.fVertexOffset = vertexOffset; } for (int t = 0; t < GrDrawState::kMaxTexCoords; ++t) { if (newTexCoordOffsets[t] > 0) { GrGLvoid* texCoordOffset = (GrGLvoid*)(vertexOffset + newTexCoordOffsets[t]); int idx = GrGLProgram::TexCoordAttributeIdx(t); if (oldTexCoordOffsets[t] <= 0) { GL_CALL(EnableVertexAttribArray(idx)); GL_CALL(VertexAttribPointer(idx, 2, scalarType, texCoordNorm, newStride, texCoordOffset)); } else if (posAndTexChange || newTexCoordOffsets[t] != oldTexCoordOffsets[t]) { GL_CALL(VertexAttribPointer(idx, 2, scalarType, texCoordNorm, newStride, texCoordOffset)); } } else if (oldTexCoordOffsets[t] > 0) { GL_CALL(DisableVertexAttribArray(GrGLProgram::TexCoordAttributeIdx(t))); } } if (newColorOffset > 0) { GrGLvoid* colorOffset = (int8_t*)(vertexOffset + newColorOffset); int idx = GrGLProgram::ColorAttributeIdx(); if (oldColorOffset <= 0) { GL_CALL(EnableVertexAttribArray(idx)); GL_CALL(VertexAttribPointer(idx, 4, GR_GL_UNSIGNED_BYTE, true, newStride, colorOffset)); } else if (allOffsetsChange || newColorOffset != oldColorOffset) { GL_CALL(VertexAttribPointer(idx, 4, GR_GL_UNSIGNED_BYTE, true, newStride, colorOffset)); } } else if (oldColorOffset > 0) { GL_CALL(DisableVertexAttribArray(GrGLProgram::ColorAttributeIdx())); } if (newCoverageOffset > 0) { GrGLvoid* coverageOffset = (int8_t*)(vertexOffset + newCoverageOffset); int idx = GrGLProgram::CoverageAttributeIdx(); if (oldCoverageOffset <= 0) { GL_CALL(EnableVertexAttribArray(idx)); GL_CALL(VertexAttribPointer(idx, 4, GR_GL_UNSIGNED_BYTE, true, newStride, coverageOffset)); } else if (allOffsetsChange || newCoverageOffset != oldCoverageOffset) { GL_CALL(VertexAttribPointer(idx, 4, GR_GL_UNSIGNED_BYTE, true, newStride, coverageOffset)); } } else if (oldCoverageOffset > 0) { GL_CALL(DisableVertexAttribArray(GrGLProgram::CoverageAttributeIdx())); } if (newEdgeOffset > 0) { GrGLvoid* edgeOffset = (int8_t*)(vertexOffset + newEdgeOffset); int idx = GrGLProgram::EdgeAttributeIdx(); if (oldEdgeOffset <= 0) { GL_CALL(EnableVertexAttribArray(idx)); GL_CALL(VertexAttribPointer(idx, 4, scalarType, false, newStride, edgeOffset)); } else if (allOffsetsChange || newEdgeOffset != oldEdgeOffset) { GL_CALL(VertexAttribPointer(idx, 4, scalarType, false, newStride, edgeOffset)); } } else if (oldEdgeOffset > 0) { GL_CALL(DisableVertexAttribArray(GrGLProgram::EdgeAttributeIdx())); } fHWGeometryState.fVertexLayout = currLayout; fHWGeometryState.fArrayPtrsDirty = false; }
void GrInOrderDrawBuffer::onDraw(const DrawInfo& info) { GeometryPoolState& poolState = fGeoPoolStateStack.back(); const GrDrawState& drawState = this->getDrawState(); AutoClipReenable acr; if (drawState.isClipState() && NULL != info.getDevBounds() && this->quickInsideClip(*info.getDevBounds())) { acr.set(this->drawState()); } if (this->needsNewClip()) { this->recordClip(); } if (this->needsNewState()) { this->recordState(); } DrawRecord* draw; if (info.isInstanced()) { int instancesConcated = this->concatInstancedDraw(info); if (info.instanceCount() > instancesConcated) { draw = this->recordDraw(info); draw->adjustInstanceCount(-instancesConcated); } else { return; } } else { draw = this->recordDraw(info); } switch (this->getGeomSrc().fVertexSrc) { case kBuffer_GeometrySrcType: draw->fVertexBuffer = this->getGeomSrc().fVertexBuffer; break; case kReserved_GeometrySrcType: // fallthrough case kArray_GeometrySrcType: { size_t vertexBytes = (info.vertexCount() + info.startVertex()) * drawState.getVertexSize(); poolState.fUsedPoolVertexBytes = GrMax(poolState.fUsedPoolVertexBytes, vertexBytes); draw->fVertexBuffer = poolState.fPoolVertexBuffer; draw->adjustStartVertex(poolState.fPoolStartVertex); break; } default: GrCrash("unknown geom src type"); } draw->fVertexBuffer->ref(); if (info.isIndexed()) { switch (this->getGeomSrc().fIndexSrc) { case kBuffer_GeometrySrcType: draw->fIndexBuffer = this->getGeomSrc().fIndexBuffer; break; case kReserved_GeometrySrcType: // fallthrough case kArray_GeometrySrcType: { size_t indexBytes = (info.indexCount() + info.startIndex()) * sizeof(uint16_t); poolState.fUsedPoolIndexBytes = GrMax(poolState.fUsedPoolIndexBytes, indexBytes); draw->fIndexBuffer = poolState.fPoolIndexBuffer; draw->adjustStartIndex(poolState.fPoolStartIndex); break; } default: GrCrash("unknown geom src type"); } draw->fIndexBuffer->ref(); } else { draw->fIndexBuffer = NULL; } }