diff options
author | jvanverth@google.com <jvanverth@google.com@2bbb7eff-a529-9590-31e7-b0007b416f81> | 2013-03-01 18:21:22 +0000 |
---|---|---|
committer | jvanverth@google.com <jvanverth@google.com@2bbb7eff-a529-9590-31e7-b0007b416f81> | 2013-03-01 18:21:22 +0000 |
commit | 9b855c7c95ce9fff7a447e4a6bdf8a469c1f3097 (patch) | |
tree | a97672e09387e62ddec1deca227f024806820222 /src/gpu | |
parent | df8114d84616f8a85a5064f8deef2cca083193f8 (diff) |
Resubmit r7899 and r7901.
git-svn-id: http://skia.googlecode.com/svn/trunk@7929 2bbb7eff-a529-9590-31e7-b0007b416f81
Diffstat (limited to 'src/gpu')
-rw-r--r-- | src/gpu/GrAAConvexPathRenderer.cpp | 16 | ||||
-rw-r--r-- | src/gpu/GrAAHairLinePathRenderer.cpp | 20 | ||||
-rw-r--r-- | src/gpu/GrAARectRenderer.cpp | 46 | ||||
-rw-r--r-- | src/gpu/GrContext.cpp | 77 | ||||
-rw-r--r-- | src/gpu/GrDefaultPathRenderer.cpp | 3 | ||||
-rw-r--r-- | src/gpu/GrDrawState.cpp | 322 | ||||
-rw-r--r-- | src/gpu/GrDrawState.h | 448 | ||||
-rw-r--r-- | src/gpu/GrDrawTarget.cpp | 42 | ||||
-rw-r--r-- | src/gpu/GrInOrderDrawBuffer.cpp | 68 | ||||
-rw-r--r-- | src/gpu/GrTextContext.cpp | 19 | ||||
-rw-r--r-- | src/gpu/gl/GrGLProgram.cpp | 102 | ||||
-rw-r--r-- | src/gpu/gl/GrGLProgram.h | 27 | ||||
-rw-r--r-- | src/gpu/gl/GrGpuGL.cpp | 4 | ||||
-rw-r--r-- | src/gpu/gl/GrGpuGL_program.cpp | 83 | ||||
-rw-r--r-- | src/gpu/gr_unittests.cpp | 2 |
15 files changed, 670 insertions, 609 deletions
diff --git a/src/gpu/GrAAConvexPathRenderer.cpp b/src/gpu/GrAAConvexPathRenderer.cpp index 98eaab84cd..46e75a07a6 100644 --- a/src/gpu/GrAAConvexPathRenderer.cpp +++ b/src/gpu/GrAAConvexPathRenderer.cpp @@ -453,9 +453,6 @@ bool GrAAConvexPathRenderer::onDrawPath(const SkPath& origPath, } const SkMatrix* vm = &adcd.getOriginalMatrix(); - GrVertexLayout layout = 0; - layout |= GrDrawState::kEdge_VertexLayoutBit; - // We use the fact that SkPath::transform path does subdivision based on // perspective. Otherwise, we apply the view matrix when copying to the // segment representation. @@ -481,11 +478,22 @@ bool GrAAConvexPathRenderer::onDrawPath(const SkPath& origPath, return false; } - drawState->setVertexLayout(layout); + // position + edge + static const GrVertexAttrib kAttribs[] = { + GrVertexAttrib(kVec2f_GrVertexAttribType, 0), + GrVertexAttrib(kVec4f_GrVertexAttribType, sizeof(GrPoint)) + }; + static const GrAttribBindings bindings = GrDrawState::kEdge_AttribBindingsBit; + + drawState->setVertexAttribs(kAttribs, SK_ARRAY_COUNT(kAttribs)); + drawState->setAttribIndex(GrDrawState::kPosition_AttribIndex, 0); + drawState->setAttribIndex(GrDrawState::kEdge_AttribIndex, 1); + drawState->setAttribBindings(bindings); GrDrawTarget::AutoReleaseGeometry arg(target, vCount, iCount); if (!arg.succeeded()) { return false; } + GrAssert(sizeof(QuadVertex) == drawState->getVertexSize()); verts = reinterpret_cast<QuadVertex*>(arg.vertices()); idxs = reinterpret_cast<uint16_t*>(arg.indices()); diff --git a/src/gpu/GrAAHairLinePathRenderer.cpp b/src/gpu/GrAAHairLinePathRenderer.cpp index 00982ee4b6..a2ad9e3327 100644 --- a/src/gpu/GrAAHairLinePathRenderer.cpp +++ b/src/gpu/GrAAHairLinePathRenderer.cpp @@ -495,15 +495,20 @@ bool GrAAHairLinePathRenderer::createGeom( int* lineCnt, int* quadCnt, GrDrawTarget::AutoReleaseGeometry* arg) { - const GrDrawState& drawState = target->getDrawState(); - int rtHeight = drawState.getRenderTarget()->height(); + GrDrawState* drawState = target->drawState(); + int rtHeight = drawState->getRenderTarget()->height(); GrIRect devClipBounds; - target->getClip()->getConservativeBounds(drawState.getRenderTarget(), + target->getClip()->getConservativeBounds(drawState->getRenderTarget(), &devClipBounds); - GrVertexLayout layout = GrDrawState::kEdge_VertexLayoutBit; - SkMatrix viewM = drawState.getViewMatrix(); + // position + edge + static const GrVertexAttrib kAttribs[] = { + GrVertexAttrib(kVec2f_GrVertexAttribType, 0), + GrVertexAttrib(kVec4f_GrVertexAttribType, sizeof(GrPoint)) + }; + static const GrAttribBindings kBindings = GrDrawState::kEdge_AttribBindingsBit; + SkMatrix viewM = drawState->getViewMatrix(); PREALLOC_PTARRAY(128) lines; PREALLOC_PTARRAY(128) quads; @@ -514,7 +519,10 @@ bool GrAAHairLinePathRenderer::createGeom( *lineCnt = lines.count() / 2; int vertCnt = kVertsPerLineSeg * *lineCnt + kVertsPerQuad * *quadCnt; - target->drawState()->setVertexLayout(layout); + target->drawState()->setVertexAttribs(kAttribs, SK_ARRAY_COUNT(kAttribs)); + target->drawState()->setAttribIndex(GrDrawState::kPosition_AttribIndex, 0); + target->drawState()->setAttribIndex(GrDrawState::kEdge_AttribIndex, 1); + target->drawState()->setAttribBindings(kBindings); GrAssert(sizeof(Vertex) == target->getDrawState().getVertexSize()); if (!arg->set(target, vertCnt, 0)) { diff --git a/src/gpu/GrAARectRenderer.cpp b/src/gpu/GrAARectRenderer.cpp index d23c4b4496..741b83d080 100644 --- a/src/gpu/GrAARectRenderer.cpp +++ b/src/gpu/GrAARectRenderer.cpp @@ -13,14 +13,15 @@ SK_DEFINE_INST_COUNT(GrAARectRenderer) namespace { -static GrVertexLayout aa_rect_layout(bool useCoverage) { - GrVertexLayout layout = 0; +static void aa_rect_attributes(bool useCoverage, GrAttribBindings* bindings, + GrDrawState::AttribIndex* index) { if (useCoverage) { - layout |= GrDrawState::kCoverage_VertexLayoutBit; + *bindings = GrDrawState::kCoverage_AttribBindingsBit; + *index = GrDrawState::kCoverage_AttribIndex; } else { - layout |= GrDrawState::kColor_VertexLayoutBit; + *bindings = GrDrawState::kColor_AttribBindingsBit; + *index = GrDrawState::kColor_AttribIndex; } - return layout; } static void set_inset_fan(GrPoint* pts, size_t stride, @@ -29,6 +30,12 @@ static void set_inset_fan(GrPoint* pts, size_t stride, r.fRight - dx, r.fBottom - dy, stride); } +// position + color/coverage +static const GrVertexAttrib kVertexAttribs[] = { + GrVertexAttrib(kVec2f_GrVertexAttribType, 0), + GrVertexAttrib(kVec4ub_GrVertexAttribType, sizeof(GrPoint)) +}; + }; void GrAARectRenderer::reset() { @@ -125,8 +132,15 @@ void GrAARectRenderer::fillAARect(GrGpu* gpu, GrDrawTarget* target, const GrRect& devRect, bool useVertexCoverage) { - GrVertexLayout layout = aa_rect_layout(useVertexCoverage); - target->drawState()->setVertexLayout(layout); + GrDrawState* drawState = target->drawState(); + + GrAttribBindings bindings; + GrDrawState::AttribIndex attribIndex; + aa_rect_attributes(useVertexCoverage, &bindings, &attribIndex); + drawState->setVertexAttribs(kVertexAttribs, SK_ARRAY_COUNT(kVertexAttribs)); + drawState->setAttribBindings(bindings); + drawState->setAttribIndex(GrDrawState::kPosition_AttribIndex, 0); + drawState->setAttribIndex(attribIndex, 1); GrDrawTarget::AutoReleaseGeometry geo(target, 8, 0); if (!geo.succeeded()) { @@ -141,7 +155,8 @@ void GrAARectRenderer::fillAARect(GrGpu* gpu, } intptr_t verts = reinterpret_cast<intptr_t>(geo.vertices()); - size_t vsize = target->getDrawState().getVertexSize(); + size_t vsize = drawState->getVertexSize(); + GrAssert(sizeof(GrPoint) + sizeof(GrColor) == vsize); GrPoint* fan0Pos = reinterpret_cast<GrPoint*>(verts); GrPoint* fan1Pos = reinterpret_cast<GrPoint*>(verts + 4 * vsize); @@ -177,6 +192,8 @@ void GrAARectRenderer::strokeAARect(GrGpu* gpu, const GrRect& devRect, const GrVec& devStrokeSize, bool useVertexCoverage) { + GrDrawState* drawState = target->drawState(); + const SkScalar& dx = devStrokeSize.fX; const SkScalar& dy = devStrokeSize.fY; const SkScalar rx = SkScalarMul(dx, SK_ScalarHalf); @@ -195,8 +212,14 @@ void GrAARectRenderer::strokeAARect(GrGpu* gpu, this->fillAARect(gpu, target, r, useVertexCoverage); return; } - GrVertexLayout layout = aa_rect_layout(useVertexCoverage); - target->drawState()->setVertexLayout(layout); + + GrAttribBindings bindings; + GrDrawState::AttribIndex attribIndex; + aa_rect_attributes(useVertexCoverage, &bindings, &attribIndex); + drawState->setVertexAttribs(kVertexAttribs, SK_ARRAY_COUNT(kVertexAttribs)); + drawState->setAttribBindings(bindings); + drawState->setAttribIndex(GrDrawState::kPosition_AttribIndex, 0); + drawState->setAttribIndex(attribIndex, 1); GrDrawTarget::AutoReleaseGeometry geo(target, 16, 0); if (!geo.succeeded()) { @@ -210,7 +233,8 @@ void GrAARectRenderer::strokeAARect(GrGpu* gpu, } intptr_t verts = reinterpret_cast<intptr_t>(geo.vertices()); - size_t vsize = target->getDrawState().getVertexSize(); + size_t vsize = drawState->getVertexSize(); + GrAssert(sizeof(GrPoint) + sizeof(GrColor) == vsize); // We create vertices for four nested rectangles. There are two ramps from 0 to full // coverage, one on the exterior of the stroke and the other on the interior. diff --git a/src/gpu/GrContext.cpp b/src/gpu/GrContext.cpp index 0f6fa1651c..3b77b73fe6 100644 --- a/src/gpu/GrContext.cpp +++ b/src/gpu/GrContext.cpp @@ -352,8 +352,16 @@ GrTexture* GrContext::createResizedTexture(const GrTextureDesc& desc, GrTextureParams params(SkShader::kClamp_TileMode, needsFiltering); drawState->createTextureEffect(0, clampedTexture, SkMatrix::I(), params); - static const GrVertexLayout layout = GrDrawState::StageTexCoordVertexLayoutBit(0); - drawState->setVertexLayout(layout); + // position + texture coordinate + static const GrVertexAttrib kVertexAttribs[] = { + GrVertexAttrib(kVec2f_GrVertexAttribType, 0), + GrVertexAttrib(kVec2f_GrVertexAttribType, sizeof(GrPoint)) + }; + static const GrAttribBindings kAttribBindings = GrDrawState::ExplicitTexCoordAttribBindingsBit(0); + drawState->setAttribBindings(kAttribBindings); + drawState->setVertexAttribs(kVertexAttribs, SK_ARRAY_COUNT(kVertexAttribs)); + drawState->setAttribIndex(GrDrawState::kPosition_AttribIndex, 0); + drawState->setAttribIndex(GrDrawState::kTexCoord_AttribIndex, 1); GrDrawTarget::AutoReleaseGeometry arg(fGpu, 4, 0); if (arg.succeeded()) { @@ -778,7 +786,7 @@ void GrContext::drawRect(const GrPaint& paint, // unitSquareVertexBuffer() static const int worstCaseVertCount = 10; - target->drawState()->setVertexLayout(GrDrawState::kDefault_VertexLayout); + target->drawState()->setDefaultVertexAttribs(); GrDrawTarget::AutoReleaseGeometry geo(target, worstCaseVertCount, 0); if (!geo.succeeded()) { @@ -821,7 +829,7 @@ void GrContext::drawRect(const GrPaint& paint, } GrDrawState* drawState = target->drawState(); - drawState->setVertexLayout(GrDrawState::kDefault_VertexLayout); + target->drawState()->setDefaultVertexAttribs(); target->setVertexSourceToBuffer(sqVB); SkMatrix m; m.setAll(rect.width(), 0, rect.fLeft, @@ -887,7 +895,7 @@ void GrContext::drawRectToRect(const GrPaint& paint, GrPrintf("Failed to create static rect vb.\n"); return; } - drawState->setVertexLayout(GrDrawState::kDefault_VertexLayout); + drawState->setDefaultVertexAttribs(); target->setVertexSourceToBuffer(sqVB); target->drawNonIndexed(kTriangleFan_GrPrimitiveType, 0, 4); #else @@ -912,37 +920,55 @@ void GrContext::drawVertices(const GrPaint& paint, GrDrawTarget* target = this->prepareToDraw(&paint, BUFFERED_DRAW); GrDrawState::AutoStageDisable atr(fDrawState); - GrVertexLayout layout = 0; + GrDrawState* drawState = target->drawState(); + + GrVertexAttribArray<3> attribs; + size_t currentOffset = 0; + int colorOffset = -1, texOffset = -1; + GrAttribBindings bindings = GrDrawState::kDefault_AttribBindings; + + // set position attribute + drawState->setAttribIndex(GrDrawState::kPosition_AttribIndex, attribs.count()); + attribs.push_back(GrVertexAttrib(kVec2f_GrVertexAttribType, currentOffset)); + currentOffset += sizeof(GrPoint); + + // set up optional texture coordinate attributes if (NULL != texCoords) { - layout |= GrDrawState::StageTexCoordVertexLayoutBit(0); + bindings |= GrDrawState::ExplicitTexCoordAttribBindingsBit(0); + drawState->setAttribIndex(GrDrawState::kTexCoord_AttribIndex, attribs.count()); + attribs.push_back(GrVertexAttrib(kVec2f_GrVertexAttribType, currentOffset)); + texOffset = currentOffset; + currentOffset += sizeof(GrPoint); } + + // set up optional color attributes if (NULL != colors) { - layout |= GrDrawState::kColor_VertexLayoutBit; + bindings |= GrDrawState::kColor_AttribBindingsBit; + drawState->setAttribIndex(GrDrawState::kColor_AttribIndex, attribs.count()); + attribs.push_back(GrVertexAttrib(kVec4ub_GrVertexAttribType, currentOffset)); + colorOffset = currentOffset; + currentOffset += sizeof(GrColor); } - target->drawState()->setVertexLayout(layout); - int vertexSize = target->getDrawState().getVertexSize(); + drawState->setVertexAttribs(attribs.begin(), attribs.count()); + drawState->setAttribBindings(bindings); + + size_t vertexSize = drawState->getVertexSize(); + GrAssert(vertexSize == currentOffset); if (sizeof(GrPoint) != vertexSize) { if (!geo.set(target, vertexCount, 0)) { GrPrintf("Failed to get space for vertices!\n"); return; } - int texOffset; - int colorOffset; - GrDrawState::VertexSizeAndOffsets(layout, - &texOffset, - &colorOffset, - NULL, - NULL); void* curVertex = geo.vertices(); for (int i = 0; i < vertexCount; ++i) { *((GrPoint*)curVertex) = positions[i]; - if (texOffset > 0) { + if (texOffset >= 0) { *(GrPoint*)((intptr_t)curVertex + texOffset) = texCoords[i]; } - if (colorOffset > 0) { + if (colorOffset >= 0) { *(GrColor*)((intptr_t)curVertex + colorOffset) = colors[i]; } curVertex = (void*)((intptr_t)curVertex + vertexSize); @@ -1045,8 +1071,17 @@ void GrContext::internalDrawOval(const GrPaint& paint, return; } - GrVertexLayout layout = GrDrawState::kEdge_VertexLayoutBit; - drawState->setVertexLayout(layout); + // position + edge + static const GrVertexAttrib kVertexAttribs[] = { + GrVertexAttrib(kVec2f_GrVertexAttribType, 0), + GrVertexAttrib(kVec4f_GrVertexAttribType, sizeof(GrPoint)) + }; + static const GrAttribBindings kAttributeBindings = GrDrawState::kEdge_AttribBindingsBit; + + drawState->setVertexAttribs(kVertexAttribs, SK_ARRAY_COUNT(kVertexAttribs)); + drawState->setAttribIndex(GrDrawState::kPosition_AttribIndex, 0); + drawState->setAttribIndex(GrDrawState::kEdge_AttribIndex, 1); + drawState->setAttribBindings(kAttributeBindings); GrAssert(sizeof(CircleVertex) == drawState->getVertexSize()); GrDrawTarget::AutoReleaseGeometry geo(target, 4, 0); diff --git a/src/gpu/GrDefaultPathRenderer.cpp b/src/gpu/GrDefaultPathRenderer.cpp index d5ebaaa602..7ca478e493 100644 --- a/src/gpu/GrDefaultPathRenderer.cpp +++ b/src/gpu/GrDefaultPathRenderer.cpp @@ -211,7 +211,6 @@ bool GrDefaultPathRenderer::createGeom(const SkPath& path, return false; } - GrVertexLayout layout = 0; bool indexed = contourCnt > 1; const bool isHairline = stroke.isHairlineStyle(); @@ -233,7 +232,7 @@ bool GrDefaultPathRenderer::createGeom(const SkPath& path, } } - target->drawState()->setVertexLayout(layout); + target->drawState()->setDefaultVertexAttribs(); if (!arg->set(target, maxPts, maxIdxs)) { return false; } diff --git a/src/gpu/GrDrawState.cpp b/src/gpu/GrDrawState.cpp index 3925bd9a91..6b00913036 100644 --- a/src/gpu/GrDrawState.cpp +++ b/src/gpu/GrDrawState.cpp @@ -57,270 +57,150 @@ namespace { * they were just a series of immediate->memory moves.) * */ -void gen_tex_coord_mask(GrVertexLayout* texCoordMask) { +void gen_tex_coord_mask(GrAttribBindings* texCoordMask) { *texCoordMask = 0; for (int s = 0; s < GrDrawState::kNumStages; ++s) { - *texCoordMask |= GrDrawState::StageTexCoordVertexLayoutBit(s); + *texCoordMask |= GrDrawState::ExplicitTexCoordAttribBindingsBit(s); } } -const GrVertexLayout kTexCoordMask = (1 << GrDrawState::kNumStages)-1; - -inline int num_tex_coords(GrVertexLayout layout) { - return (kTexCoordMask & layout) ? 1 : 0; -} +const GrAttribBindings kTexCoord_AttribBindingsMask = (1 << GrDrawState::kNumStages)-1; } //unnamed namespace -static const size_t kVec2Size = sizeof(GrPoint); - -size_t GrDrawState::VertexSize(GrVertexLayout vertexLayout) { - size_t size = kVec2Size; // position - size += num_tex_coords(vertexLayout) * kVec2Size; - if (vertexLayout & kColor_VertexLayoutBit) { - size += sizeof(GrColor); - } - if (vertexLayout & kCoverage_VertexLayoutBit) { - size += sizeof(GrColor); - } - if (vertexLayout & kEdge_VertexLayoutBit) { - size += 4 * sizeof(SkScalar); +const size_t GrDrawState::kVertexAttribSizes[kGrVertexAttribTypeCount] = { + sizeof(float), // kFloat_GrVertexAttribType + 2*sizeof(float), // kVec2_GrVertexAttribType + 3*sizeof(float), // kVec3_GrVertexAttribType + 4*sizeof(float), // kVec4_GrVertexAttribType + 4*sizeof(char) // kCVec4_GrVertexAttribType +}; + +static size_t vertex_size(const GrVertexAttrib* attribs, int count) { + // this works as long as we're 4 byte-aligned +#if GR_DEBUG + uint32_t overlapCheck = 0; +#endif + GrAssert(count <= GrDrawState::kAttribIndexCount); + size_t size = 0; + for (int index = 0; index < count; ++index) { + size_t attribSize = GrDrawState::kVertexAttribSizes[attribs[index].fType]; + size += attribSize; +#if GR_DEBUG + size_t dwordCount = attribSize >> 2; + uint32_t mask = (1 << dwordCount)-1; + size_t offsetShift = attribs[index].fOffset >> 2; + GrAssert(!(overlapCheck & (mask << offsetShift))); + overlapCheck |= (mask << offsetShift); +#endif } return size; } -//////////////////////////////////////////////////////////////////////////////// - -/** - * Functions for computing offsets of various components from the layout - * bitfield. - * - * Order of vertex components: - * Position - * Tex Coord - * Color - * Coverage - */ - -int GrDrawState::VertexStageCoordOffset(int stageIdx, GrVertexLayout vertexLayout) { - if (!StageUsesTexCoords(vertexLayout, stageIdx)) { - return 0; - } - - return kVec2Size; +size_t GrDrawState::getVertexSize() const { + return vertex_size(fVertexAttribs.begin(), fVertexAttribs.count()); } -int GrDrawState::VertexColorOffset(GrVertexLayout vertexLayout) { - if (vertexLayout & kColor_VertexLayoutBit) { - return kVec2Size * (num_tex_coords(vertexLayout) + 1); //+1 for pos - } - return -1; -} +const GrAttribBindings GrDrawState::kAttribIndexMasks[kAttribIndexCount] = { + 0, // position is not reflected in the bindings + kColor_AttribBindingsBit, + kCoverage_AttribBindingsBit, + kEdge_AttribBindingsBit, + kTexCoord_AttribBindingsMask +}; -int GrDrawState::VertexCoverageOffset(GrVertexLayout vertexLayout) { - if (vertexLayout & kCoverage_VertexLayoutBit) { - int offset = kVec2Size * (num_tex_coords(vertexLayout) + 1); - if (vertexLayout & kColor_VertexLayoutBit) { - offset += sizeof(GrColor); - } - return offset; - } - return -1; -} +//////////////////////////////////////////////////////////////////////////////// -int GrDrawState::VertexEdgeOffset(GrVertexLayout vertexLayout) { - // edge pts are after the pos, tex coords, and color - if (vertexLayout & kEdge_VertexLayoutBit) { - int offset = kVec2Size * (num_tex_coords(vertexLayout) + 1); //+1 for pos - if (vertexLayout & kColor_VertexLayoutBit) { - offset += sizeof(GrColor); - } - if (vertexLayout & kCoverage_VertexLayoutBit) { - offset += sizeof(GrColor); - } - return offset; +void GrDrawState::setVertexAttribs(const GrVertexAttrib* attribs, int count) { + GrAssert(count <= GrDrawState::kAttribIndexCount); + fVertexAttribs.reset(); + for (int index = 0; index < count; ++index) { + fVertexAttribs.push_back(attribs[index]); } - return -1; } -int GrDrawState::VertexSizeAndOffsets( - GrVertexLayout vertexLayout, - int* texCoordOffset, - int* colorOffset, - int* coverageOffset, - int* edgeOffset) { - int size = kVec2Size; // position - - if (kTexCoordMask & vertexLayout) { - if (NULL != texCoordOffset) { - *texCoordOffset = size; - } - size += kVec2Size; - } else { - if (NULL != texCoordOffset) { - *texCoordOffset = -1; - } - } - if (kColor_VertexLayoutBit & vertexLayout) { - if (NULL != colorOffset) { - *colorOffset = size; - } - size += sizeof(GrColor); - } else { - if (NULL != colorOffset) { - *colorOffset = -1; - } - } - if (kCoverage_VertexLayoutBit & vertexLayout) { - if (NULL != coverageOffset) { - *coverageOffset = size; - } - size += sizeof(GrColor); - } else { - if (NULL != coverageOffset) { - *coverageOffset = -1; - } - } - if (kEdge_VertexLayoutBit & vertexLayout) { - if (NULL != edgeOffset) { - *edgeOffset = size; - } - size += 4 * sizeof(SkScalar); - } else { - if (NULL != edgeOffset) { - *edgeOffset = -1; - } - } - return size; -} +//////////////////////////////////////////////////////////////////////////////// -int GrDrawState::VertexSizeAndOffsetsByStage( - GrVertexLayout vertexLayout, - int texCoordOffsetsByStage[GrDrawState::kNumStages], - int* colorOffset, - int* coverageOffset, - int* edgeOffset) { - - int texCoordOffset; - int size = VertexSizeAndOffsets(vertexLayout, - &texCoordOffset, - colorOffset, - coverageOffset, - edgeOffset); - if (NULL != texCoordOffsetsByStage) { - for (int s = 0; s < GrDrawState::kNumStages; ++s) { - texCoordOffsetsByStage[s] = StageUsesTexCoords(vertexLayout, s) ? - texCoordOffset : 0; - } - } - return size; +void GrDrawState::setDefaultVertexAttribs() { + fVertexAttribs.reset(); + fVertexAttribs.push_back(GrVertexAttrib(kVec2f_GrVertexAttribType, 0)); + + fCommon.fAttribBindings = kDefault_AttribBindings; + + fAttribIndices[kPosition_AttribIndex] = 0; } //////////////////////////////////////////////////////////////////////////////// -bool GrDrawState::VertexUsesTexCoords(GrVertexLayout vertexLayout) { - return SkToBool(kTexCoordMask & vertexLayout); +bool GrDrawState::AttributesBindExplicitTexCoords(GrAttribBindings attribBindings) { + return SkToBool(kTexCoord_AttribBindingsMask & attribBindings); } //////////////////////////////////////////////////////////////////////////////// -void GrDrawState::VertexLayoutUnitTest() { +void GrDrawState::VertexAttributesUnitTest() { // Ensure that our tex coord mask is correct - GrVertexLayout texCoordMask; + GrAttribBindings texCoordMask; gen_tex_coord_mask(&texCoordMask); - GrAssert(texCoordMask == kTexCoordMask); + GrAssert(texCoordMask == kTexCoord_AttribBindingsMask); // not necessarily exhaustive static bool run; if (!run) { run = true; - GrVertexLayout tcMask = 0; - GrAssert(!VertexUsesTexCoords(0)); + + GrVertexAttribArray<6> attribs; + GrAssert(0 == vertex_size(attribs.begin(), attribs.count())); + + attribs.push_back(GrVertexAttrib(kFloat_GrVertexAttribType, 0)); + GrAssert(sizeof(float) == vertex_size(attribs.begin(), attribs.count())); + attribs[0].fType = kVec2f_GrVertexAttribType; + GrAssert(2*sizeof(float) == vertex_size(attribs.begin(), attribs.count())); + attribs[0].fType = kVec3f_GrVertexAttribType; + GrAssert(3*sizeof(float) == vertex_size(attribs.begin(), attribs.count())); + attribs[0].fType = kVec4f_GrVertexAttribType; + GrAssert(4*sizeof(float) == vertex_size(attribs.begin(), attribs.count())); + attribs[0].fType = kVec4ub_GrVertexAttribType; + GrAssert(4*sizeof(char) == vertex_size(attribs.begin(), attribs.count())); + + attribs.push_back(GrVertexAttrib(kVec2f_GrVertexAttribType, attribs[0].fOffset + 4*sizeof(char))); + GrAssert(4*sizeof(char) + 2*sizeof(float) == vertex_size(attribs.begin(), attribs.count())); + attribs.push_back(GrVertexAttrib(kVec3f_GrVertexAttribType, attribs[1].fOffset + 2*sizeof(float))); + GrAssert(4*sizeof(char) + 2*sizeof(float) + 3*sizeof(float) == + vertex_size(attribs.begin(), attribs.count())); + attribs.push_back(GrVertexAttrib(kFloat_GrVertexAttribType, attribs[2].fOffset + 3*sizeof(float))); + GrAssert(4*sizeof(char) + 2*sizeof(float) + 3*sizeof(float) + sizeof(float) == + vertex_size(attribs.begin(), attribs.count())); + attribs.push_back(GrVertexAttrib(kVec4f_GrVertexAttribType, attribs[3].fOffset + sizeof(float))); + GrAssert(4*sizeof(char) + 2*sizeof(float) + 3*sizeof(float) + sizeof(float) + 4*sizeof(float) == + vertex_size(attribs.begin(), attribs.count())); + + GrAttribBindings tcMask = 0; + GrAssert(!AttributesBindExplicitTexCoords(0)); for (int s = 0; s < GrDrawState::kNumStages; ++s) { - tcMask |= StageTexCoordVertexLayoutBit(s); - GrAssert(sizeof(GrPoint) == VertexStageCoordOffset(s, tcMask)); - GrAssert(VertexUsesTexCoords(tcMask)); - GrAssert(2*sizeof(GrPoint) == VertexSize(tcMask)); - GrAssert(StageUsesTexCoords(tcMask, s)); + tcMask |= ExplicitTexCoordAttribBindingsBit(s); + GrAssert(AttributesBindExplicitTexCoords(tcMask)); + GrAssert(StageBindsExplicitTexCoords(tcMask, s)); for (int s2 = s + 1; s2 < GrDrawState::kNumStages; ++s2) { - GrAssert(!StageUsesTexCoords(tcMask, s2)); - - #if GR_DEBUG - GrVertexLayout posAsTex = tcMask; - #endif - GrAssert(0 == VertexStageCoordOffset(s2, posAsTex)); - GrAssert(2*sizeof(GrPoint) == VertexSize(posAsTex)); - GrAssert(!StageUsesTexCoords(posAsTex, s2)); - GrAssert(-1 == VertexEdgeOffset(posAsTex)); + GrAssert(!StageBindsExplicitTexCoords(tcMask, s2)); } - 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(kTexCoordMask == 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)); } + GrAssert(kTexCoord_AttribBindingsMask == tcMask); } } //////////////////////////////////////////////////////////////////////////////// -bool GrDrawState::StageUsesTexCoords(GrVertexLayout layout, int stageIdx) { - return SkToBool(layout & StageTexCoordVertexLayoutBit(stageIdx)); +bool GrDrawState::StageBindsExplicitTexCoords(GrAttribBindings bindings, int stageIdx) { + return SkToBool(bindings & ExplicitTexCoordAttribBindingsBit(stageIdx)); } -bool GrDrawState::srcAlphaWillBeOne(GrVertexLayout layout) const { +bool GrDrawState::srcAlphaWillBeOne(GrAttribBindings bindings) const { uint32_t validComponentFlags; GrColor color; // Check if per-vertex or constant color may have partial alpha - if (layout & kColor_VertexLayoutBit) { + if (bindings & kColor_AttribBindingsBit) { validComponentFlags = 0; color = 0; // not strictly necessary but we get false alarms from tools about uninit. } else { @@ -366,7 +246,7 @@ bool GrDrawState::srcAlphaWillBeOne(GrVertexLayout layout) const { return (GrEffect::kA_ValidComponentFlag & validComponentFlags) && 0xff == GrColorUnpackA(color); } -bool GrDrawState::hasSolidCoverage(GrVertexLayout layout) const { +bool GrDrawState::hasSolidCoverage(GrAttribBindings bindings) const { // If we're drawing coverage directly then coverage is effectively treated as color. if (this->isCoverageDrawing()) { return true; @@ -375,7 +255,7 @@ bool GrDrawState::hasSolidCoverage(GrVertexLayout layout) const { GrColor coverage; uint32_t validComponentFlags; // Initialize to an unknown starting coverage if per-vertex coverage is specified. - if (layout & kCoverage_VertexLayoutBit) { + if (bindings & kCoverage_AttribBindingsBit) { validComponentFlags = 0; } else { coverage = fCommon.fCoverage; @@ -417,7 +297,7 @@ bool GrDrawState::canTweakAlphaForCoverage() const { GrDrawState::BlendOptFlags GrDrawState::getBlendOpts(bool forceCoverage, GrBlendCoeff* srcCoeff, GrBlendCoeff* dstCoeff) const { - GrVertexLayout layout = this->getVertexLayout(); + GrAttribBindings bindings = this->getAttribBindings(); GrBlendCoeff bogusSrcCoeff, bogusDstCoeff; if (NULL == srcCoeff) { @@ -435,14 +315,14 @@ GrDrawState::BlendOptFlags GrDrawState::getBlendOpts(bool forceCoverage, *dstCoeff = kOne_GrBlendCoeff; } - bool srcAIsOne = this->srcAlphaWillBeOne(layout); + bool srcAIsOne = this->srcAlphaWillBeOne(bindings); bool dstCoeffIsOne = kOne_GrBlendCoeff == *dstCoeff || (kSA_GrBlendCoeff == *dstCoeff && srcAIsOne); bool dstCoeffIsZero = kZero_GrBlendCoeff == *dstCoeff || (kISA_GrBlendCoeff == *dstCoeff && srcAIsOne); bool covIsZero = !this->isCoverageDrawing() && - !(layout & GrDrawState::kCoverage_VertexLayoutBit) && + !(bindings & GrDrawState::kCoverage_AttribBindingsBit) && 0 == this->getCoverage(); // When coeffs are (0,1) there is no reason to draw at all, unless // stenciling is enabled. Having color writes disabled is effectively @@ -460,8 +340,8 @@ GrDrawState::BlendOptFlags GrDrawState::getBlendOpts(bool forceCoverage, // edge aa or coverage stage bool hasCoverage = forceCoverage || 0xffffffff != this->getCoverage() || - (layout & GrDrawState::kCoverage_VertexLayoutBit) || - (layout & GrDrawState::kEdge_VertexLayoutBit); + (bindings & GrDrawState::kCoverage_AttribBindingsBit) || + (bindings & GrDrawState::kEdge_AttribBindingsBit); for (int s = this->getFirstCoverageStage(); !hasCoverage && s < GrDrawState::kNumStages; ++s) { diff --git a/src/gpu/GrDrawState.h b/src/gpu/GrDrawState.h index 05492a73ae..53c575d3af 100644 --- a/src/gpu/GrDrawState.h +++ b/src/gpu/GrDrawState.h @@ -23,6 +23,41 @@ class GrPaint; +/** + * Types used to describe format of vertices in arrays + */ +enum GrVertexAttribType { + kFloat_GrVertexAttribType = 0, + kVec2f_GrVertexAttribType, + kVec3f_GrVertexAttribType, + kVec4f_GrVertexAttribType, + kVec4ub_GrVertexAttribType, // vector of 4 unsigned bytes, e.g. colors + + kLast_GrVertexAttribType = kVec4ub_GrVertexAttribType +}; +static const int kGrVertexAttribTypeCount = kLast_GrVertexAttribType + 1; + +struct GrVertexAttrib { + GrVertexAttrib() {} + GrVertexAttrib(GrVertexAttribType type, size_t offset) : + fType(type), fOffset(offset) {} + bool operator==(const GrVertexAttrib& other) const { + return fType == other.fType && fOffset == other.fOffset; + }; + bool operator!=(const GrVertexAttrib& other) const { return !(*this == other); } + + GrVertexAttribType fType; + size_t fOffset; +}; + +template <int N> +class GrVertexAttribArray : public SkSTArray<N, GrVertexAttrib, true> {}; + +/** + * Type used to describe how attributes bind to program usage + */ +typedef int GrAttribBindings; + class GrDrawState : public GrRefCnt { public: SK_DECLARE_INST_COUNT(GrDrawState) @@ -32,7 +67,7 @@ public: * GrEffect. The effect produces an output color in the fragment shader. It's inputs are the * output from the previous enabled stage and a position. The position is either derived from * the interpolated vertex positions or explicit per-vertex coords, depending upon the - * GrVertexLayout used to draw. + * GrAttribBindings used to draw. * * The stages are divided into two sets, color-computing and coverage-computing. The final color * stage produces the final pixel color. The coverage-computing stages function exactly as the @@ -40,7 +75,7 @@ public: * coverage rather than as input to the src/dst color blend step. * * The input color to the first enabled color-stage is either the constant color or interpolated - * per-vertex colors, depending upon GrVertexLayout. The input to the first coverage stage is + * per-vertex colors, depending upon GrAttribBindings. The input to the first coverage stage is * either a constant coverage (usually full-coverage), interpolated per-vertex coverage, or * edge-AA computed coverage. (This latter is going away as soon as it can be rewritten as a * GrEffect). @@ -59,7 +94,7 @@ public: GrDrawState() { #if GR_DEBUG - VertexLayoutUnitTest(); + VertexAttributesUnitTest(); #endif this->reset(); } @@ -82,8 +117,9 @@ public: fRenderTarget.reset(NULL); + this->setDefaultVertexAttribs(); + fCommon.fColor = 0xffffffff; - fCommon.fVertexLayout = kDefault_VertexLayout; fCommon.fViewMatrix.reset(); fCommon.fSrcBlend = kOne_GrBlendCoeff; fCommon.fDstBlend = kZero_GrBlendCoeff; @@ -107,193 +143,50 @@ public: void setFromPaint(const GrPaint& paint); /////////////////////////////////////////////////////////////////////////// - /// @name Vertex Layout + /// @name Vertex Attributes //// - /** - * The format of vertices is represented as a bitfield of flags. - * Flags that indicate the layout of vertex data. Vertices always contain - * positions and may also contain texture coordinates, per-vertex colors, - * and per-vertex coverage. Each stage can use any texture coordinates as - * its input texture coordinates or it may use the positions as texture - * coordinates. - * - * If no texture coordinates are specified for a stage then the stage is - * disabled. - * - * The order in memory is always (position, texture coords, color, coverage) - * with any unused fields omitted. - */ - - /** - * Generates a bit indicating that a texture stage uses texture coordinates - * - * @param stageIdx the stage that will use texture coordinates. - * - * @return the bit to add to a GrVertexLayout bitfield. - */ - static int StageTexCoordVertexLayoutBit(int stageIdx) { - GrAssert(stageIdx < kNumStages); - return (1 << stageIdx); - } - - static bool StageUsesTexCoords(GrVertexLayout layout, int stageIdx); - -private: - // non-stage bits start at this index. - static const int STAGE_BIT_CNT = kNumStages; -public: - - /** - * Additional Bits that can be specified in GrVertexLayout. - */ - enum VertexLayoutBits { - /* vertices have colors (GrColor) */ - kColor_VertexLayoutBit = 1 << (STAGE_BIT_CNT + 0), - /* vertices have coverage (GrColor) - */ - kCoverage_VertexLayoutBit = 1 << (STAGE_BIT_CNT + 1), - /* Each vertex specificies an edge. Distance to the edge is used to - * compute a coverage. See GrDrawState::setVertexEdgeType(). - */ - kEdge_VertexLayoutBit = 1 << (STAGE_BIT_CNT + 2), - // for below assert - kDummyVertexLayoutBit, - kHighVertexLayoutBit = kDummyVertexLayoutBit - 1 - }; - // make sure we haven't exceeded the number of bits in GrVertexLayout. - GR_STATIC_ASSERT(kHighVertexLayoutBit < ((uint64_t)1 << 8*sizeof(GrVertexLayout))); - - enum VertexLayout { - kDefault_VertexLayout = 0 + enum { + kVertexAttribCnt = 6, }; - /** - * Sets vertex layout for next draw. + /** + * The format of vertices is represented as an array of vertex attribute + * pair, with each pair representing the type of the attribute and the + * offset in the vertex structure (see GrVertexAttrib, above). * - * @param layout the vertex layout to set. + * This will only set up the vertex geometry. To bind the attributes in + * the shaders, attribute indices and attribute bindings need to be set + * as well. */ - void setVertexLayout(GrVertexLayout layout) { fCommon.fVertexLayout = layout; } - - GrVertexLayout getVertexLayout() const { return fCommon.fVertexLayout; } - size_t getVertexSize() const { return VertexSize(fCommon.fVertexLayout); } - - - //////////////////////////////////////////////////////////////////////////// - // Helpers for picking apart vertex layouts - - /** - * Helper function to compute the size of a vertex from a vertex layout - * @return size of a single vertex. - */ - static size_t VertexSize(GrVertexLayout vertexLayout); - - /** - * Helper function to compute the offset of texture coordinates in a vertex - * @return offset of texture coordinates in vertex layout or 0 if positions - * are used as texture coordinates for the stage. - */ - static int VertexStageCoordOffset(int stageIdx, GrVertexLayout vertexLayout); - - /** - * Helper function to compute the offset of the color in a vertex - * @return offset of color in vertex layout or -1 if the - * layout has no color. - */ - static int VertexColorOffset(GrVertexLayout vertexLayout); - - /** - * Helper function to compute the offset of the coverage in a vertex - * @return offset of coverage in vertex layout or -1 if the - * layout has no coverage. - */ - static int VertexCoverageOffset(GrVertexLayout vertexLayout); - - /** - * Helper function to compute the offset of the edge pts in a vertex - * @return offset of edge in vertex layout or -1 if the - * layout has no edge. - */ - static int VertexEdgeOffset(GrVertexLayout vertexLayout); /** - * Helper function to determine if vertex layout contains explicit texture - * coordinates. - * - * @param vertexLayout layout to query + * Sets vertex attributes for next draw. * - * @return true if vertex specifies texture coordinates, - * false otherwise. + * @param attribs the array of vertex attributes to set. + * @param count the number of attributes being set. + * limited to a count of kVertexAttribCnt. */ - static bool VertexUsesTexCoords(GrVertexLayout vertexLayout); + void setVertexAttribs(const GrVertexAttrib attribs[], int count); - /** - * Helper function to compute the size of each vertex and the offsets of - * texture coordinates and color. - * - * @param vertexLayout the layout to query - * @param texCoordOffset after return it is the offset of the - * tex coord index in the vertex or -1 if - * tex coords aren't used. (optional) - * @param colorOffset after return it is the offset of the - * color field in each vertex, or -1 if - * there aren't per-vertex colors. (optional) - * @param coverageOffset after return it is the offset of the - * coverage field in each vertex, or -1 if - * there aren't per-vertex coeverages. - * (optional) - * @param edgeOffset after return it is the offset of the - * edge eq field in each vertex, or -1 if - * there aren't per-vertex edge equations. - * (optional) - * @return size of a single vertex - */ - static int VertexSizeAndOffsets(GrVertexLayout vertexLayout, - int *texCoordOffset, - int *colorOffset, - int *coverageOffset, - int* edgeOffset); + const GrVertexAttrib* getVertexAttribs() const { return fVertexAttribs.begin(); } + int getVertexAttribCount() const { return fVertexAttribs.count(); } + + size_t getVertexSize() const; /** - * Helper function to compute the size of each vertex and the offsets of - * texture coordinates and color. Determines tex coord offsets by stage - * rather than by index. (Each stage can be mapped to any t.c. index - * by StageTexCoordVertexLayoutBit.) If a stage uses positions for - * tex coords then that stage's offset will be 0 (positions are always at 0). + * Sets default vertex attributes for next draw. * - * @param vertexLayout the layout to query - * @param texCoordOffsetsByStage after return it is the offset of each - * tex coord index in the vertex or -1 if - * index isn't used. (optional) - * @param colorOffset after return it is the offset of the - * color field in each vertex, or -1 if - * there aren't per-vertex colors. - * (optional) - * @param coverageOffset after return it is the offset of the - * coverage field in each vertex, or -1 if - * there aren't per-vertex coeverages. - * (optional) - * @param edgeOffset after return it is the offset of the - * edge eq field in each vertex, or -1 if - * there aren't per-vertex edge equations. - * (optional) - * @return size of a single vertex + * This will also set default vertex attribute indices and bindings */ - static int VertexSizeAndOffsetsByStage(GrVertexLayout vertexLayout, - int texCoordOffsetsByStage[kNumStages], - int* colorOffset, - int* coverageOffset, - int* edgeOffset); + void setDefaultVertexAttribs(); - /** - * Determines whether src alpha is guaranteed to be one for all src pixels - */ - bool srcAlphaWillBeOne(GrVertexLayout) const; + //////////////////////////////////////////////////////////////////////////// + // Helpers for picking apart vertex attributes - /** - * Determines whether the output coverage is guaranteed to be one for all pixels hit by a draw. - */ - bool hasSolidCoverage(GrVertexLayout) const; + // helper array to let us check the expected so we know what bound attrib indices + // we care about + static const size_t kVertexAttribSizes[kGrVertexAttribTypeCount]; /** * Accessing positions, texture coords, or colors, of a vertex within an @@ -304,7 +197,7 @@ public: /** * Gets a pointer to a GrPoint of a vertex's position or texture * coordinate. - * @param vertices the vetex array + * @param vertices the vertex array * @param vertexIndex the index of the vertex in the array * @param vertexSize the size of each vertex in the array * @param offset the offset in bytes of the vertex component. @@ -353,7 +246,140 @@ public: vertexIndex * vertexSize); } - static void VertexLayoutUnitTest(); + /// @} + + /////////////////////////////////////////////////////////////////////////// + /// @name Attribute Bindings + //// + + /** + * The vertex data used by the current program is represented as a bitfield + * of flags. Programs always use positions and may also use texture + * coordinates, per-vertex colors, per-vertex coverage and edge data. Each + * stage can use the explicit texture coordinates as its input texture + * coordinates or it may use the positions as texture coordinates. + */ + + /** + * Generates a bit indicating that a texture stage uses texture coordinates + * + * @param stageIdx the stage that will use texture coordinates. + * + * @return the bit to add to a GrAttribBindings bitfield. + */ + static int ExplicitTexCoordAttribBindingsBit(int stageIdx) { + GrAssert(stageIdx < kNumStages); + return (1 << stageIdx); + } + + static bool StageBindsExplicitTexCoords(GrAttribBindings bindings, int stageIdx); + + /** + * Additional Bits that can be specified in GrAttribBindings. + */ + enum AttribBindingsBits { + /* program uses colors (GrColor) */ + kColor_AttribBindingsBit = 1 << (kNumStages + 0), + /* program uses coverage (GrColor) + */ + kCoverage_AttribBindingsBit = 1 << (kNumStages + 1), + /* program uses edge data. Distance to the edge is used to + * compute a coverage. See GrDrawState::setVertexEdgeType(). + */ + kEdge_AttribBindingsBit = 1 << (kNumStages + 2), + // for below assert + kDummyAttribBindingsBit, + kHighAttribBindingsBit = kDummyAttribBindingsBit - 1 + }; + // make sure we haven't exceeded the number of bits in GrAttribBindings. + GR_STATIC_ASSERT(kHighAttribBindingsBit < ((uint64_t)1 << 8*sizeof(GrAttribBindings))); + + enum AttribBindings { + kDefault_AttribBindings = 0 + }; + + /** + * Sets attribute bindings for next draw. + * + * @param bindings the attribute bindings to set. + */ + void setAttribBindings(GrAttribBindings bindings) { fCommon.fAttribBindings = bindings; } + + GrAttribBindings getAttribBindings() const { return fCommon.fAttribBindings; } + + //////////////////////////////////////////////////////////////////////////// + // Helpers for picking apart attribute bindings + + /** + * Helper function to determine if program uses explicit texture + * coordinates. + * + * @param bindings attribute bindings to query + * + * @return true if program uses texture coordinates, + * false otherwise. + */ + static bool AttributesBindExplicitTexCoords(GrAttribBindings bindings); + + /** + * Determines whether src alpha is guaranteed to be one for all src pixels + */ + bool srcAlphaWillBeOne(GrAttribBindings) const; + + /** + * Determines whether the output coverage is guaranteed to be one for all pixels hit by a draw. + */ + bool hasSolidCoverage(GrAttribBindings) const; + + static void VertexAttributesUnitTest(); + + /// @} + + /////////////////////////////////////////////////////////////////////////// + /// @name Vertex Attribute Indices + //// + + /** + * Vertex attribute indices map the data set in the vertex attribute array + * to the bindings specified in the attribute bindings. Each binding type + * has an associated index in the attribute array. This index is used to + * look up the vertex attribute data from the array, and potentially as the + * attribute index if we're binding attributes in GL. + * + * Indices which do not have active attribute bindings will be ignored. + */ + + enum AttribIndex { + kPosition_AttribIndex = 0, + kColor_AttribIndex, + kCoverage_AttribIndex, + kEdge_AttribIndex, + kTexCoord_AttribIndex, + + kLast_AttribIndex = kTexCoord_AttribIndex + }; + static const int kAttribIndexCount = kLast_AttribIndex + 1; + + // these are used when vertex color and coverage isn't set + enum { + kColorOverrideAttribIndexValue = GrDrawState::kVertexAttribCnt, + kCoverageOverrideAttribIndexValue = GrDrawState::kVertexAttribCnt+1, + }; + + //////////////////////////////////////////////////////////////////////////// + // Helpers to set attribute indices. These should match the index in the + // current attribute index array. + + /** + * Sets index for next draw. This is used to look up the offset + * from the current vertex attribute array and to bind the attributes. + * + * @param index the attribute index we're setting + * @param value the value of the index + */ + void setAttribIndex(AttribIndex index, int value) { fAttribIndices[index] = value; } + + int getAttribIndex(AttribIndex index) const { return fAttribIndices[index]; } /// @} @@ -1004,7 +1030,7 @@ public: /** * Determines the interpretation per-vertex edge data when the - * kEdge_VertexLayoutBit is set (see GrDrawTarget). When per-vertex edges + * kEdge_AttribBindingsBit is set (see GrDrawTarget). When per-vertex edges * are not specified the value of this setting has no effect. */ void setVertexEdgeType(VertexEdgeType type) { @@ -1159,13 +1185,25 @@ public: return (NULL != fStages[s].getEffect()); } - // Most stages are usually not used, so conditionals here - // reduce the expected number of bytes touched by 50%. bool operator ==(const GrDrawState& s) const { if (fRenderTarget.get() != s.fRenderTarget.get() || fCommon != s.fCommon) { return false; } - + if (fVertexAttribs.count() != s.fVertexAttribs.count()) { + return false; + } + for (int i = 0; i < fVertexAttribs.count(); ++i) { + if (fVertexAttribs[i] != s.fVertexAttribs[i]) { + return false; + } + } + for (int i = 0; i < kAttribIndexCount; ++i) { + if ((i == kPosition_AttribIndex || + s.fCommon.fAttribBindings & kAttribIndexMasks[i]) && + fAttribIndices[i] != s.fAttribIndices[i]) { + return false; + } + } for (int i = 0; i < kNumStages; i++) { bool enabled = this->isStageEnabled(i); if (enabled != s.isStageEnabled(i)) { @@ -1182,6 +1220,10 @@ public: GrDrawState& operator= (const GrDrawState& s) { this->setRenderTarget(s.fRenderTarget.get()); fCommon = s.fCommon; + fVertexAttribs = s.fVertexAttribs; + for (int i = 0; i < kAttribIndexCount; i++) { + fAttribIndices[i] = s.fAttribIndices[i]; + } for (int i = 0; i < kNumStages; i++) { if (s.isStageEnabled(i)) { this->fStages[i] = s.fStages[i]; @@ -1196,7 +1238,7 @@ private: struct CommonState { // These fields are roughly sorted by decreasing likelihood of being different in op== GrColor fColor; - GrVertexLayout fVertexLayout; + GrAttribBindings fAttribBindings; SkMatrix fViewMatrix; GrBlendCoeff fSrcBlend; GrBlendCoeff fDstBlend; @@ -1211,7 +1253,7 @@ private: DrawFace fDrawFace; bool operator== (const CommonState& other) const { return fColor == other.fColor && - fVertexLayout == other.fVertexLayout && + fAttribBindings == other.fAttribBindings && fViewMatrix.cheapEqualTo(other.fViewMatrix) && fSrcBlend == other.fSrcBlend && fDstBlend == other.fDstBlend && @@ -1256,6 +1298,10 @@ public: // TODO: Here we will copy the GrRenderTarget pointer without taking a ref. fRenderTarget = drawState.fRenderTarget.get(); SkSafeRef(fRenderTarget); + fVertexAttribs = drawState.fVertexAttribs; + for (int i = 0; i < kAttribIndexCount; i++) { + fAttribIndices[i] = drawState.fAttribIndices[i]; + } // Here we ref the effects directly rather than the effect-refs. TODO: When the effect- // ref gets fully unref'ed it will cause the underlying effect to unref its resources // and recycle them to the cache (if no one else is holding a ref to the resources). @@ -1269,6 +1315,10 @@ public: GrAssert(fInitialized); drawState->fCommon = fCommon; drawState->setRenderTarget(fRenderTarget); + drawState->fVertexAttribs = fVertexAttribs; + for (int i = 0; i < kAttribIndexCount; i++) { + drawState->fAttribIndices[i] = fAttribIndices[i]; + } for (int i = 0; i < kNumStages; ++i) { fStages[i].restoreTo(&drawState->fStages[i]); } @@ -1278,6 +1328,20 @@ public: if (fRenderTarget != state.fRenderTarget.get() || fCommon != state.fCommon) { return false; } + for (int i = 0; i < kAttribIndexCount; ++i) { + if ((i == kPosition_AttribIndex || + state.fCommon.fAttribBindings & kAttribIndexMasks[i]) && + fAttribIndices[i] != state.fAttribIndices[i]) { + return false; + } + } + if (fVertexAttribs.count() != state.fVertexAttribs.count()) { + return false; + } + for (int i = 0; i < fVertexAttribs.count(); ++i) + if (fVertexAttribs[i] != state.fVertexAttribs[i]) { + return false; + } for (int i = 0; i < kNumStages; ++i) { if (!fStages[i].isEqual(state.fStages[i])) { return false; @@ -1287,17 +1351,25 @@ public: } private: - GrRenderTarget* fRenderTarget; - CommonState fCommon; - GrEffectStage::DeferredStage fStages[kNumStages]; + GrRenderTarget* fRenderTarget; + CommonState fCommon; + int fAttribIndices[kAttribIndexCount]; + GrVertexAttribArray<kVertexAttribCnt> fVertexAttribs; + GrEffectStage::DeferredStage fStages[kNumStages]; GR_DEBUGCODE(bool fInitialized;) }; private: - SkAutoTUnref<GrRenderTarget> fRenderTarget; - CommonState fCommon; - GrEffectStage fStages[kNumStages]; + // helper array to let us check the current bindings so we know what bound attrib indices + // we care about + static const GrAttribBindings kAttribIndexMasks[kAttribIndexCount]; + + SkAutoTUnref<GrRenderTarget> fRenderTarget; + CommonState fCommon; + int fAttribIndices[kAttribIndexCount]; + GrVertexAttribArray<kVertexAttribCnt> fVertexAttribs; + GrEffectStage fStages[kNumStages]; typedef GrRefCnt INHERITED; }; diff --git a/src/gpu/GrDrawTarget.cpp b/src/gpu/GrDrawTarget.cpp index 2c2d949224..dab2965c6b 100644 --- a/src/gpu/GrDrawTarget.cpp +++ b/src/gpu/GrDrawTarget.cpp @@ -530,11 +530,19 @@ void GrDrawTarget::drawRect(const GrRect& rect, const GrRect* srcRect, const SkMatrix* srcMatrix, int stage) { - GrVertexLayout layout = 0; + GrAttribBindings bindings = 0; uint32_t explicitCoordMask = 0; + // position + (optional) texture coord + static const GrVertexAttrib kAttribs[] = { + GrVertexAttrib(kVec2f_GrVertexAttribType, 0), + GrVertexAttrib(kVec2f_GrVertexAttribType, sizeof(GrPoint)) + }; + int attribCount = 1; if (NULL != srcRect) { - layout |= GrDrawState::StageTexCoordVertexLayoutBit(stage); + bindings |= GrDrawState::ExplicitTexCoordAttribBindingsBit(stage); + attribCount = 2; + this->drawState()->setAttribIndex(GrDrawState::kTexCoord_AttribIndex, 1); explicitCoordMask = (1 << stage); } @@ -543,30 +551,26 @@ void GrDrawTarget::drawRect(const GrRect& rect, avmr.set(this->drawState(), *matrix, explicitCoordMask); } - this->drawState()->setVertexLayout(layout); + this->drawState()->setVertexAttribs(kAttribs, attribCount); + this->drawState()->setAttribIndex(GrDrawState::kPosition_AttribIndex, 0); + this->drawState()->setAttribBindings(bindings); AutoReleaseGeometry geo(this, 4, 0); if (!geo.succeeded()) { GrPrintf("Failed to get space for vertices!\n"); return; } - int stageOffsets[GrDrawState::kNumStages]; - int vsize = GrDrawState::VertexSizeAndOffsetsByStage(layout, stageOffsets, NULL, NULL, NULL); + size_t vsize = this->drawState()->getVertexSize(); geo.positions()->setRectFan(rect.fLeft, rect.fTop, rect.fRight, rect.fBottom, vsize); - - for (int i = 0; i < GrDrawState::kNumStages; ++i) { - if (explicitCoordMask & (1 << i)) { - GrAssert(0 != stageOffsets[i]); - GrPoint* coords = GrTCast<GrPoint*>(GrTCast<intptr_t>(geo.vertices()) + - stageOffsets[i]); - coords->setRectFan(srcRect->fLeft, srcRect->fTop, - srcRect->fRight, srcRect->fBottom, - vsize); - if (NULL != srcMatrix) { - srcMatrix->mapPointsWithStride(coords, vsize, 4); - } - } else { - GrAssert(0 == stageOffsets[i]); + if (NULL != srcRect) { + GrAssert(attribCount == 2); + GrPoint* coords = GrTCast<GrPoint*>(GrTCast<intptr_t>(geo.vertices()) + + kAttribs[1].fOffset); + coords->setRectFan(srcRect->fLeft, srcRect->fTop, + srcRect->fRight, srcRect->fBottom, + vsize); + if (NULL != srcMatrix) { + srcMatrix->mapPointsWithStride(coords, vsize, 4); } } diff --git a/src/gpu/GrInOrderDrawBuffer.cpp b/src/gpu/GrInOrderDrawBuffer.cpp index 00aaadbe98..b2705a4b9b 100644 --- a/src/gpu/GrInOrderDrawBuffer.cpp +++ b/src/gpu/GrInOrderDrawBuffer.cpp @@ -78,9 +78,20 @@ void GrInOrderDrawBuffer::drawRect(const GrRect& rect, const SkMatrix* srcMatrix, int stage) { - GrVertexLayout layout = 0; + GrAttribBindings bindings = GrDrawState::kDefault_AttribBindings; GrDrawState::AutoColorRestore acr; - GrColor color = this->drawState()->getColor(); + + GrDrawState* drawState = this->drawState(); + + GrColor color = drawState->getColor(); + GrVertexAttribArray<3> attribs; + size_t currentOffset = 0; + int colorOffset = -1, texOffset = -1; + + // set position attrib + drawState->setAttribIndex(GrDrawState::kPosition_AttribIndex, attribs.count()); + attribs.push_back(GrVertexAttrib(kVec2f_GrVertexAttribType, currentOffset)); + currentOffset += sizeof(GrPoint); // Using per-vertex colors allows batching across colors. (A lot of rects in a row differing // only in color is a common occurrence in tables). However, having per-vertex colors disables @@ -89,22 +100,31 @@ void GrInOrderDrawBuffer::drawRect(const GrRect& rect, // dual-source blending isn't available. This comes into play when there is coverage. If colors // were a stage it could take a hint that every vertex's color will be opaque. if (this->getCaps().dualSourceBlendingSupport() || - this->getDrawState().hasSolidCoverage(this->getDrawState().getVertexLayout())) { - layout |= GrDrawState::kColor_VertexLayoutBit;; + drawState->hasSolidCoverage(drawState->getAttribBindings())) { + bindings |= GrDrawState::kColor_AttribBindingsBit; + drawState->setAttribIndex(GrDrawState::kColor_AttribIndex, attribs.count()); + attribs.push_back(GrVertexAttrib(kVec4ub_GrVertexAttribType, currentOffset)); + colorOffset = currentOffset; + currentOffset += sizeof(GrColor); // We set the draw state's color to white here. This is done so that any batching performed // in our subclass's onDraw() won't get a false from GrDrawState::op== due to a color // mismatch. TODO: Once vertex layout is owned by GrDrawState it should skip comparing the // constant color in its op== when the kColor layout bit is set and then we can remove this. - acr.set(this->drawState(), 0xFFFFFFFF); + acr.set(drawState, 0xFFFFFFFF); } uint32_t explicitCoordMask = 0; if (NULL != srcRect) { - layout |= GrDrawState::StageTexCoordVertexLayoutBit(stage); + bindings |= GrDrawState::ExplicitTexCoordAttribBindingsBit(stage); + drawState->setAttribIndex(GrDrawState::kTexCoord_AttribIndex, attribs.count()); + attribs.push_back(GrVertexAttrib(kVec2f_GrVertexAttribType, currentOffset)); + texOffset = currentOffset; + currentOffset += sizeof(GrPoint); explicitCoordMask = (1 << stage); } - this->drawState()->setVertexLayout(layout); + drawState->setVertexAttribs(attribs.begin(), attribs.count()); + drawState->setAttribBindings(bindings); AutoReleaseGeometry geo(this, 4, 0); if (!geo.succeeded()) { GrPrintf("Failed to get space for vertices!\n"); @@ -118,18 +138,17 @@ void GrInOrderDrawBuffer::drawRect(const GrRect& rect, } else { combinedMatrix.reset(); } - combinedMatrix.postConcat(this->drawState()->getViewMatrix()); + combinedMatrix.postConcat(drawState->getViewMatrix()); // When the caller has provided an explicit source rect for a stage then we don't want to // modify that stage's matrix. Otherwise if the effect is generating its source rect from // the vertex positions then we have to account for the view matrix change. - GrDrawState::AutoDeviceCoordDraw adcd(this->drawState(), explicitCoordMask); + GrDrawState::AutoDeviceCoordDraw adcd(drawState, explicitCoordMask); if (!adcd.succeeded()) { return; } - int stageOffsets[GrDrawState::kNumStages], colorOffset; - int vsize = GrDrawState::VertexSizeAndOffsetsByStage(layout, stageOffsets, - &colorOffset, NULL, NULL); + size_t vsize = drawState->getVertexSize(); + GrAssert(vsize == currentOffset); geo.positions()->setRectFan(rect.fLeft, rect.fTop, rect.fRight, rect.fBottom, vsize); combinedMatrix.mapPointsWithStride(geo.positions(), vsize, 4); @@ -139,19 +158,15 @@ void GrInOrderDrawBuffer::drawRect(const GrRect& rect, // unnecessary clipping in our onDraw(). get_vertex_bounds(geo.vertices(), vsize, 4, &devBounds); - for (int i = 0; i < GrDrawState::kNumStages; ++i) { - if (explicitCoordMask & (1 << i)) { - GrAssert(0 != stageOffsets[i]); - GrPoint* coords = GrTCast<GrPoint*>(GrTCast<intptr_t>(geo.vertices()) + - stageOffsets[i]); - coords->setRectFan(srcRect->fLeft, srcRect->fTop, - srcRect->fRight, srcRect->fBottom, - vsize); - if (NULL != srcMatrix) { - srcMatrix->mapPointsWithStride(coords, vsize, 4); - } - } else { - GrAssert(0 == stageOffsets[i]); + if (texOffset >= 0) { + GrAssert(explicitCoordMask != 0); + GrPoint* coords = GrTCast<GrPoint*>(GrTCast<intptr_t>(geo.vertices()) + + texOffset); + coords->setRectFan(srcRect->fLeft, srcRect->fTop, + srcRect->fRight, srcRect->fBottom, + vsize); + if (NULL != srcMatrix) { + srcMatrix->mapPointsWithStride(coords, vsize, 4); } } @@ -165,6 +180,9 @@ void GrInOrderDrawBuffer::drawRect(const GrRect& rect, this->setIndexSourceToBuffer(this->getContext()->getQuadIndexBuffer()); this->drawIndexedInstances(kTriangles_GrPrimitiveType, 1, 4, 6, &devBounds); + + // to ensure that stashing the drawState ptr is valid + GrAssert(this->drawState() == drawState); } bool GrInOrderDrawBuffer::quickInsideClip(const SkRect& devBounds) { diff --git a/src/gpu/GrTextContext.cpp b/src/gpu/GrTextContext.cpp index e599fc9500..e77bf93429 100644 --- a/src/gpu/GrTextContext.cpp +++ b/src/gpu/GrTextContext.cpp @@ -92,8 +92,6 @@ GrTextContext::GrTextContext(GrContext* context, const GrPaint& paint) : fPaint( fVertices = NULL; fMaxVertices = 0; - - fVertexLayout = GrDrawState::StageTexCoordVertexLayoutBit(kGlyphMaskStage); } GrTextContext::~GrTextContext() { @@ -189,13 +187,20 @@ HAS_ATLAS: } if (NULL == fVertices) { - // If we need to reserve vertices allow the draw target to suggest + // position + texture coord + static const GrVertexAttrib kVertexAttribs[] = { + GrVertexAttrib(kVec2f_GrVertexAttribType, 0), + GrVertexAttrib(kVec2f_GrVertexAttribType, sizeof(GrPoint)) + }; + static const GrAttribBindings kAttribBindings = GrDrawState::ExplicitTexCoordAttribBindingsBit(kGlyphMaskStage); + + // If we need to reserve vertices allow the draw target to suggest // a number of verts to reserve and whether to perform a flush. fMaxVertices = kMinRequestedVerts; bool flush = false; fDrawTarget = fContext->getTextTarget(fPaint); if (NULL != fDrawTarget) { - fDrawTarget->drawState()->setVertexLayout(fVertexLayout); + fDrawTarget->drawState()->setVertexAttribs(kVertexAttribs, SK_ARRAY_COUNT(kVertexAttribs)); flush = fDrawTarget->geometryHints(&fMaxVertices, NULL); } if (flush) { @@ -203,8 +208,11 @@ HAS_ATLAS: fContext->flush(); // flushGlyphs() will reset fDrawTarget to NULL. fDrawTarget = fContext->getTextTarget(fPaint); - fDrawTarget->drawState()->setVertexLayout(fVertexLayout); + fDrawTarget->drawState()->setVertexAttribs(kVertexAttribs, SK_ARRAY_COUNT(kVertexAttribs)); } + fDrawTarget->drawState()->setAttribIndex(GrDrawState::kPosition_AttribIndex, 0); + fDrawTarget->drawState()->setAttribIndex(GrDrawState::kTexCoord_AttribIndex, 1); + fDrawTarget->drawState()->setAttribBindings(kAttribBindings); fMaxVertices = kDefaultRequestedVerts; // ignore return, no point in flushing again. fDrawTarget->geometryHints(&fMaxVertices, NULL); @@ -222,6 +230,7 @@ HAS_ATLAS: GrTCast<void**>(&fVertices), NULL); GrAlwaysAssert(success); + GrAssert(2*sizeof(GrPoint) == fDrawTarget->getDrawState().getVertexSize()); } GrFixed tx = SkIntToFixed(glyph->fAtlasLocation.fX); diff --git a/src/gpu/gl/GrGLProgram.cpp b/src/gpu/gl/GrGLProgram.cpp index 0ca84bc50a..781e15fdde 100644 --- a/src/gpu/gl/GrGLProgram.cpp +++ b/src/gpu/gl/GrGLProgram.cpp @@ -35,6 +35,14 @@ inline const char* declared_color_output_name() { return "fsColorOut"; } inline const char* dual_source_output_name() { return "dualSourceOut"; } } +const GrGLProgram::AttribLayout GrGLProgram::kAttribLayouts[kGrVertexAttribTypeCount] = { + {1, GR_GL_FLOAT, false}, // kFloat_GrVertexAttribType + {2, GR_GL_FLOAT, false}, // kVec2f_GrVertexAttribType + {3, GR_GL_FLOAT, false}, // kVec3f_GrVertexAttribType + {4, GR_GL_FLOAT, false}, // kVec4f_GrVertexAttribType + {4, GR_GL_UNSIGNED_BYTE, true}, // kVec4ub_GrVertexAttribType +}; + void GrGLProgram::BuildDesc(const GrDrawState& drawState, bool isPoints, GrDrawState::BlendOptFlags blendOpts, @@ -52,24 +60,24 @@ void GrGLProgram::BuildDesc(const GrDrawState& drawState, GrDrawState::kEmitCoverage_BlendOptFlag)); // The descriptor is used as a cache key. Thus when a field of the - // descriptor will not affect program generation (because of the vertex - // layout in use or other descriptor field settings) it should be set + // descriptor will not affect program generation (because of the attribute + // bindings in use or other descriptor field settings) it should be set // to a canonical value to avoid duplicate programs with different keys. // Must initialize all fields or cache will have false negatives! - desc->fVertexLayout = drawState.getVertexLayout(); + desc->fAttribBindings = drawState.getAttribBindings(); desc->fEmitsPointSize = isPoints; bool requiresAttributeColors = !skipColor && - SkToBool(desc->fVertexLayout & GrDrawState::kColor_VertexLayoutBit); + SkToBool(desc->fAttribBindings & GrDrawState::kColor_AttribBindingsBit); bool requiresAttributeCoverage = !skipCoverage && - SkToBool(desc->fVertexLayout & GrDrawState::kCoverage_VertexLayoutBit); + SkToBool(desc->fAttribBindings & GrDrawState::kCoverage_AttribBindingsBit); // fColorInput/fCoverageInput records how colors are specified for the program So we strip the - // bits from the layout to avoid false negatives when searching for an existing program in the + // bits from the bindings to avoid false negatives when searching for an existing program in the // cache. - desc->fVertexLayout &= ~(GrDrawState::kColor_VertexLayoutBit | GrDrawState::kCoverage_VertexLayoutBit); + desc->fAttribBindings &= ~(GrDrawState::kColor_AttribBindingsBit | GrDrawState::kCoverage_AttribBindingsBit); desc->fColorFilterXfermode = skipColor ? SkXfermode::kDst_Mode : @@ -77,8 +85,8 @@ void GrGLProgram::BuildDesc(const GrDrawState& drawState, // no reason to do edge aa or look at per-vertex coverage if coverage is ignored if (skipCoverage) { - desc->fVertexLayout &= ~(GrDrawState::kEdge_VertexLayoutBit | - GrDrawState::kCoverage_VertexLayoutBit); + desc->fAttribBindings &= ~(GrDrawState::kEdge_AttribBindingsBit | + GrDrawState::kCoverage_AttribBindingsBit); } bool colorIsTransBlack = SkToBool(blendOpts & GrDrawState::kEmitTransBlack_BlendOptFlag); @@ -108,7 +116,7 @@ void GrGLProgram::BuildDesc(const GrDrawState& drawState, int lastEnabledStage = -1; - if (!skipCoverage && (desc->fVertexLayout & GrDrawState::kEdge_VertexLayoutBit)) { + if (!skipCoverage && (desc->fAttribBindings & GrDrawState::kEdge_AttribBindingsBit)) { desc->fVertexEdgeType = drawState.getVertexEdgeType(); desc->fDiscardIfOutsideEdge = drawState.getStencil().doesWrite(); } else { @@ -155,7 +163,7 @@ void GrGLProgram::BuildDesc(const GrDrawState& drawState, // other coverage inputs if (!hasCoverage) { hasCoverage = requiresAttributeCoverage || - (desc->fVertexLayout & GrDrawState::kEdge_VertexLayoutBit); + (desc->fAttribBindings & GrDrawState::kEdge_AttribBindingsBit); } if (hasCoverage) { @@ -182,6 +190,43 @@ void GrGLProgram::BuildDesc(const GrDrawState& drawState, } } } + + desc->fPositionAttributeIndex = drawState.getAttribIndex(GrDrawState::kPosition_AttribIndex); + if (requiresAttributeColors) { + desc->fColorAttributeIndex = drawState.getAttribIndex(GrDrawState::kColor_AttribIndex); + } else { + desc->fColorAttributeIndex = GrDrawState::kColorOverrideAttribIndexValue; + } + if (requiresAttributeCoverage) { + desc->fCoverageAttributeIndex = drawState.getAttribIndex(GrDrawState::kCoverage_AttribIndex); + } else { + desc->fCoverageAttributeIndex = GrDrawState::kCoverageOverrideAttribIndexValue; + } + desc->fEdgeAttributeIndex = drawState.getAttribIndex(GrDrawState::kEdge_AttribIndex); + desc->fTexCoordAttributeIndex = drawState.getAttribIndex(GrDrawState::kTexCoord_AttribIndex); + +#if GR_DEBUG + // verify valid vertex attribute state + const GrVertexAttrib* vertexAttribs = drawState.getVertexAttribs(); + GrAssert(desc->fPositionAttributeIndex < GrDrawState::kVertexAttribCnt); + GrAssert(kAttribLayouts[vertexAttribs[desc->fPositionAttributeIndex].fType].fCount == 2); + if (requiresAttributeColors) { + GrAssert(desc->fColorAttributeIndex < GrDrawState::kVertexAttribCnt); + GrAssert(kAttribLayouts[vertexAttribs[desc->fColorAttributeIndex].fType].fCount == 4); + } + if (requiresAttributeCoverage) { + GrAssert(desc->fCoverageAttributeIndex < GrDrawState::kVertexAttribCnt); + GrAssert(kAttribLayouts[vertexAttribs[desc->fCoverageAttributeIndex].fType].fCount == 4); + } + if (desc->fAttribBindings & GrDrawState::kEdge_AttribBindingsBit) { + GrAssert(desc->fEdgeAttributeIndex < GrDrawState::kVertexAttribCnt); + GrAssert(kAttribLayouts[vertexAttribs[desc->fEdgeAttributeIndex].fType].fCount == 4); + } + if (GrDrawState::AttributesBindExplicitTexCoords(desc->fAttribBindings)) { + GrAssert(desc->fTexCoordAttributeIndex < GrDrawState::kVertexAttribCnt); + GrAssert(kAttribLayouts[vertexAttribs[desc->fTexCoordAttributeIndex].fType].fCount == 2); + } +#endif } GrGLProgram* GrGLProgram::Create(const GrGLContext& gl, @@ -366,7 +411,7 @@ void add_color_filter(SkString* fsCode, const char * outputVar, bool GrGLProgram::genEdgeCoverage(SkString* coverageVar, GrGLShaderBuilder* builder) const { - if (fDesc.fVertexLayout & GrDrawState::kEdge_VertexLayoutBit) { + if (fDesc.fAttribBindings & GrDrawState::kEdge_AttribBindingsBit) { const char *vsName, *fsName; builder->addVarying(kVec4f_GrSLType, "Edge", &vsName, &fsName); builder->fVSAttrs.push_back().set(kVec4f_GrSLType, @@ -645,7 +690,7 @@ bool GrGLProgram::genProgram(const GrEffectStage* stages[]) { GrAssert(0 == fProgramID); GrGLShaderBuilder builder(fContext.info(), fUniformManager); - const uint32_t& layout = fDesc.fVertexLayout; + const GrAttribBindings& attribBindings = fDesc.fAttribBindings; #if GR_GL_EXPERIMENTAL_GS builder.fUsesGS = fDesc.fExperimentalGS; @@ -726,7 +771,7 @@ bool GrGLProgram::genProgram(const GrEffectStage* stages[]) { } // add texture coordinates that are used to the list of vertex attr decls - if (GrDrawState::VertexUsesTexCoords(layout)) { + if (GrDrawState::AttributesBindExplicitTexCoords(attribBindings)) { builder.fVSAttrs.push_back().set(kVec2f_GrSLType, GrGLShaderVar::kAttribute_TypeModifier, TEX_ATTR_NAME); @@ -748,7 +793,7 @@ bool GrGLProgram::genProgram(const GrEffectStage* stages[]) { const char* inCoords; // figure out what our input coords are - if (!GrDrawState::StageUsesTexCoords(layout, s)) { + if (!GrDrawState::StageBindsExplicitTexCoords(attribBindings, s)) { inCoords = builder.positionAttribute().c_str(); } else { // must have input tex coordinates if stage is enabled. @@ -842,7 +887,7 @@ bool GrGLProgram::genProgram(const GrEffectStage* stages[]) { const char* inCoords; // figure out what our input coords are - if (!GrDrawState::StageUsesTexCoords(layout, s)) { + if (!GrDrawState::StageBindsExplicitTexCoords(attribBindings, s)) { inCoords = builder.positionAttribute().c_str(); } else { // must have input tex coordinates if stage is @@ -966,13 +1011,18 @@ bool GrGLProgram::bindOutputsAttribsAndLinkProgram(const GrGLShaderBuilder& buil // Bind the attrib locations to same values for all shaders GL_CALL(BindAttribLocation(fProgramID, - kPositionAttributeIndex, + fDesc.fPositionAttributeIndex, builder.positionAttribute().c_str())); - GL_CALL(BindAttribLocation(fProgramID, kTexCoordAttributeIndex, TEX_ATTR_NAME)); - GL_CALL(BindAttribLocation(fProgramID, kColorAttributeIndex, COL_ATTR_NAME)); - GL_CALL(BindAttribLocation(fProgramID, kCoverageAttributeIndex, COV_ATTR_NAME)); - GL_CALL(BindAttribLocation(fProgramID, kEdgeAttributeIndex, EDGE_ATTR_NAME)); - + GL_CALL(BindAttribLocation(fProgramID, fDesc.fColorAttributeIndex, COL_ATTR_NAME)); + GL_CALL(BindAttribLocation(fProgramID, fDesc.fCoverageAttributeIndex, COV_ATTR_NAME)); + + if (fDesc.fAttribBindings & GrDrawState::kEdge_AttribBindingsBit) { + GL_CALL(BindAttribLocation(fProgramID, fDesc.fEdgeAttributeIndex, EDGE_ATTR_NAME)); + } + if (GrDrawState::AttributesBindExplicitTexCoords(fDesc.fAttribBindings)) { + GL_CALL(BindAttribLocation(fProgramID, fDesc.fTexCoordAttributeIndex, TEX_ATTR_NAME)); + } + GL_CALL(LinkProgram(fProgramID)); GrGLint linked = GR_GL_INIT_ZERO; @@ -1060,14 +1110,14 @@ void GrGLProgram::setData(GrGpuGL* gpu, void GrGLProgram::setColor(const GrDrawState& drawState, GrColor color, SharedGLState* sharedState) { - if (!(drawState.getVertexLayout() & GrDrawState::kColor_VertexLayoutBit)) { + if (!(drawState.getAttribBindings() & GrDrawState::kColor_AttribBindingsBit)) { switch (fDesc.fColorInput) { case GrGLProgram::Desc::kAttribute_ColorInput: if (sharedState->fConstAttribColor != color) { // OpenGL ES only supports the float varieties of glVertexAttrib GrGLfloat c[4]; GrColorToRGBAFloat(color, c); - GL_CALL(VertexAttrib4fv(kColorAttributeIndex, c)); + GL_CALL(VertexAttrib4fv(fDesc.fColorAttributeIndex, c)); sharedState->fConstAttribColor = color; } break; @@ -1094,14 +1144,14 @@ void GrGLProgram::setColor(const GrDrawState& drawState, void GrGLProgram::setCoverage(const GrDrawState& drawState, GrColor coverage, SharedGLState* sharedState) { - if (!(drawState.getVertexLayout() & GrDrawState::kCoverage_VertexLayoutBit)) { + if (!(drawState.getAttribBindings() & GrDrawState::kCoverage_AttribBindingsBit)) { switch (fDesc.fCoverageInput) { case Desc::kAttribute_ColorInput: if (sharedState->fConstAttribCoverage != coverage) { // OpenGL ES only supports the float varieties of glVertexAttrib GrGLfloat c[4]; GrColorToRGBAFloat(coverage, c); - GL_CALL(VertexAttrib4fv(kCoverageAttributeIndex, c)); + GL_CALL(VertexAttrib4fv(fDesc.fCoverageAttributeIndex, c)); sharedState->fConstAttribCoverage = coverage; } break; diff --git a/src/gpu/gl/GrGLProgram.h b/src/gpu/gl/GrGLProgram.h index a2958e736b..cde918b54b 100644 --- a/src/gpu/gl/GrGLProgram.h +++ b/src/gpu/gl/GrGLProgram.h @@ -79,17 +79,6 @@ public: GrGLuint programID() const { return fProgramID; } /** - * Attribute indices. These should not overlap. - */ - enum { - kPositionAttributeIndex = 0, - kColorAttributeIndex = 1, - kCoverageAttributeIndex = 2, - kEdgeAttributeIndex = 3, - kTexCoordAttributeIndex = 4, - }; - - /** * Some GL state that is relevant to programs is not stored per-program. In particular vertex * attributes are global state. This struct is read and updated by GrGLProgram::setData to * allow us to avoid setting this state redundantly. @@ -182,7 +171,7 @@ public: bool fDiscardIfOutsideEdge; // stripped of bits that don't affect program generation - GrVertexLayout fVertexLayout; + GrAttribBindings fAttribBindings; /** Non-zero if this stage has an effect */ GrGLEffect::EffectKey fEffectKeys[GrDrawState::kNumStages]; @@ -199,9 +188,23 @@ public: SkBool8 fEmitsPointSize; uint8_t fColorFilterXfermode; // casts to enum SkXfermode::Mode + int8_t fPositionAttributeIndex; + int8_t fColorAttributeIndex; + int8_t fCoverageAttributeIndex; + int8_t fEdgeAttributeIndex; + int8_t fTexCoordAttributeIndex; + friend class GrGLProgram; }; + // Layout information for OpenGL vertex attributes + struct AttribLayout { + GrGLint fCount; + GrGLenum fType; + GrGLboolean fNormalized; + }; + static const AttribLayout kAttribLayouts[kGrVertexAttribTypeCount]; + private: GrGLProgram(const GrGLContext& gl, const Desc& desc, diff --git a/src/gpu/gl/GrGpuGL.cpp b/src/gpu/gl/GrGpuGL.cpp index f9c94c4f78..42e83b0435 100644 --- a/src/gpu/gl/GrGpuGL.cpp +++ b/src/gpu/gl/GrGpuGL.cpp @@ -182,6 +182,10 @@ GrGpuGL::GrGpuGL(const GrGLContext& ctx, GrContext* context) fHWGeometryState.setMaxAttribArrays(this->glCaps().maxVertexAttributes()); + GrAssert(this->glCaps().maxVertexAttributes() >= GrDrawState::kVertexAttribCnt); + GrAssert(this->glCaps().maxVertexAttributes() > GrDrawState::kColorOverrideAttribIndexValue); + GrAssert(this->glCaps().maxVertexAttributes() > GrDrawState::kCoverageOverrideAttribIndexValue); + fLastSuccessfulStencilFmtIdx = 0; if (false) { // avoid bit rot, suppress warning fbo_test(this->glInterface(), 0, 0); diff --git a/src/gpu/gl/GrGpuGL_program.cpp b/src/gpu/gl/GrGpuGL_program.cpp index 93af1b9196..e5a71831ec 100644 --- a/src/gpu/gl/GrGpuGL_program.cpp +++ b/src/gpu/gl/GrGpuGL_program.cpp @@ -215,83 +215,30 @@ bool GrGpuGL::flushGraphicsState(DrawType type) { void GrGpuGL::setupGeometry(const DrawInfo& info, size_t* indexOffsetInBytes) { - int colorOffset; - int coverageOffset; - int texCoordOffset; - int edgeOffset; - - GrVertexLayout currLayout = this->getDrawState().getVertexLayout(); - - GrGLsizei stride = GrDrawState::VertexSizeAndOffsets(currLayout, - &texCoordOffset, - &colorOffset, - &coverageOffset, - &edgeOffset); + GrGLsizei stride = this->getDrawState().getVertexSize(); size_t vertexOffset; GrGLVertexBuffer* vb= this->setBuffers(info.isIndexed(), &vertexOffset, indexOffsetInBytes); vertexOffset += stride * info.startVertex(); - uint32_t usedAttribArraysMask = (1 << GrGLProgram::kPositionAttributeIndex); - fHWGeometryState.setAttribArray(this, - GrGLProgram::kPositionAttributeIndex, - vb, - 2, - GR_GL_FLOAT, - false, - stride, - reinterpret_cast<GrGLvoid*>(vertexOffset)); - if (texCoordOffset > 0) { - usedAttribArraysMask |= (1 << GrGLProgram::kTexCoordAttributeIndex); - GrGLvoid* texCoordPtr = reinterpret_cast<GrGLvoid*>(vertexOffset + texCoordOffset); - fHWGeometryState.setAttribArray(this, - GrGLProgram::kTexCoordAttributeIndex, - vb, - 2, - GR_GL_FLOAT, - false, - stride, - texCoordPtr); - } + uint32_t usedAttribArraysMask = 0; + const GrVertexAttrib* vertexAttrib = this->getDrawState().getVertexAttribs(); + int vertexAttribCount = this->getDrawState().getVertexAttribCount(); + for (int vertexAttribIndex = 0; vertexAttribIndex < vertexAttribCount; + ++vertexAttribIndex, ++vertexAttrib) { - if (colorOffset > 0) { - usedAttribArraysMask |= (1 << GrGLProgram::kColorAttributeIndex); - GrGLvoid* colorPtr = reinterpret_cast<GrGLvoid*>(vertexOffset + colorOffset); + usedAttribArraysMask |= (1 << vertexAttribIndex); + GrVertexAttribType attribType = vertexAttrib->fType; fHWGeometryState.setAttribArray(this, - GrGLProgram::kColorAttributeIndex, + vertexAttribIndex, vb, - 4, - GR_GL_UNSIGNED_BYTE, - true, + GrGLProgram::kAttribLayouts[attribType].fCount, + GrGLProgram::kAttribLayouts[attribType].fType, + GrGLProgram::kAttribLayouts[attribType].fNormalized, stride, - colorPtr); - } - - if (coverageOffset > 0) { - usedAttribArraysMask |= (1 << GrGLProgram::kCoverageAttributeIndex); - GrGLvoid* coveragePtr = reinterpret_cast<GrGLvoid*>(vertexOffset + coverageOffset); - fHWGeometryState.setAttribArray(this, - GrGLProgram::kCoverageAttributeIndex, - vb, - 4, - GR_GL_UNSIGNED_BYTE, - true, - stride, - coveragePtr); - } - - if (edgeOffset > 0) { - usedAttribArraysMask |= (1 << GrGLProgram::kEdgeAttributeIndex); - GrGLvoid* edgePtr = reinterpret_cast<GrGLvoid*>(vertexOffset + edgeOffset); - fHWGeometryState.setAttribArray(this, - GrGLProgram::kEdgeAttributeIndex, - vb, - 4, - GR_GL_FLOAT, - false, - stride, - edgePtr); - } + reinterpret_cast<GrGLvoid*>( + vertexOffset + vertexAttrib->fOffset)); + } fHWGeometryState.disableUnusedAttribArrays(this, usedAttribArraysMask); } diff --git a/src/gpu/gr_unittests.cpp b/src/gpu/gr_unittests.cpp index 7f5c7e9cff..c7daf7718f 100644 --- a/src/gpu/gr_unittests.cpp +++ b/src/gpu/gr_unittests.cpp @@ -75,5 +75,5 @@ void gr_run_unittests() { test_bsearch(); test_binHashKey(); GrRedBlackTree<int>::UnitTest(); - GrDrawState::VertexLayoutUnitTest(); + GrDrawState::VertexAttributesUnitTest(); } |