aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/gpu
diff options
context:
space:
mode:
authorGravatar jvanverth@google.com <jvanverth@google.com@2bbb7eff-a529-9590-31e7-b0007b416f81>2013-03-01 18:21:22 +0000
committerGravatar jvanverth@google.com <jvanverth@google.com@2bbb7eff-a529-9590-31e7-b0007b416f81>2013-03-01 18:21:22 +0000
commit9b855c7c95ce9fff7a447e4a6bdf8a469c1f3097 (patch)
treea97672e09387e62ddec1deca227f024806820222 /src/gpu
parentdf8114d84616f8a85a5064f8deef2cca083193f8 (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.cpp16
-rw-r--r--src/gpu/GrAAHairLinePathRenderer.cpp20
-rw-r--r--src/gpu/GrAARectRenderer.cpp46
-rw-r--r--src/gpu/GrContext.cpp77
-rw-r--r--src/gpu/GrDefaultPathRenderer.cpp3
-rw-r--r--src/gpu/GrDrawState.cpp322
-rw-r--r--src/gpu/GrDrawState.h448
-rw-r--r--src/gpu/GrDrawTarget.cpp42
-rw-r--r--src/gpu/GrInOrderDrawBuffer.cpp68
-rw-r--r--src/gpu/GrTextContext.cpp19
-rw-r--r--src/gpu/gl/GrGLProgram.cpp102
-rw-r--r--src/gpu/gl/GrGLProgram.h27
-rw-r--r--src/gpu/gl/GrGpuGL.cpp4
-rw-r--r--src/gpu/gl/GrGpuGL_program.cpp83
-rw-r--r--src/gpu/gr_unittests.cpp2
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();
}