diff --git a/experimental/AndroidPathRenderer/GrAndroidPathRenderer.cpp b/experimental/AndroidPathRenderer/GrAndroidPathRenderer.cpp index 66cb93a87..2050f091a 100644 --- a/experimental/AndroidPathRenderer/GrAndroidPathRenderer.cpp +++ b/experimental/AndroidPathRenderer/GrAndroidPathRenderer.cpp @@ -36,25 +36,12 @@ bool GrAndroidPathRenderer::onDrawPath(const SkPath& origPath, android::uirenderer::PathRenderer::ConvexPathVertices(origPath, stroke, antiAlias, NULL, &vertices); - // set vertex attributes depending on anti-alias - GrDrawState* drawState = target->drawState(); - if (antiAlias) { - // position + coverage - GrVertexAttrib attribs[] = { - GrVertexAttrib(kVec2f_GrVertexAttribType, 0), - GrVertexAttrib(kVec4ub_GrVertexAttribType, sizeof(GrPoint)) - }; - drawState->setVertexAttribs(attribs, SK_ARRAY_COUNT(attribs)); - drawState->setAttribIndex(GrDrawState::kPosition_AttribIndex, 0); - drawState->setAttribIndex(GrDrawState::kCoverage_AttribIndex, 1); - drawState->setAttribBindings(GrDrawState::kCoverage_AttribBindingsBit); - } else { - drawState->setDefaultVertexAttribs(); - } + // set vertex layout depending on anti-alias + GrVertexLayout layout = antiAlias ? GrDrawState::kCoverage_VertexLayoutBit : 0; // allocate our vert buffer int vertCount = vertices.getSize(); - GrDrawTarget::AutoReleaseGeometry geo(target, vertCount, 0); + GrDrawTarget::AutoReleaseGeometry geo(target, layout, vertCount, 0); if (!geo.succeeded()) { GrPrintf("Failed to get space for vertices!\n"); return false; @@ -62,7 +49,6 @@ bool GrAndroidPathRenderer::onDrawPath(const SkPath& origPath, // copy android verts to our vertex buffer if (antiAlias) { - GrAssert(sizeof(ColorVertex) == drawState->getVertexSize()); ColorVertex* outVert = reinterpret_cast(geo.vertices()); android::uirenderer::AlphaVertex* inVert = reinterpret_cast(vertices.getBuffer()); @@ -77,7 +63,7 @@ bool GrAndroidPathRenderer::onDrawPath(const SkPath& origPath, ++inVert; } } else { - size_t vsize = drawState->getVertexSize(); + size_t vsize = GrDrawState::VertexSize(layout); size_t copySize = vsize*vertCount; memcpy(geo.vertices(), vertices.getBuffer(), copySize); } diff --git a/experimental/StrokePathRenderer/GrStrokePathRenderer.cpp b/experimental/StrokePathRenderer/GrStrokePathRenderer.cpp index a8ae91727..03c135df6 100644 --- a/experimental/StrokePathRenderer/GrStrokePathRenderer.cpp +++ b/experimental/StrokePathRenderer/GrStrokePathRenderer.cpp @@ -111,11 +111,11 @@ bool GrStrokePathRenderer::onDrawPath(const SkPath& origPath, // Allocate vertices const int nbQuads = origPath.countPoints() + 1; // Could be "-1" if path is not closed + GrVertexLayout layout = 0; // Just 3D points const int extraVerts = isMiter || isBevel ? 1 : 0; const int maxVertexCount = nbQuads * (4 + extraVerts); const int maxIndexCount = nbQuads * (6 + extraVerts * 3); // Each extra vert adds a triangle - target->drawState()->setDefaultVertexAttribs(); - GrDrawTarget::AutoReleaseGeometry arg(target, maxVertexCount, maxIndexCount); + GrDrawTarget::AutoReleaseGeometry arg(target, layout, maxVertexCount, maxIndexCount); if (!arg.succeeded()) { return false; } @@ -126,7 +126,7 @@ bool GrStrokePathRenderer::onDrawPath(const SkPath& origPath, // Transform the path into a list of triangles SkPath::Iter iter(origPath, false); SkPoint pts[4]; - const SkScalar radius = SkScalarMul(width, 0.5f); + const SkScalar radius = SkScalarMul(width, 0.5); SkPoint *firstPt = verts, *lastPt = NULL; SkVector firstDir, dir; firstDir.set(0, 0); diff --git a/include/core/SkTArray.h b/include/core/SkTArray.h index 89f4c9d30..3489de02d 100644 --- a/include/core/SkTArray.h +++ b/include/core/SkTArray.h @@ -223,20 +223,7 @@ public: } } - T* begin() { - return fItemArray; - } - const T* begin() const { - return fItemArray; - } - T* end() { - return fItemArray ? fItemArray + fCount : NULL; - } - const T* end() const { - return fItemArray ? fItemArray + fCount : NULL;; - } - - /** + /** * Get the i^th element. */ T& operator[] (int i) { diff --git a/include/gpu/GrTextContext.h b/include/gpu/GrTextContext.h index 348f3abb4..f329fdefd 100644 --- a/include/gpu/GrTextContext.h +++ b/include/gpu/GrTextContext.h @@ -32,6 +32,7 @@ public: private: GrPaint fPaint; + GrVertexLayout fVertexLayout; GrContext* fContext; GrDrawTarget* fDrawTarget; diff --git a/include/gpu/GrTypes.h b/include/gpu/GrTypes.h index 2ba499aa2..d79e0c36d 100644 --- a/include/gpu/GrTypes.h +++ b/include/gpu/GrTypes.h @@ -194,6 +194,12 @@ typedef intptr_t GrBackendContext; /////////////////////////////////////////////////////////////////////////////// +/** + * Type used to describe format of vertices in arrays + * Values are defined in GrDrawTarget + */ +typedef int GrVertexLayout; + /** * Geometric primitives used for drawing. */ diff --git a/src/gpu/GrAAConvexPathRenderer.cpp b/src/gpu/GrAAConvexPathRenderer.cpp index 46e75a07a..98eaab84c 100644 --- a/src/gpu/GrAAConvexPathRenderer.cpp +++ b/src/gpu/GrAAConvexPathRenderer.cpp @@ -453,6 +453,9 @@ 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. @@ -478,22 +481,11 @@ bool GrAAConvexPathRenderer::onDrawPath(const SkPath& origPath, return false; } - // 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); + drawState->setVertexLayout(layout); GrDrawTarget::AutoReleaseGeometry arg(target, vCount, iCount); if (!arg.succeeded()) { return false; } - GrAssert(sizeof(QuadVertex) == drawState->getVertexSize()); verts = reinterpret_cast(arg.vertices()); idxs = reinterpret_cast(arg.indices()); diff --git a/src/gpu/GrAAHairLinePathRenderer.cpp b/src/gpu/GrAAHairLinePathRenderer.cpp index a2ad9e332..00982ee4b 100644 --- a/src/gpu/GrAAHairLinePathRenderer.cpp +++ b/src/gpu/GrAAHairLinePathRenderer.cpp @@ -495,20 +495,15 @@ bool GrAAHairLinePathRenderer::createGeom( int* lineCnt, int* quadCnt, GrDrawTarget::AutoReleaseGeometry* arg) { - GrDrawState* drawState = target->drawState(); - int rtHeight = drawState->getRenderTarget()->height(); + const GrDrawState& drawState = target->getDrawState(); + int rtHeight = drawState.getRenderTarget()->height(); GrIRect devClipBounds; - target->getClip()->getConservativeBounds(drawState->getRenderTarget(), + target->getClip()->getConservativeBounds(drawState.getRenderTarget(), &devClipBounds); - // 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(); + GrVertexLayout layout = GrDrawState::kEdge_VertexLayoutBit; + SkMatrix viewM = drawState.getViewMatrix(); PREALLOC_PTARRAY(128) lines; PREALLOC_PTARRAY(128) quads; @@ -519,10 +514,7 @@ bool GrAAHairLinePathRenderer::createGeom( *lineCnt = lines.count() / 2; int vertCnt = kVertsPerLineSeg * *lineCnt + kVertsPerQuad * *quadCnt; - 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); + target->drawState()->setVertexLayout(layout); 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 741b83d08..d23c4b449 100644 --- a/src/gpu/GrAARectRenderer.cpp +++ b/src/gpu/GrAARectRenderer.cpp @@ -13,15 +13,14 @@ SK_DEFINE_INST_COUNT(GrAARectRenderer) namespace { -static void aa_rect_attributes(bool useCoverage, GrAttribBindings* bindings, - GrDrawState::AttribIndex* index) { +static GrVertexLayout aa_rect_layout(bool useCoverage) { + GrVertexLayout layout = 0; if (useCoverage) { - *bindings = GrDrawState::kCoverage_AttribBindingsBit; - *index = GrDrawState::kCoverage_AttribIndex; + layout |= GrDrawState::kCoverage_VertexLayoutBit; } else { - *bindings = GrDrawState::kColor_AttribBindingsBit; - *index = GrDrawState::kColor_AttribIndex; + layout |= GrDrawState::kColor_VertexLayoutBit; } + return layout; } static void set_inset_fan(GrPoint* pts, size_t stride, @@ -30,12 +29,6 @@ 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() { @@ -132,15 +125,8 @@ void GrAARectRenderer::fillAARect(GrGpu* gpu, GrDrawTarget* target, const GrRect& devRect, bool useVertexCoverage) { - 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); + GrVertexLayout layout = aa_rect_layout(useVertexCoverage); + target->drawState()->setVertexLayout(layout); GrDrawTarget::AutoReleaseGeometry geo(target, 8, 0); if (!geo.succeeded()) { @@ -155,8 +141,7 @@ void GrAARectRenderer::fillAARect(GrGpu* gpu, } intptr_t verts = reinterpret_cast(geo.vertices()); - size_t vsize = drawState->getVertexSize(); - GrAssert(sizeof(GrPoint) + sizeof(GrColor) == vsize); + size_t vsize = target->getDrawState().getVertexSize(); GrPoint* fan0Pos = reinterpret_cast(verts); GrPoint* fan1Pos = reinterpret_cast(verts + 4 * vsize); @@ -192,8 +177,6 @@ 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); @@ -212,14 +195,8 @@ void GrAARectRenderer::strokeAARect(GrGpu* gpu, this->fillAARect(gpu, target, r, useVertexCoverage); return; } - - 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); + GrVertexLayout layout = aa_rect_layout(useVertexCoverage); + target->drawState()->setVertexLayout(layout); GrDrawTarget::AutoReleaseGeometry geo(target, 16, 0); if (!geo.succeeded()) { @@ -233,8 +210,7 @@ void GrAARectRenderer::strokeAARect(GrGpu* gpu, } intptr_t verts = reinterpret_cast(geo.vertices()); - size_t vsize = drawState->getVertexSize(); - GrAssert(sizeof(GrPoint) + sizeof(GrColor) == vsize); + size_t vsize = target->getDrawState().getVertexSize(); // 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 3b77b73fe..0f6fa1651 100644 --- a/src/gpu/GrContext.cpp +++ b/src/gpu/GrContext.cpp @@ -352,16 +352,8 @@ GrTexture* GrContext::createResizedTexture(const GrTextureDesc& desc, GrTextureParams params(SkShader::kClamp_TileMode, needsFiltering); drawState->createTextureEffect(0, clampedTexture, SkMatrix::I(), params); - // 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); + static const GrVertexLayout layout = GrDrawState::StageTexCoordVertexLayoutBit(0); + drawState->setVertexLayout(layout); GrDrawTarget::AutoReleaseGeometry arg(fGpu, 4, 0); if (arg.succeeded()) { @@ -786,7 +778,7 @@ void GrContext::drawRect(const GrPaint& paint, // unitSquareVertexBuffer() static const int worstCaseVertCount = 10; - target->drawState()->setDefaultVertexAttribs(); + target->drawState()->setVertexLayout(GrDrawState::kDefault_VertexLayout); GrDrawTarget::AutoReleaseGeometry geo(target, worstCaseVertCount, 0); if (!geo.succeeded()) { @@ -829,7 +821,7 @@ void GrContext::drawRect(const GrPaint& paint, } GrDrawState* drawState = target->drawState(); - target->drawState()->setDefaultVertexAttribs(); + drawState->setVertexLayout(GrDrawState::kDefault_VertexLayout); target->setVertexSourceToBuffer(sqVB); SkMatrix m; m.setAll(rect.width(), 0, rect.fLeft, @@ -895,7 +887,7 @@ void GrContext::drawRectToRect(const GrPaint& paint, GrPrintf("Failed to create static rect vb.\n"); return; } - drawState->setDefaultVertexAttribs(); + drawState->setVertexLayout(GrDrawState::kDefault_VertexLayout); target->setVertexSourceToBuffer(sqVB); target->drawNonIndexed(kTriangleFan_GrPrimitiveType, 0, 4); #else @@ -920,55 +912,37 @@ void GrContext::drawVertices(const GrPaint& paint, GrDrawTarget* target = this->prepareToDraw(&paint, BUFFERED_DRAW); GrDrawState::AutoStageDisable atr(fDrawState); - 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 + GrVertexLayout layout = 0; if (NULL != texCoords) { - bindings |= GrDrawState::ExplicitTexCoordAttribBindingsBit(0); - drawState->setAttribIndex(GrDrawState::kTexCoord_AttribIndex, attribs.count()); - attribs.push_back(GrVertexAttrib(kVec2f_GrVertexAttribType, currentOffset)); - texOffset = currentOffset; - currentOffset += sizeof(GrPoint); + layout |= GrDrawState::StageTexCoordVertexLayoutBit(0); } - - // set up optional color attributes if (NULL != colors) { - bindings |= GrDrawState::kColor_AttribBindingsBit; - drawState->setAttribIndex(GrDrawState::kColor_AttribIndex, attribs.count()); - attribs.push_back(GrVertexAttrib(kVec4ub_GrVertexAttribType, currentOffset)); - colorOffset = currentOffset; - currentOffset += sizeof(GrColor); + layout |= GrDrawState::kColor_VertexLayoutBit; } + target->drawState()->setVertexLayout(layout); - drawState->setVertexAttribs(attribs.begin(), attribs.count()); - drawState->setAttribBindings(bindings); - - size_t vertexSize = drawState->getVertexSize(); - GrAssert(vertexSize == currentOffset); + int vertexSize = target->getDrawState().getVertexSize(); 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); @@ -1071,17 +1045,8 @@ void GrContext::internalDrawOval(const GrPaint& paint, return; } - // 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); + GrVertexLayout layout = GrDrawState::kEdge_VertexLayoutBit; + drawState->setVertexLayout(layout); GrAssert(sizeof(CircleVertex) == drawState->getVertexSize()); GrDrawTarget::AutoReleaseGeometry geo(target, 4, 0); diff --git a/src/gpu/GrDefaultPathRenderer.cpp b/src/gpu/GrDefaultPathRenderer.cpp index 7ca478e49..d5ebaaa60 100644 --- a/src/gpu/GrDefaultPathRenderer.cpp +++ b/src/gpu/GrDefaultPathRenderer.cpp @@ -211,6 +211,7 @@ bool GrDefaultPathRenderer::createGeom(const SkPath& path, return false; } + GrVertexLayout layout = 0; bool indexed = contourCnt > 1; const bool isHairline = stroke.isHairlineStyle(); @@ -232,7 +233,7 @@ bool GrDefaultPathRenderer::createGeom(const SkPath& path, } } - target->drawState()->setDefaultVertexAttribs(); + target->drawState()->setVertexLayout(layout); if (!arg->set(target, maxPts, maxIdxs)) { return false; } diff --git a/src/gpu/GrDrawState.cpp b/src/gpu/GrDrawState.cpp index 6b0091303..3925bd9a9 100644 --- a/src/gpu/GrDrawState.cpp +++ b/src/gpu/GrDrawState.cpp @@ -57,150 +57,270 @@ namespace { * they were just a series of immediate->memory moves.) * */ -void gen_tex_coord_mask(GrAttribBindings* texCoordMask) { +void gen_tex_coord_mask(GrVertexLayout* texCoordMask) { *texCoordMask = 0; for (int s = 0; s < GrDrawState::kNumStages; ++s) { - *texCoordMask |= GrDrawState::ExplicitTexCoordAttribBindingsBit(s); + *texCoordMask |= GrDrawState::StageTexCoordVertexLayoutBit(s); } } -const GrAttribBindings kTexCoord_AttribBindingsMask = (1 << GrDrawState::kNumStages)-1; +const GrVertexLayout kTexCoordMask = (1 << GrDrawState::kNumStages)-1; + +inline int num_tex_coords(GrVertexLayout layout) { + return (kTexCoordMask & layout) ? 1 : 0; +} } //unnamed namespace -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 const size_t kVec2Size = sizeof(GrPoint); -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 +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); } return size; } -size_t GrDrawState::getVertexSize() const { - return vertex_size(fVertexAttribs.begin(), fVertexAttribs.count()); -} - -const GrAttribBindings GrDrawState::kAttribIndexMasks[kAttribIndexCount] = { - 0, // position is not reflected in the bindings - kColor_AttribBindingsBit, - kCoverage_AttribBindingsBit, - kEdge_AttribBindingsBit, - kTexCoord_AttribBindingsMask -}; - //////////////////////////////////////////////////////////////////////////////// -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]); +/** + * 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; +} + +int GrDrawState::VertexColorOffset(GrVertexLayout vertexLayout) { + if (vertexLayout & kColor_VertexLayoutBit) { + return kVec2Size * (num_tex_coords(vertexLayout) + 1); //+1 for pos + } + return -1; +} + +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; + } + 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::VertexAttributesUnitTest() { +void GrDrawState::VertexLayoutUnitTest() { // Ensure that our tex coord mask is correct - GrAttribBindings texCoordMask; + GrVertexLayout texCoordMask; gen_tex_coord_mask(&texCoordMask); - GrAssert(texCoordMask == kTexCoord_AttribBindingsMask); + GrAssert(texCoordMask == kTexCoordMask); // not necessarily exhaustive static bool run; if (!run) { run = true; - - 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)); + GrVertexLayout tcMask = 0; + GrAssert(!VertexUsesTexCoords(0)); for (int s = 0; s < GrDrawState::kNumStages; ++s) { - tcMask |= ExplicitTexCoordAttribBindingsBit(s); - GrAssert(AttributesBindExplicitTexCoords(tcMask)); - GrAssert(StageBindsExplicitTexCoords(tcMask, s)); + tcMask |= StageTexCoordVertexLayoutBit(s); + GrAssert(sizeof(GrPoint) == VertexStageCoordOffset(s, tcMask)); + GrAssert(VertexUsesTexCoords(tcMask)); + GrAssert(2*sizeof(GrPoint) == VertexSize(tcMask)); + GrAssert(StageUsesTexCoords(tcMask, s)); for (int s2 = s + 1; s2 < GrDrawState::kNumStages; ++s2) { - GrAssert(!StageBindsExplicitTexCoords(tcMask, 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(-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::StageBindsExplicitTexCoords(GrAttribBindings bindings, int stageIdx) { - return SkToBool(bindings & ExplicitTexCoordAttribBindingsBit(stageIdx)); +bool GrDrawState::StageUsesTexCoords(GrVertexLayout layout, int stageIdx) { + return SkToBool(layout & StageTexCoordVertexLayoutBit(stageIdx)); } -bool GrDrawState::srcAlphaWillBeOne(GrAttribBindings bindings) const { +bool GrDrawState::srcAlphaWillBeOne(GrVertexLayout layout) const { uint32_t validComponentFlags; GrColor color; // Check if per-vertex or constant color may have partial alpha - if (bindings & kColor_AttribBindingsBit) { + if (layout & kColor_VertexLayoutBit) { validComponentFlags = 0; color = 0; // not strictly necessary but we get false alarms from tools about uninit. } else { @@ -246,7 +366,7 @@ bool GrDrawState::srcAlphaWillBeOne(GrAttribBindings bindings) const { return (GrEffect::kA_ValidComponentFlag & validComponentFlags) && 0xff == GrColorUnpackA(color); } -bool GrDrawState::hasSolidCoverage(GrAttribBindings bindings) const { +bool GrDrawState::hasSolidCoverage(GrVertexLayout layout) const { // If we're drawing coverage directly then coverage is effectively treated as color. if (this->isCoverageDrawing()) { return true; @@ -255,7 +375,7 @@ bool GrDrawState::hasSolidCoverage(GrAttribBindings bindings) const { GrColor coverage; uint32_t validComponentFlags; // Initialize to an unknown starting coverage if per-vertex coverage is specified. - if (bindings & kCoverage_AttribBindingsBit) { + if (layout & kCoverage_VertexLayoutBit) { validComponentFlags = 0; } else { coverage = fCommon.fCoverage; @@ -297,7 +417,7 @@ bool GrDrawState::canTweakAlphaForCoverage() const { GrDrawState::BlendOptFlags GrDrawState::getBlendOpts(bool forceCoverage, GrBlendCoeff* srcCoeff, GrBlendCoeff* dstCoeff) const { - GrAttribBindings bindings = this->getAttribBindings(); + GrVertexLayout layout = this->getVertexLayout(); GrBlendCoeff bogusSrcCoeff, bogusDstCoeff; if (NULL == srcCoeff) { @@ -315,14 +435,14 @@ GrDrawState::BlendOptFlags GrDrawState::getBlendOpts(bool forceCoverage, *dstCoeff = kOne_GrBlendCoeff; } - bool srcAIsOne = this->srcAlphaWillBeOne(bindings); + bool srcAIsOne = this->srcAlphaWillBeOne(layout); bool dstCoeffIsOne = kOne_GrBlendCoeff == *dstCoeff || (kSA_GrBlendCoeff == *dstCoeff && srcAIsOne); bool dstCoeffIsZero = kZero_GrBlendCoeff == *dstCoeff || (kISA_GrBlendCoeff == *dstCoeff && srcAIsOne); bool covIsZero = !this->isCoverageDrawing() && - !(bindings & GrDrawState::kCoverage_AttribBindingsBit) && + !(layout & GrDrawState::kCoverage_VertexLayoutBit) && 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 @@ -340,8 +460,8 @@ GrDrawState::BlendOptFlags GrDrawState::getBlendOpts(bool forceCoverage, // edge aa or coverage stage bool hasCoverage = forceCoverage || 0xffffffff != this->getCoverage() || - (bindings & GrDrawState::kCoverage_AttribBindingsBit) || - (bindings & GrDrawState::kEdge_AttribBindingsBit); + (layout & GrDrawState::kCoverage_VertexLayoutBit) || + (layout & GrDrawState::kEdge_VertexLayoutBit); for (int s = this->getFirstCoverageStage(); !hasCoverage && s < GrDrawState::kNumStages; ++s) { diff --git a/src/gpu/GrDrawState.h b/src/gpu/GrDrawState.h index 53c575d3a..05492a73a 100644 --- a/src/gpu/GrDrawState.h +++ b/src/gpu/GrDrawState.h @@ -23,41 +23,6 @@ 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 -class GrVertexAttribArray : public SkSTArray {}; - -/** - * Type used to describe how attributes bind to program usage - */ -typedef int GrAttribBindings; - class GrDrawState : public GrRefCnt { public: SK_DECLARE_INST_COUNT(GrDrawState) @@ -67,7 +32,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 - * GrAttribBindings used to draw. + * GrVertexLayout 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 @@ -75,7 +40,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 GrAttribBindings. The input to the first coverage stage is + * per-vertex colors, depending upon GrVertexLayout. 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). @@ -94,7 +59,7 @@ public: GrDrawState() { #if GR_DEBUG - VertexAttributesUnitTest(); + VertexLayoutUnitTest(); #endif this->reset(); } @@ -117,9 +82,8 @@ public: fRenderTarget.reset(NULL); - this->setDefaultVertexAttribs(); - fCommon.fColor = 0xffffffff; + fCommon.fVertexLayout = kDefault_VertexLayout; fCommon.fViewMatrix.reset(); fCommon.fSrcBlend = kOne_GrBlendCoeff; fCommon.fDstBlend = kZero_GrBlendCoeff; @@ -143,50 +107,193 @@ public: void setFromPaint(const GrPaint& paint); /////////////////////////////////////////////////////////////////////////// - /// @name Vertex Attributes + /// @name Vertex Layout //// - enum { - kVertexAttribCnt = 6, + /** + * 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 }; - /** - * 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). - * - * 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. - */ - /** - * Sets vertex attributes for next draw. + * Sets vertex layout for next draw. * - * @param attribs the array of vertex attributes to set. - * @param count the number of attributes being set. - * limited to a count of kVertexAttribCnt. + * @param layout the vertex layout to set. */ - void setVertexAttribs(const GrVertexAttrib attribs[], int count); + void setVertexLayout(GrVertexLayout layout) { fCommon.fVertexLayout = layout; } - const GrVertexAttrib* getVertexAttribs() const { return fVertexAttribs.begin(); } - int getVertexAttribCount() const { return fVertexAttribs.count(); } + GrVertexLayout getVertexLayout() const { return fCommon.fVertexLayout; } + size_t getVertexSize() const { return VertexSize(fCommon.fVertexLayout); } - size_t getVertexSize() const; - - /** - * Sets default vertex attributes for next draw. - * - * This will also set default vertex attribute indices and bindings - */ - void setDefaultVertexAttribs(); //////////////////////////////////////////////////////////////////////////// - // Helpers for picking apart vertex attributes + // Helpers for picking apart vertex layouts - // helper array to let us check the expected so we know what bound attrib indices - // we care about - static const size_t kVertexAttribSizes[kGrVertexAttribTypeCount]; + /** + * 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 + * + * @return true if vertex specifies texture coordinates, + * false otherwise. + */ + static bool VertexUsesTexCoords(GrVertexLayout vertexLayout); + + /** + * 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); + + /** + * 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). + * + * @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 + */ + static int VertexSizeAndOffsetsByStage(GrVertexLayout vertexLayout, + int texCoordOffsetsByStage[kNumStages], + int* colorOffset, + int* coverageOffset, + int* edgeOffset); + + /** + * Determines whether src alpha is guaranteed to be one for all src pixels + */ + bool srcAlphaWillBeOne(GrVertexLayout) const; + + /** + * Determines whether the output coverage is guaranteed to be one for all pixels hit by a draw. + */ + bool hasSolidCoverage(GrVertexLayout) const; /** * Accessing positions, texture coords, or colors, of a vertex within an @@ -197,7 +304,7 @@ public: /** * Gets a pointer to a GrPoint of a vertex's position or texture * coordinate. - * @param vertices the vertex array + * @param vertices the vetex 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. @@ -246,140 +353,7 @@ public: vertexIndex * vertexSize); } - /// @} - - /////////////////////////////////////////////////////////////////////////// - /// @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]; } + static void VertexLayoutUnitTest(); /// @} @@ -1030,7 +1004,7 @@ public: /** * Determines the interpretation per-vertex edge data when the - * kEdge_AttribBindingsBit is set (see GrDrawTarget). When per-vertex edges + * kEdge_VertexLayoutBit is set (see GrDrawTarget). When per-vertex edges * are not specified the value of this setting has no effect. */ void setVertexEdgeType(VertexEdgeType type) { @@ -1185,25 +1159,13 @@ 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)) { @@ -1220,10 +1182,6 @@ 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]; @@ -1238,7 +1196,7 @@ private: struct CommonState { // These fields are roughly sorted by decreasing likelihood of being different in op== GrColor fColor; - GrAttribBindings fAttribBindings; + GrVertexLayout fVertexLayout; SkMatrix fViewMatrix; GrBlendCoeff fSrcBlend; GrBlendCoeff fDstBlend; @@ -1253,7 +1211,7 @@ private: DrawFace fDrawFace; bool operator== (const CommonState& other) const { return fColor == other.fColor && - fAttribBindings == other.fAttribBindings && + fVertexLayout == other.fVertexLayout && fViewMatrix.cheapEqualTo(other.fViewMatrix) && fSrcBlend == other.fSrcBlend && fDstBlend == other.fDstBlend && @@ -1298,10 +1256,6 @@ 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). @@ -1315,10 +1269,6 @@ 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]); } @@ -1328,20 +1278,6 @@ 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; @@ -1351,25 +1287,17 @@ public: } private: - GrRenderTarget* fRenderTarget; - CommonState fCommon; - int fAttribIndices[kAttribIndexCount]; - GrVertexAttribArray fVertexAttribs; - GrEffectStage::DeferredStage fStages[kNumStages]; + GrRenderTarget* fRenderTarget; + CommonState fCommon; + GrEffectStage::DeferredStage fStages[kNumStages]; GR_DEBUGCODE(bool fInitialized;) }; private: - // 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 fRenderTarget; - CommonState fCommon; - int fAttribIndices[kAttribIndexCount]; - GrVertexAttribArray fVertexAttribs; - GrEffectStage fStages[kNumStages]; + SkAutoTUnref fRenderTarget; + CommonState fCommon; + GrEffectStage fStages[kNumStages]; typedef GrRefCnt INHERITED; }; diff --git a/src/gpu/GrDrawTarget.cpp b/src/gpu/GrDrawTarget.cpp index dab2965c6..2c2d94922 100644 --- a/src/gpu/GrDrawTarget.cpp +++ b/src/gpu/GrDrawTarget.cpp @@ -530,19 +530,11 @@ void GrDrawTarget::drawRect(const GrRect& rect, const GrRect* srcRect, const SkMatrix* srcMatrix, int stage) { - GrAttribBindings bindings = 0; + GrVertexLayout layout = 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) { - bindings |= GrDrawState::ExplicitTexCoordAttribBindingsBit(stage); - attribCount = 2; - this->drawState()->setAttribIndex(GrDrawState::kTexCoord_AttribIndex, 1); + layout |= GrDrawState::StageTexCoordVertexLayoutBit(stage); explicitCoordMask = (1 << stage); } @@ -551,26 +543,30 @@ void GrDrawTarget::drawRect(const GrRect& rect, avmr.set(this->drawState(), *matrix, explicitCoordMask); } - this->drawState()->setVertexAttribs(kAttribs, attribCount); - this->drawState()->setAttribIndex(GrDrawState::kPosition_AttribIndex, 0); - this->drawState()->setAttribBindings(bindings); + this->drawState()->setVertexLayout(layout); AutoReleaseGeometry geo(this, 4, 0); if (!geo.succeeded()) { GrPrintf("Failed to get space for vertices!\n"); return; } - size_t vsize = this->drawState()->getVertexSize(); + int stageOffsets[GrDrawState::kNumStages]; + int vsize = GrDrawState::VertexSizeAndOffsetsByStage(layout, stageOffsets, NULL, NULL, NULL); geo.positions()->setRectFan(rect.fLeft, rect.fTop, rect.fRight, rect.fBottom, vsize); - if (NULL != srcRect) { - GrAssert(attribCount == 2); - GrPoint* coords = GrTCast(GrTCast(geo.vertices()) + - kAttribs[1].fOffset); - coords->setRectFan(srcRect->fLeft, srcRect->fTop, - srcRect->fRight, srcRect->fBottom, - vsize); - if (NULL != srcMatrix) { - srcMatrix->mapPointsWithStride(coords, vsize, 4); + + for (int i = 0; i < GrDrawState::kNumStages; ++i) { + if (explicitCoordMask & (1 << i)) { + GrAssert(0 != stageOffsets[i]); + GrPoint* coords = GrTCast(GrTCast(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]); } } diff --git a/src/gpu/GrInOrderDrawBuffer.cpp b/src/gpu/GrInOrderDrawBuffer.cpp index b2705a4b9..00aaadbe9 100644 --- a/src/gpu/GrInOrderDrawBuffer.cpp +++ b/src/gpu/GrInOrderDrawBuffer.cpp @@ -78,20 +78,9 @@ void GrInOrderDrawBuffer::drawRect(const GrRect& rect, const SkMatrix* srcMatrix, int stage) { - GrAttribBindings bindings = GrDrawState::kDefault_AttribBindings; + GrVertexLayout layout = 0; GrDrawState::AutoColorRestore acr; - - 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); + GrColor color = this->drawState()->getColor(); // 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 @@ -100,31 +89,22 @@ 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() || - 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); + this->getDrawState().hasSolidCoverage(this->getDrawState().getVertexLayout())) { + layout |= GrDrawState::kColor_VertexLayoutBit;; // 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(drawState, 0xFFFFFFFF); + acr.set(this->drawState(), 0xFFFFFFFF); } uint32_t explicitCoordMask = 0; if (NULL != srcRect) { - bindings |= GrDrawState::ExplicitTexCoordAttribBindingsBit(stage); - drawState->setAttribIndex(GrDrawState::kTexCoord_AttribIndex, attribs.count()); - attribs.push_back(GrVertexAttrib(kVec2f_GrVertexAttribType, currentOffset)); - texOffset = currentOffset; - currentOffset += sizeof(GrPoint); + layout |= GrDrawState::StageTexCoordVertexLayoutBit(stage); explicitCoordMask = (1 << stage); } - drawState->setVertexAttribs(attribs.begin(), attribs.count()); - drawState->setAttribBindings(bindings); + this->drawState()->setVertexLayout(layout); AutoReleaseGeometry geo(this, 4, 0); if (!geo.succeeded()) { GrPrintf("Failed to get space for vertices!\n"); @@ -138,17 +118,18 @@ void GrInOrderDrawBuffer::drawRect(const GrRect& rect, } else { combinedMatrix.reset(); } - combinedMatrix.postConcat(drawState->getViewMatrix()); + combinedMatrix.postConcat(this->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(drawState, explicitCoordMask); + GrDrawState::AutoDeviceCoordDraw adcd(this->drawState(), explicitCoordMask); if (!adcd.succeeded()) { return; } - size_t vsize = drawState->getVertexSize(); - GrAssert(vsize == currentOffset); + int stageOffsets[GrDrawState::kNumStages], colorOffset; + int vsize = GrDrawState::VertexSizeAndOffsetsByStage(layout, stageOffsets, + &colorOffset, NULL, NULL); geo.positions()->setRectFan(rect.fLeft, rect.fTop, rect.fRight, rect.fBottom, vsize); combinedMatrix.mapPointsWithStride(geo.positions(), vsize, 4); @@ -158,15 +139,19 @@ void GrInOrderDrawBuffer::drawRect(const GrRect& rect, // unnecessary clipping in our onDraw(). get_vertex_bounds(geo.vertices(), vsize, 4, &devBounds); - if (texOffset >= 0) { - GrAssert(explicitCoordMask != 0); - GrPoint* coords = GrTCast(GrTCast(geo.vertices()) + - texOffset); - coords->setRectFan(srcRect->fLeft, srcRect->fTop, - srcRect->fRight, srcRect->fBottom, - vsize); - if (NULL != srcMatrix) { - srcMatrix->mapPointsWithStride(coords, vsize, 4); + for (int i = 0; i < GrDrawState::kNumStages; ++i) { + if (explicitCoordMask & (1 << i)) { + GrAssert(0 != stageOffsets[i]); + GrPoint* coords = GrTCast(GrTCast(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]); } } @@ -180,9 +165,6 @@ 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 e77bf9342..e599fc950 100644 --- a/src/gpu/GrTextContext.cpp +++ b/src/gpu/GrTextContext.cpp @@ -92,6 +92,8 @@ GrTextContext::GrTextContext(GrContext* context, const GrPaint& paint) : fPaint( fVertices = NULL; fMaxVertices = 0; + + fVertexLayout = GrDrawState::StageTexCoordVertexLayoutBit(kGlyphMaskStage); } GrTextContext::~GrTextContext() { @@ -187,20 +189,13 @@ HAS_ATLAS: } if (NULL == fVertices) { - // 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 + // 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()->setVertexAttribs(kVertexAttribs, SK_ARRAY_COUNT(kVertexAttribs)); + fDrawTarget->drawState()->setVertexLayout(fVertexLayout); flush = fDrawTarget->geometryHints(&fMaxVertices, NULL); } if (flush) { @@ -208,11 +203,8 @@ HAS_ATLAS: fContext->flush(); // flushGlyphs() will reset fDrawTarget to NULL. fDrawTarget = fContext->getTextTarget(fPaint); - fDrawTarget->drawState()->setVertexAttribs(kVertexAttribs, SK_ARRAY_COUNT(kVertexAttribs)); + fDrawTarget->drawState()->setVertexLayout(fVertexLayout); } - 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); @@ -230,7 +222,6 @@ HAS_ATLAS: GrTCast(&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 781e15fdd..0ca84bc50 100644 --- a/src/gpu/gl/GrGLProgram.cpp +++ b/src/gpu/gl/GrGLProgram.cpp @@ -35,14 +35,6 @@ 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, @@ -60,24 +52,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 attribute - // bindings in use or other descriptor field settings) it should be set + // descriptor will not affect program generation (because of the vertex + // layout 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->fAttribBindings = drawState.getAttribBindings(); + desc->fVertexLayout = drawState.getVertexLayout(); desc->fEmitsPointSize = isPoints; bool requiresAttributeColors = !skipColor && - SkToBool(desc->fAttribBindings & GrDrawState::kColor_AttribBindingsBit); + SkToBool(desc->fVertexLayout & GrDrawState::kColor_VertexLayoutBit); bool requiresAttributeCoverage = !skipCoverage && - SkToBool(desc->fAttribBindings & GrDrawState::kCoverage_AttribBindingsBit); + SkToBool(desc->fVertexLayout & GrDrawState::kCoverage_VertexLayoutBit); // fColorInput/fCoverageInput records how colors are specified for the program So we strip the - // bits from the bindings to avoid false negatives when searching for an existing program in the + // bits from the layout to avoid false negatives when searching for an existing program in the // cache. - desc->fAttribBindings &= ~(GrDrawState::kColor_AttribBindingsBit | GrDrawState::kCoverage_AttribBindingsBit); + desc->fVertexLayout &= ~(GrDrawState::kColor_VertexLayoutBit | GrDrawState::kCoverage_VertexLayoutBit); desc->fColorFilterXfermode = skipColor ? SkXfermode::kDst_Mode : @@ -85,8 +77,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->fAttribBindings &= ~(GrDrawState::kEdge_AttribBindingsBit | - GrDrawState::kCoverage_AttribBindingsBit); + desc->fVertexLayout &= ~(GrDrawState::kEdge_VertexLayoutBit | + GrDrawState::kCoverage_VertexLayoutBit); } bool colorIsTransBlack = SkToBool(blendOpts & GrDrawState::kEmitTransBlack_BlendOptFlag); @@ -116,7 +108,7 @@ void GrGLProgram::BuildDesc(const GrDrawState& drawState, int lastEnabledStage = -1; - if (!skipCoverage && (desc->fAttribBindings & GrDrawState::kEdge_AttribBindingsBit)) { + if (!skipCoverage && (desc->fVertexLayout & GrDrawState::kEdge_VertexLayoutBit)) { desc->fVertexEdgeType = drawState.getVertexEdgeType(); desc->fDiscardIfOutsideEdge = drawState.getStencil().doesWrite(); } else { @@ -163,7 +155,7 @@ void GrGLProgram::BuildDesc(const GrDrawState& drawState, // other coverage inputs if (!hasCoverage) { hasCoverage = requiresAttributeCoverage || - (desc->fAttribBindings & GrDrawState::kEdge_AttribBindingsBit); + (desc->fVertexLayout & GrDrawState::kEdge_VertexLayoutBit); } if (hasCoverage) { @@ -190,43 +182,6 @@ 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, @@ -411,7 +366,7 @@ void add_color_filter(SkString* fsCode, const char * outputVar, bool GrGLProgram::genEdgeCoverage(SkString* coverageVar, GrGLShaderBuilder* builder) const { - if (fDesc.fAttribBindings & GrDrawState::kEdge_AttribBindingsBit) { + if (fDesc.fVertexLayout & GrDrawState::kEdge_VertexLayoutBit) { const char *vsName, *fsName; builder->addVarying(kVec4f_GrSLType, "Edge", &vsName, &fsName); builder->fVSAttrs.push_back().set(kVec4f_GrSLType, @@ -690,7 +645,7 @@ bool GrGLProgram::genProgram(const GrEffectStage* stages[]) { GrAssert(0 == fProgramID); GrGLShaderBuilder builder(fContext.info(), fUniformManager); - const GrAttribBindings& attribBindings = fDesc.fAttribBindings; + const uint32_t& layout = fDesc.fVertexLayout; #if GR_GL_EXPERIMENTAL_GS builder.fUsesGS = fDesc.fExperimentalGS; @@ -771,7 +726,7 @@ bool GrGLProgram::genProgram(const GrEffectStage* stages[]) { } // add texture coordinates that are used to the list of vertex attr decls - if (GrDrawState::AttributesBindExplicitTexCoords(attribBindings)) { + if (GrDrawState::VertexUsesTexCoords(layout)) { builder.fVSAttrs.push_back().set(kVec2f_GrSLType, GrGLShaderVar::kAttribute_TypeModifier, TEX_ATTR_NAME); @@ -793,7 +748,7 @@ bool GrGLProgram::genProgram(const GrEffectStage* stages[]) { const char* inCoords; // figure out what our input coords are - if (!GrDrawState::StageBindsExplicitTexCoords(attribBindings, s)) { + if (!GrDrawState::StageUsesTexCoords(layout, s)) { inCoords = builder.positionAttribute().c_str(); } else { // must have input tex coordinates if stage is enabled. @@ -887,7 +842,7 @@ bool GrGLProgram::genProgram(const GrEffectStage* stages[]) { const char* inCoords; // figure out what our input coords are - if (!GrDrawState::StageBindsExplicitTexCoords(attribBindings, s)) { + if (!GrDrawState::StageUsesTexCoords(layout, s)) { inCoords = builder.positionAttribute().c_str(); } else { // must have input tex coordinates if stage is @@ -1011,18 +966,13 @@ bool GrGLProgram::bindOutputsAttribsAndLinkProgram(const GrGLShaderBuilder& buil // Bind the attrib locations to same values for all shaders GL_CALL(BindAttribLocation(fProgramID, - fDesc.fPositionAttributeIndex, + kPositionAttributeIndex, builder.positionAttribute().c_str())); - 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(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(LinkProgram(fProgramID)); GrGLint linked = GR_GL_INIT_ZERO; @@ -1110,14 +1060,14 @@ void GrGLProgram::setData(GrGpuGL* gpu, void GrGLProgram::setColor(const GrDrawState& drawState, GrColor color, SharedGLState* sharedState) { - if (!(drawState.getAttribBindings() & GrDrawState::kColor_AttribBindingsBit)) { + if (!(drawState.getVertexLayout() & GrDrawState::kColor_VertexLayoutBit)) { 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(fDesc.fColorAttributeIndex, c)); + GL_CALL(VertexAttrib4fv(kColorAttributeIndex, c)); sharedState->fConstAttribColor = color; } break; @@ -1144,14 +1094,14 @@ void GrGLProgram::setColor(const GrDrawState& drawState, void GrGLProgram::setCoverage(const GrDrawState& drawState, GrColor coverage, SharedGLState* sharedState) { - if (!(drawState.getAttribBindings() & GrDrawState::kCoverage_AttribBindingsBit)) { + if (!(drawState.getVertexLayout() & GrDrawState::kCoverage_VertexLayoutBit)) { 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(fDesc.fCoverageAttributeIndex, c)); + GL_CALL(VertexAttrib4fv(kCoverageAttributeIndex, c)); sharedState->fConstAttribCoverage = coverage; } break; diff --git a/src/gpu/gl/GrGLProgram.h b/src/gpu/gl/GrGLProgram.h index cde918b54..a2958e736 100644 --- a/src/gpu/gl/GrGLProgram.h +++ b/src/gpu/gl/GrGLProgram.h @@ -78,6 +78,17 @@ 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 @@ -171,7 +182,7 @@ public: bool fDiscardIfOutsideEdge; // stripped of bits that don't affect program generation - GrAttribBindings fAttribBindings; + GrVertexLayout fVertexLayout; /** Non-zero if this stage has an effect */ GrGLEffect::EffectKey fEffectKeys[GrDrawState::kNumStages]; @@ -188,23 +199,9 @@ 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 42e83b043..f9c94c4f7 100644 --- a/src/gpu/gl/GrGpuGL.cpp +++ b/src/gpu/gl/GrGpuGL.cpp @@ -182,10 +182,6 @@ 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 e5a71831e..93af1b919 100644 --- a/src/gpu/gl/GrGpuGL_program.cpp +++ b/src/gpu/gl/GrGpuGL_program.cpp @@ -215,30 +215,83 @@ bool GrGpuGL::flushGraphicsState(DrawType type) { void GrGpuGL::setupGeometry(const DrawInfo& info, size_t* indexOffsetInBytes) { - GrGLsizei stride = this->getDrawState().getVertexSize(); + int colorOffset; + int coverageOffset; + int texCoordOffset; + int edgeOffset; + + GrVertexLayout currLayout = this->getDrawState().getVertexLayout(); + + GrGLsizei stride = GrDrawState::VertexSizeAndOffsets(currLayout, + &texCoordOffset, + &colorOffset, + &coverageOffset, + &edgeOffset); size_t vertexOffset; GrGLVertexBuffer* vb= this->setBuffers(info.isIndexed(), &vertexOffset, indexOffsetInBytes); vertexOffset += stride * info.startVertex(); - uint32_t usedAttribArraysMask = 0; - const GrVertexAttrib* vertexAttrib = this->getDrawState().getVertexAttribs(); - int vertexAttribCount = this->getDrawState().getVertexAttribCount(); - for (int vertexAttribIndex = 0; vertexAttribIndex < vertexAttribCount; - ++vertexAttribIndex, ++vertexAttrib) { - - usedAttribArraysMask |= (1 << vertexAttribIndex); - GrVertexAttribType attribType = vertexAttrib->fType; + uint32_t usedAttribArraysMask = (1 << GrGLProgram::kPositionAttributeIndex); + fHWGeometryState.setAttribArray(this, + GrGLProgram::kPositionAttributeIndex, + vb, + 2, + GR_GL_FLOAT, + false, + stride, + reinterpret_cast(vertexOffset)); + if (texCoordOffset > 0) { + usedAttribArraysMask |= (1 << GrGLProgram::kTexCoordAttributeIndex); + GrGLvoid* texCoordPtr = reinterpret_cast(vertexOffset + texCoordOffset); fHWGeometryState.setAttribArray(this, - vertexAttribIndex, + GrGLProgram::kTexCoordAttributeIndex, vb, - GrGLProgram::kAttribLayouts[attribType].fCount, - GrGLProgram::kAttribLayouts[attribType].fType, - GrGLProgram::kAttribLayouts[attribType].fNormalized, + 2, + GR_GL_FLOAT, + false, stride, - reinterpret_cast( - vertexOffset + vertexAttrib->fOffset)); - } + texCoordPtr); + } + + if (colorOffset > 0) { + usedAttribArraysMask |= (1 << GrGLProgram::kColorAttributeIndex); + GrGLvoid* colorPtr = reinterpret_cast(vertexOffset + colorOffset); + fHWGeometryState.setAttribArray(this, + GrGLProgram::kColorAttributeIndex, + vb, + 4, + GR_GL_UNSIGNED_BYTE, + true, + stride, + colorPtr); + } + + if (coverageOffset > 0) { + usedAttribArraysMask |= (1 << GrGLProgram::kCoverageAttributeIndex); + GrGLvoid* coveragePtr = reinterpret_cast(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(vertexOffset + edgeOffset); + fHWGeometryState.setAttribArray(this, + GrGLProgram::kEdgeAttributeIndex, + vb, + 4, + GR_GL_FLOAT, + false, + stride, + edgePtr); + } fHWGeometryState.disableUnusedAttribArrays(this, usedAttribArraysMask); } diff --git a/src/gpu/gr_unittests.cpp b/src/gpu/gr_unittests.cpp index c7daf7718..7f5c7e9cf 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::UnitTest(); - GrDrawState::VertexAttributesUnitTest(); + GrDrawState::VertexLayoutUnitTest(); } diff --git a/tests/GLProgramsTest.cpp b/tests/GLProgramsTest.cpp index 45c5f2d16..bc148f175 100644 --- a/tests/GLProgramsTest.cpp +++ b/tests/GLProgramsTest.cpp @@ -23,7 +23,7 @@ void GrGLProgram::Desc::setRandom(SkMWCRandom* random, const GrGpuGL* gpu, const GrEffectStage stages[GrDrawState::kNumStages]) { - fAttribBindings = 0; + fVertexLayout = 0; fEmitsPointSize = random->nextBool(); fColorInput = random->nextULessThan(kColorInputCnt); fCoverageInput = random->nextULessThan(kColorInputCnt); @@ -32,7 +32,7 @@ void GrGLProgram::Desc::setRandom(SkMWCRandom* random, fFirstCoverageStage = random->nextULessThan(GrDrawState::kNumStages); - fAttribBindings |= random->nextBool() ? GrDrawState::kCoverage_AttribBindingsBit : 0; + fVertexLayout |= random->nextBool() ? GrDrawState::kCoverage_VertexLayoutBit : 0; #if GR_GL_EXPERIMENTAL_GS fExperimentalGS = gpu->getCaps().geometryShaderSupport() && random->nextBool(); @@ -40,7 +40,7 @@ void GrGLProgram::Desc::setRandom(SkMWCRandom* random, bool edgeAA = random->nextBool(); if (edgeAA) { - fAttribBindings |= GrDrawState::kEdge_AttribBindingsBit; + fVertexLayout |= GrDrawState::kEdge_VertexLayoutBit; if (gpu->getCaps().shaderDerivativeSupport()) { fVertexEdgeType = (GrDrawState::VertexEdgeType) random->nextULessThan(GrDrawState::kVertexEdgeTypeCnt); @@ -64,31 +64,11 @@ void GrGLProgram::Desc::setRandom(SkMWCRandom* random, fEffectKeys[s] = factory.glEffectKey(stages[s], gpu->glCaps()); // use separate tex coords? if (!useOnce && random->nextBool()) { - fAttribBindings |= GrDrawState::ExplicitTexCoordAttribBindingsBit(s); + fVertexLayout |= GrDrawState::StageTexCoordVertexLayoutBit(s); useOnce = true; } } } - - int attributeIndex = 0; - fPositionAttributeIndex = attributeIndex; - ++attributeIndex; - if (fColorInput || (fAttribBindings & GrDrawState::kColor_AttribBindingsBit)) { - fColorAttributeIndex = attributeIndex; - ++attributeIndex; - } - if (fCoverageInput || (fAttribBindings & GrDrawState::kCoverage_AttribBindingsBit)) { - fCoverageAttributeIndex = attributeIndex; - ++attributeIndex; - } - if (fAttribBindings & GrDrawState::kEdge_AttribBindingsBit) { - fEdgeAttributeIndex = attributeIndex; - ++attributeIndex; - } - if (GrDrawState::AttributesBindExplicitTexCoords(fAttribBindings)) { - fTexCoordAttributeIndex = attributeIndex; - ++attributeIndex; - } } bool GrGpuGL::programUnitTest(int maxStages) {