Add new vertex attribute array specification.
This changes the old method of setting vertex layout to a new one where we specify vertex attribute data separately from attribute bindings (i.e. program functionality). Attribute data is now set up via an array of generic attribute types and offsets, and this is mapped to the old program functionality by setting specific attribute indices. This allows us to create more general inputs to shaders. git-svn-id: http://skia.googlecode.com/svn/trunk@7899 2bbb7eff-a529-9590-31e7-b0007b416f81
This commit is contained in:
parent
4aaaaeace7
commit
b8b705b1b9
@ -36,12 +36,25 @@ bool GrAndroidPathRenderer::onDrawPath(const SkPath& origPath,
|
||||
android::uirenderer::PathRenderer::ConvexPathVertices(origPath, stroke, antiAlias, NULL,
|
||||
&vertices);
|
||||
|
||||
// set vertex layout depending on anti-alias
|
||||
GrVertexLayout layout = antiAlias ? GrDrawState::kCoverage_VertexLayoutBit : 0;
|
||||
// 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();
|
||||
}
|
||||
|
||||
// allocate our vert buffer
|
||||
int vertCount = vertices.getSize();
|
||||
GrDrawTarget::AutoReleaseGeometry geo(target, layout, vertCount, 0);
|
||||
GrDrawTarget::AutoReleaseGeometry geo(target, vertCount, 0);
|
||||
if (!geo.succeeded()) {
|
||||
GrPrintf("Failed to get space for vertices!\n");
|
||||
return false;
|
||||
@ -49,6 +62,7 @@ bool GrAndroidPathRenderer::onDrawPath(const SkPath& origPath,
|
||||
|
||||
// copy android verts to our vertex buffer
|
||||
if (antiAlias) {
|
||||
GrAssert(sizeof(ColorVertex) == drawState->getVertexSize());
|
||||
ColorVertex* outVert = reinterpret_cast<ColorVertex*>(geo.vertices());
|
||||
android::uirenderer::AlphaVertex* inVert =
|
||||
reinterpret_cast<android::uirenderer::AlphaVertex*>(vertices.getBuffer());
|
||||
@ -63,7 +77,7 @@ bool GrAndroidPathRenderer::onDrawPath(const SkPath& origPath,
|
||||
++inVert;
|
||||
}
|
||||
} else {
|
||||
size_t vsize = GrDrawState::VertexSize(layout);
|
||||
size_t vsize = drawState->getVertexSize();
|
||||
size_t copySize = vsize*vertCount;
|
||||
memcpy(geo.vertices(), vertices.getBuffer(), copySize);
|
||||
}
|
||||
|
@ -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
|
||||
GrDrawTarget::AutoReleaseGeometry arg(target, layout, maxVertexCount, maxIndexCount);
|
||||
target->drawState()->setDefaultVertexAttribs();
|
||||
GrDrawTarget::AutoReleaseGeometry arg(target, 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.5);
|
||||
const SkScalar radius = SkScalarMul(width, 0.5f);
|
||||
SkPoint *firstPt = verts, *lastPt = NULL;
|
||||
SkVector firstDir, dir;
|
||||
firstDir.set(0, 0);
|
||||
|
@ -223,7 +223,20 @@ 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) {
|
||||
|
@ -32,7 +32,6 @@ public:
|
||||
|
||||
private:
|
||||
GrPaint fPaint;
|
||||
GrVertexLayout fVertexLayout;
|
||||
GrContext* fContext;
|
||||
GrDrawTarget* fDrawTarget;
|
||||
|
||||
|
@ -194,12 +194,6 @@ 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.
|
||||
*/
|
||||
|
@ -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());
|
||||
|
||||
|
@ -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)) {
|
||||
|
@ -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.
|
||||
|
@ -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;
|
||||
if (NULL != texCoords) {
|
||||
layout |= GrDrawState::StageTexCoordVertexLayoutBit(0);
|
||||
}
|
||||
if (NULL != colors) {
|
||||
layout |= GrDrawState::kColor_VertexLayoutBit;
|
||||
}
|
||||
target->drawState()->setVertexLayout(layout);
|
||||
GrDrawState* drawState = target->drawState();
|
||||
|
||||
int vertexSize = target->getDrawState().getVertexSize();
|
||||
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) {
|
||||
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) {
|
||||
bindings |= GrDrawState::kColor_AttribBindingsBit;
|
||||
drawState->setAttribIndex(GrDrawState::kColor_AttribIndex, attribs.count());
|
||||
attribs.push_back(GrVertexAttrib(kVec4ub_GrVertexAttribType, currentOffset));
|
||||
colorOffset = currentOffset;
|
||||
currentOffset += sizeof(GrPoint);
|
||||
}
|
||||
|
||||
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);
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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);
|
||||
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
|
||||
};
|
||||
|
||||
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);
|
||||
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;
|
||||
}
|
||||
|
||||
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
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
/**
|
||||
* 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;
|
||||
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 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;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
bool GrDrawState::VertexUsesTexCoords(GrVertexLayout vertexLayout) {
|
||||
return SkToBool(kTexCoordMask & vertexLayout);
|
||||
void GrDrawState::setDefaultVertexAttribs() {
|
||||
fVertexAttribs.reset();
|
||||
fVertexAttribs.push_back(GrVertexAttrib(kVec2f_GrVertexAttribType, 0));
|
||||
|
||||
fCommon.fAttribBindings = kDefault_AttribBindings;
|
||||
|
||||
fAttribIndices[kPosition_AttribIndex] = 0;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void GrDrawState::VertexLayoutUnitTest() {
|
||||
bool GrDrawState::AttributesBindExplicitTexCoords(GrAttribBindings attribBindings) {
|
||||
return SkToBool(kTexCoord_AttribBindingsMask & attribBindings);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
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) {
|
||||
|
@ -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); }
|
||||
/**
|
||||
* Sets vertex attributes 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.
|
||||
*/
|
||||
void setVertexAttribs(const GrVertexAttrib attribs[], int count);
|
||||
|
||||
const GrVertexAttrib* getVertexAttribs() const { return fVertexAttribs.begin(); }
|
||||
int getVertexAttribCount() const { return fVertexAttribs.count(); }
|
||||
|
||||
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 layouts
|
||||
// Helpers for picking apart vertex attributes
|
||||
|
||||
/**
|
||||
* 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;
|
||||
// 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;
|
||||
};
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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) {
|
||||
|
@ -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);
|
||||
|
@ -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 GrGLContextInfo& 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(fContextInfo, 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;
|
||||
|
@ -78,17 +78,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
|
||||
@ -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 GrGLContextInfo& gl,
|
||||
const Desc& desc,
|
||||
|
@ -182,6 +182,10 @@ GrGpuGL::GrGpuGL(const GrGLContextInfo& ctxInfo, 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);
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -75,5 +75,5 @@ void gr_run_unittests() {
|
||||
test_bsearch();
|
||||
test_binHashKey();
|
||||
GrRedBlackTree<int>::UnitTest();
|
||||
GrDrawState::VertexLayoutUnitTest();
|
||||
GrDrawState::VertexAttributesUnitTest();
|
||||
}
|
||||
|
@ -23,7 +23,7 @@
|
||||
void GrGLProgram::Desc::setRandom(SkMWCRandom* random,
|
||||
const GrGpuGL* gpu,
|
||||
const GrEffectStage stages[GrDrawState::kNumStages]) {
|
||||
fVertexLayout = 0;
|
||||
fAttribBindings = 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);
|
||||
|
||||
fVertexLayout |= random->nextBool() ? GrDrawState::kCoverage_VertexLayoutBit : 0;
|
||||
fAttribBindings |= random->nextBool() ? GrDrawState::kCoverage_AttribBindingsBit : 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) {
|
||||
fVertexLayout |= GrDrawState::kEdge_VertexLayoutBit;
|
||||
fAttribBindings |= GrDrawState::kEdge_AttribBindingsBit;
|
||||
if (gpu->getCaps().shaderDerivativeSupport()) {
|
||||
fVertexEdgeType = (GrDrawState::VertexEdgeType)
|
||||
random->nextULessThan(GrDrawState::kVertexEdgeTypeCnt);
|
||||
@ -64,11 +64,31 @@ void GrGLProgram::Desc::setRandom(SkMWCRandom* random,
|
||||
fEffectKeys[s] = factory.glEffectKey(stages[s], gpu->glCaps());
|
||||
// use separate tex coords?
|
||||
if (!useOnce && random->nextBool()) {
|
||||
fVertexLayout |= GrDrawState::StageTexCoordVertexLayoutBit(s);
|
||||
fAttribBindings |= GrDrawState::ExplicitTexCoordAttribBindingsBit(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) {
|
||||
|
Loading…
Reference in New Issue
Block a user