Revise attribute binding interface.

Replace the old attribute binding and index interface with one where we include the binding as part of the attribute array. Also removed the fixed attribute indices for constant color and coverage attributes, and replaced with dynamic ones based on current attribute set. Removed binding of color and coverage attributes unless they're actually set.

Original author: bsalomon@google.com

Author: jvanverth@google.com

Reviewed By: bsalomon@google.com,robertphillips@google.com

Review URL: https://chromiumcodereview.appspot.com/13296005

git-svn-id: http://skia.googlecode.com/svn/trunk@8466 2bbb7eff-a529-9590-31e7-b0007b416f81
This commit is contained in:
commit-bot@chromium.org 2013-04-01 19:12:42 +00:00
parent d9c1853fb8
commit fb495b537f
21 changed files with 452 additions and 579 deletions

View File

@ -111,6 +111,21 @@ public:
*/
void reset() { this->pop_back_n(fCount); }
/**
* Resets to a copy of a C array.
*/
void reset(const T* array, int count) {
for (int i = 0; i < fCount; ++i) {
fItemArray[i].~T();
}
int delta = count - fCount;
this->checkRealloc(delta);
fCount = count;
for (int i = 0; i < count; ++i) {
SkTArrayExt::copy(this, array);
}
}
/**
* Number of elements in the array.
*/

View File

@ -8,12 +8,12 @@
#ifndef GrTypesPriv_DEFINED
#define GrTypesPriv_DEFINED
#include "GrTypes.h"
#include "SkTArray.h"
/**
* Types of shader-language-specific boxed variables we can create.
* (Currently only GrGLShaderVars, but should be applicable to other shader
* languages.)
* Types of shader-language-specific boxed variables we can create. (Currently only GrGLShaderVars,
* but should be applicable to other shader languages.)
*/
enum GrSLType {
kVoid_GrSLType,
@ -23,11 +23,43 @@ enum GrSLType {
kVec4f_GrSLType,
kMat33f_GrSLType,
kMat44f_GrSLType,
kSampler2D_GrSLType
kSampler2D_GrSLType,
kLast_GrSLType = kSampler2D_GrSLType
};
static const int kGrSLTypeCount = kLast_GrSLType + 1;
/**
* Types used to describe format of vertices in arrays
* Gets the vector size of the SLType. Returns -1 for void, matrices, and samplers.
*/
static inline int GrSLTypeVectorCount(GrSLType type) {
GrAssert(type >= 0 && type < kGrSLTypeCount);
static const int kCounts[] = { -1, 1, 2, 3, 4, -1, -1, -1 };
return kCounts[type];
GR_STATIC_ASSERT(0 == kVoid_GrSLType);
GR_STATIC_ASSERT(1 == kFloat_GrSLType);
GR_STATIC_ASSERT(2 == kVec2f_GrSLType);
GR_STATIC_ASSERT(3 == kVec3f_GrSLType);
GR_STATIC_ASSERT(4 == kVec4f_GrSLType);
GR_STATIC_ASSERT(5 == kMat33f_GrSLType);
GR_STATIC_ASSERT(6 == kMat44f_GrSLType);
GR_STATIC_ASSERT(7 == kSampler2D_GrSLType);
GR_STATIC_ASSERT(GR_ARRAY_COUNT(kCounts) == kGrSLTypeCount);
}
static inline GrSLType GrSLFloatVectorType(int count) {
GrAssert(count > 0 && count <= 4);
return (GrSLType)(count);
GR_STATIC_ASSERT(kFloat_GrSLType == 1);
GR_STATIC_ASSERT(kVec2f_GrSLType == 2);
GR_STATIC_ASSERT(kVec3f_GrSLType == 3);
GR_STATIC_ASSERT(kVec4f_GrSLType == 4);
}
/**
* Types used to describe format of vertices in arrays.
*/
enum GrVertexAttribType {
kFloat_GrVertexAttribType = 0,
@ -40,20 +72,96 @@ enum GrVertexAttribType {
};
static const int kGrVertexAttribTypeCount = kLast_GrVertexAttribType + 1;
/**
* Returns the vector size of the type.
*/
static inline int GrVertexAttribTypeVectorCount(GrVertexAttribType type) {
GrAssert(type >= 0 && type < kGrVertexAttribTypeCount);
static const int kCounts[] = { 1, 2, 3, 4, 4 };
return kCounts[type];
GR_STATIC_ASSERT(0 == kFloat_GrVertexAttribType);
GR_STATIC_ASSERT(1 == kVec2f_GrVertexAttribType);
GR_STATIC_ASSERT(2 == kVec3f_GrVertexAttribType);
GR_STATIC_ASSERT(3 == kVec4f_GrVertexAttribType);
GR_STATIC_ASSERT(4 == kVec4ub_GrVertexAttribType);
GR_STATIC_ASSERT(GR_ARRAY_COUNT(kCounts) == kGrVertexAttribTypeCount);
}
/**
* Returns the size of the attrib type in bytes.
*/
static inline size_t GrVertexAttribTypeSize(GrVertexAttribType type) {
GrAssert(type >= 0 && type < kGrVertexAttribTypeCount);
static const size_t kSizes[] = {
sizeof(float), // kFloat_GrVertexAttribType
2*sizeof(float), // kVec2f_GrVertexAttribType
3*sizeof(float), // kVec3f_GrVertexAttribType
4*sizeof(float), // kVec4f_GrVertexAttribType
4*sizeof(char) // kVec4ub_GrVertexAttribType
};
return kSizes[type];
GR_STATIC_ASSERT(0 == kFloat_GrVertexAttribType);
GR_STATIC_ASSERT(1 == kVec2f_GrVertexAttribType);
GR_STATIC_ASSERT(2 == kVec3f_GrVertexAttribType);
GR_STATIC_ASSERT(3 == kVec4f_GrVertexAttribType);
GR_STATIC_ASSERT(4 == kVec4ub_GrVertexAttribType);
GR_STATIC_ASSERT(GR_ARRAY_COUNT(kSizes) == kGrVertexAttribTypeCount);
}
/**
* Semantic bindings for vertex attributes. kEffect means that the attribute is input to a GrEffect.
* Each binding other than kEffect may not appear more than once in the current set of attributes.
* kPosition must be appear for exactly one attribute.
*/
enum GrVertexAttribBinding {
kPosition_GrVertexAttribBinding, // required, must have vector count of 2
kLocalCoord_GrVertexAttribBinding, // must have vector count of 2
kColor_GrVertexAttribBinding, // must have vector count of 4
kCoverage_GrVertexAttribBinding, // must have vector count of 4
kLastFixedFunction_GrVertexAttribBinding = kCoverage_GrVertexAttribBinding,
kEffect_GrVertexAttribBinding, // vector length must agree with
// GrEffect::vertexAttribType() for each effect input to
// which the attribute is mapped by GrDrawState::setEffect()
kLast_GrVertexAttribBinding = kEffect_GrVertexAttribBinding
};
static const int kGrVertexAttribBindingCnt = kLast_GrVertexAttribBinding + 1;
static const int kGrFixedFunctionVertexAttribBindingCnt =
kLastFixedFunction_GrVertexAttribBinding + 1;
static const int GrFixedFunctionVertexAttribVectorCount(GrVertexAttribBinding binding) {
GrAssert(binding >= 0 && binding < kGrFixedFunctionVertexAttribBindingCnt);
static const int kVecCounts[] = { 2, 2, 4, 4 };
return kVecCounts[binding];
GR_STATIC_ASSERT(0 == kPosition_GrVertexAttribBinding);
GR_STATIC_ASSERT(1 == kLocalCoord_GrVertexAttribBinding);
GR_STATIC_ASSERT(2 == kColor_GrVertexAttribBinding);
GR_STATIC_ASSERT(3 == kCoverage_GrVertexAttribBinding);
GR_STATIC_ASSERT(kGrFixedFunctionVertexAttribBindingCnt == SK_ARRAY_COUNT(kVecCounts));
}
struct GrVertexAttrib {
inline void set(GrVertexAttribType type, size_t offset) {
fType = type; fOffset = offset;
inline void set(GrVertexAttribType type, size_t offset, GrVertexAttribBinding binding) {
fType = type;
fOffset = offset;
fBinding = binding;
}
bool operator==(const GrVertexAttrib& other) const {
return fType == other.fType && fOffset == other.fOffset;
return fType == other.fType && fOffset == other.fOffset && fBinding == other.fBinding;
};
bool operator!=(const GrVertexAttrib& other) const { return !(*this == other); }
GrVertexAttribType fType;
size_t fOffset;
GrVertexAttribType fType;
size_t fOffset;
GrVertexAttribBinding fBinding;
};
template <int N>
class GrVertexAttribArray : public SkSTArray<N, GrVertexAttrib, true> {};
template <int N> class GrVertexAttribArray : public SkSTArray<N, GrVertexAttrib, true> {};
#endif

View File

@ -485,13 +485,10 @@ bool GrAAConvexPathRenderer::onDrawPath(const SkPath& origPath,
// position + edge
static const GrVertexAttrib kAttribs[] = {
{kVec2f_GrVertexAttribType, 0},
{kVec4f_GrVertexAttribType, sizeof(GrPoint)}
{kVec2f_GrVertexAttribType, 0, kPosition_GrVertexAttribBinding},
{kVec4f_GrVertexAttribType, sizeof(GrPoint), kEffect_GrVertexAttribBinding}
};
drawState->setVertexAttribs(kAttribs, SK_ARRAY_COUNT(kAttribs));
drawState->setAttribIndex(GrDrawState::kPosition_AttribIndex, 0);
drawState->setAttribBindings(GrDrawState::kDefault_AttribBindings);
enum {
// the edge effects share this stage with glyph rendering

View File

@ -507,8 +507,8 @@ bool GrAAHairLinePathRenderer::createGeom(
// position + edge
static const GrVertexAttrib kAttribs[] = {
{kVec2f_GrVertexAttribType, 0},
{kVec4f_GrVertexAttribType, sizeof(GrPoint)}
{kVec2f_GrVertexAttribType, 0, kPosition_GrVertexAttribBinding},
{kVec4f_GrVertexAttribType, sizeof(GrPoint), kEffect_GrVertexAttribBinding}
};
SkMatrix viewM = drawState->getViewMatrix();
@ -522,8 +522,6 @@ bool GrAAHairLinePathRenderer::createGeom(
int vertCnt = kVertsPerLineSeg * *lineCnt + kVertsPerQuad * *quadCnt;
target->drawState()->setVertexAttribs(kAttribs, SK_ARRAY_COUNT(kAttribs));
target->drawState()->setAttribIndex(GrDrawState::kPosition_AttribIndex, 0);
target->drawState()->setAttribBindings(GrDrawState::kDefault_AttribBindings);
GrAssert(sizeof(Vertex) == target->getDrawState().getVertexSize());
if (!arg->set(target, vertCnt, 0)) {

View File

@ -13,15 +13,17 @@ SK_DEFINE_INST_COUNT(GrAARectRenderer)
namespace {
static void aa_rect_attributes(bool useCoverage, GrAttribBindings* bindings,
GrDrawState::AttribIndex* index) {
if (useCoverage) {
*bindings = GrDrawState::kCoverage_AttribBindingsBit;
*index = GrDrawState::kCoverage_AttribIndex;
} else {
*bindings = GrDrawState::kColor_AttribBindingsBit;
*index = GrDrawState::kColor_AttribIndex;
}
static void aa_rect_attributes(bool useCoverage, const GrVertexAttrib** attribs, int* count) {
static const GrVertexAttrib kCoverageAttribs[] = {
{kVec2f_GrVertexAttribType, 0, kPosition_GrVertexAttribBinding},
{kVec4ub_GrVertexAttribType, sizeof(GrPoint), kCoverage_GrVertexAttribBinding},
};
static const GrVertexAttrib kColorAttribs[] = {
{kVec2f_GrVertexAttribType, 0, kPosition_GrVertexAttribBinding},
{kVec4ub_GrVertexAttribType, sizeof(GrPoint), kColor_GrVertexAttribBinding},
};
*attribs = useCoverage ? kCoverageAttribs : kColorAttribs;
*count = 2;
}
static void set_inset_fan(GrPoint* pts, size_t stride,
@ -128,18 +130,10 @@ void GrAARectRenderer::fillAARect(GrGpu* gpu,
bool useVertexCoverage) {
GrDrawState* drawState = target->drawState();
// position + color/coverage
static const GrVertexAttrib kVertexAttribs[] = {
{kVec2f_GrVertexAttribType, 0},
{kVec4ub_GrVertexAttribType, sizeof(GrPoint)}
};
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);
const GrVertexAttrib* attribs;
int attribCount;
aa_rect_attributes(useVertexCoverage, &attribs, &attribCount);
drawState->setVertexAttribs(attribs, attribCount);
GrDrawTarget::AutoReleaseGeometry geo(target, 8, 0);
if (!geo.succeeded()) {
@ -212,18 +206,10 @@ void GrAARectRenderer::strokeAARect(GrGpu* gpu,
return;
}
// position + color/coverage
static const GrVertexAttrib kVertexAttribs[] = {
{kVec2f_GrVertexAttribType, 0},
{kVec4ub_GrVertexAttribType, sizeof(GrPoint)}
};
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);
const GrVertexAttrib* attribs;
int attribCount;
aa_rect_attributes(useVertexCoverage, &attribs, &attribCount);
drawState->setVertexAttribs(attribs, attribCount);
GrDrawTarget::AutoReleaseGeometry geo(target, 16, 0);
if (!geo.succeeded()) {

View File

@ -358,17 +358,13 @@ GrTexture* GrContext::createResizedTexture(const GrTextureDesc& desc,
GrTextureParams params(SkShader::kClamp_TileMode, needsFiltering);
drawState->createTextureEffect(0, clampedTexture, SkMatrix::I(), params);
// position + texture coordinate
// position + local coordinate
static const GrVertexAttrib kVertexAttribs[] = {
{kVec2f_GrVertexAttribType, 0},
{kVec2f_GrVertexAttribType, sizeof(GrPoint)}
{kVec2f_GrVertexAttribType, 0, kPosition_GrVertexAttribBinding},
{kVec2f_GrVertexAttribType, sizeof(GrPoint), kLocalCoord_GrVertexAttribBinding}
};
static const GrAttribBindings kAttribBindings = GrDrawState::kLocalCoords_AttribBindingsBit;
drawState->setAttribBindings(kAttribBindings);
drawState->setVertexAttribs(kVertexAttribs, SK_ARRAY_COUNT(kVertexAttribs));
drawState->setAttribIndex(GrDrawState::kPosition_AttribIndex, 0);
drawState->setAttribIndex(GrDrawState::kLocalCoords_AttribIndex, 1);
GrDrawTarget::AutoReleaseGeometry arg(fGpu, 4, 0);
if (arg.succeeded()) {
@ -925,19 +921,16 @@ void GrContext::drawVertices(const GrPaint& paint,
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());
GrVertexAttrib currAttrib = {kVec2f_GrVertexAttribType, currentOffset};
GrVertexAttrib currAttrib =
{kVec2f_GrVertexAttribType, currentOffset, kPosition_GrVertexAttribBinding};
attribs.push_back(currAttrib);
currentOffset += sizeof(GrPoint);
// set up optional texture coordinate attributes
if (NULL != texCoords) {
bindings |= GrDrawState::kLocalCoords_AttribBindingsBit;
drawState->setAttribIndex(GrDrawState::kLocalCoords_AttribIndex, attribs.count());
currAttrib.set(kVec2f_GrVertexAttribType, currentOffset);
currAttrib.set(kVec2f_GrVertexAttribType, currentOffset, kLocalCoord_GrVertexAttribBinding);
attribs.push_back(currAttrib);
texOffset = currentOffset;
currentOffset += sizeof(GrPoint);
@ -945,16 +938,13 @@ void GrContext::drawVertices(const GrPaint& paint,
// set up optional color attributes
if (NULL != colors) {
bindings |= GrDrawState::kColor_AttribBindingsBit;
drawState->setAttribIndex(GrDrawState::kColor_AttribIndex, attribs.count());
currAttrib.set(kVec4ub_GrVertexAttribType, currentOffset);
currAttrib.set(kVec4ub_GrVertexAttribType, currentOffset, kColor_GrVertexAttribBinding);
attribs.push_back(currAttrib);
colorOffset = currentOffset;
currentOffset += sizeof(GrColor);
}
drawState->setVertexAttribs(attribs.begin(), attribs.count());
drawState->setAttribBindings(bindings);
size_t vertexSize = drawState->getVertexSize();
GrAssert(vertexSize == currentOffset);

View File

@ -46,23 +46,15 @@ void GrDrawState::setFromPaint(const GrPaint& paint) {
////////////////////////////////////////////////////////////////////////////////
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::kVertexAttribCnt);
GrAssert(count <= GrDrawState::kMaxVertexAttribCnt);
size_t size = 0;
for (int index = 0; index < count; ++index) {
size_t attribSize = GrDrawState::kVertexAttribSizes[attribs[index].fType];
size_t attribSize = GrVertexAttribTypeSize(attribs[index].fType);
size += attribSize;
#if GR_DEBUG
size_t dwordCount = attribSize >> 2;
@ -76,163 +68,102 @@ static size_t vertex_size(const GrVertexAttrib* attribs, int count) {
}
size_t GrDrawState::getVertexSize() const {
return vertex_size(fVertexAttribs.begin(), fVertexAttribs.count());
return vertex_size(fCommon.fVertexAttribs.begin(), fCommon.fVertexAttribs.count());
}
const GrAttribBindings GrDrawState::kAttribIndexMasks[kAttribIndexCount] = {
0, // position is not reflected in the bindings
kColor_AttribBindingsBit,
kCoverage_AttribBindingsBit,
kLocalCoords_AttribBindingsBit,
};
////////////////////////////////////////////////////////////////////////////////
void GrDrawState::setVertexAttribs(const GrVertexAttrib* attribs, int count) {
GrAssert(count <= GrDrawState::kVertexAttribCnt);
fVertexAttribs.reset();
for (int index = 0; index < count; ++index) {
fVertexAttribs.push_back(attribs[index]);
GrAssert(count <= kMaxVertexAttribCnt);
fCommon.fVertexAttribs.reset(attribs, count);
// Set all the indices to -1
memset(fCommon.fFixedFunctionVertexAttribIndices,
0xff,
sizeof(fCommon.fFixedFunctionVertexAttribIndices));
#if GR_DEBUG
uint32_t overlapCheck = 0;
#endif
for (int i = 0; i < count; ++i) {
if (attribs[i].fBinding < kGrFixedFunctionVertexAttribBindingCnt) {
// The fixed function attribs can only be specified once
GrAssert(-1 == fCommon.fFixedFunctionVertexAttribIndices[attribs[i].fBinding]);
GrAssert(GrFixedFunctionVertexAttribVectorCount(attribs[i].fBinding) ==
GrVertexAttribTypeVectorCount(attribs[i].fType));
fCommon.fFixedFunctionVertexAttribIndices[attribs[i].fBinding] = i;
}
#if GR_DEBUG
size_t dwordCount = GrVertexAttribTypeSize(attribs[i].fType) >> 2;
uint32_t mask = (1 << dwordCount)-1;
size_t offsetShift = attribs[i].fOffset >> 2;
GrAssert(!(overlapCheck & (mask << offsetShift)));
overlapCheck |= (mask << offsetShift);
#endif
}
// Positions must be specified.
GrAssert(-1 != fCommon.fFixedFunctionVertexAttribIndices[kPosition_GrVertexAttribBinding]);
}
////////////////////////////////////////////////////////////////////////////////
void GrDrawState::setDefaultVertexAttribs() {
static const GrVertexAttrib kPositionAttrib = {kVec2f_GrVertexAttribType, 0};
fVertexAttribs.reset();
fVertexAttribs.push_back(kPositionAttrib);
fCommon.fAttribBindings = kDefault_AttribBindings;
fAttribIndices[kPosition_AttribIndex] = 0;
static const GrVertexAttrib kPositionAttrib =
{kVec2f_GrVertexAttribType, 0, kPosition_GrVertexAttribBinding};
fCommon.fVertexAttribs.reset(&kPositionAttrib, 1);
// set all the fixed function indices to -1 except position.
memset(fCommon.fFixedFunctionVertexAttribIndices,
0xff,
sizeof(fCommon.fFixedFunctionVertexAttribIndices));
fCommon.fFixedFunctionVertexAttribIndices[kPosition_GrVertexAttribBinding] = 0;
}
////////////////////////////////////////////////////////////////////////////////
bool GrDrawState::validateVertexAttribs() const {
// color and coverage can set indices beyond the standard count
static const int kMaxValidAttribIndex = kVertexAttribCnt+2;
int attributeTypes[kMaxValidAttribIndex];
for (int i = 0; i < kMaxValidAttribIndex; ++i) {
attributeTypes[i] = -1;
// check consistency of effects and attributes
GrSLType slTypes[kMaxVertexAttribCnt];
for (int i = 0; i < kMaxVertexAttribCnt; ++i) {
slTypes[i] = static_cast<GrSLType>(-1);
}
// sentinel to make sure effects don't try to use built-in attributes
static const int kBuiltInAttributeType = 10000;
// check our built-in indices
if (fAttribIndices[kPosition_AttribIndex] >= kVertexAttribCnt) {
return false;
}
attributeTypes[fAttribIndices[kPosition_AttribIndex]] = kBuiltInAttributeType;
for (int j = kColor_AttribIndex; j <= kCoverage_AttribIndex; ++j) {
if (fCommon.fAttribBindings & kAttribIndexMasks[j]) {
int attributeIndex = fAttribIndices[j];
if (attributeIndex >= kMaxValidAttribIndex) {
return false;
}
// they should not be shared at all
if (attributeTypes[attributeIndex] != -1) {
return false;
}
attributeTypes[attributeIndex] = kBuiltInAttributeType;
}
}
if (fCommon.fAttribBindings & kAttribIndexMasks[kLocalCoords_AttribIndex]) {
int attributeIndex = fAttribIndices[kLocalCoords_AttribIndex];
if (attributeIndex >= kVertexAttribCnt) {
return false;
}
// they should not be shared at all
if (attributeTypes[attributeIndex] != -1) {
return false;
}
attributeTypes[attributeIndex] = kBuiltInAttributeType;
}
// now those set by effects
for (int s = 0; s < kNumStages; ++s) {
const GrEffectStage& stage = fStages[s];
const GrEffectRef* effect = stage.getEffect();
if (effect == NULL) {
continue;
}
if (this->isStageEnabled(s)) {
const GrEffectStage& stage = fStages[s];
const GrEffectRef* effect = stage.getEffect();
// make sure that any attribute indices have the correct binding type, that the attrib
// type and effect's shader lang type are compatible, and that attributes shared by
// multiple effects use the same shader lang type.
const int* attributeIndices = stage.getVertexAttribIndices();
int numAttributes = stage.getVertexAttribIndexCount();
for (int i = 0; i < numAttributes; ++i) {
int attribIndex = attributeIndices[i];
if (attribIndex >= fCommon.fVertexAttribs.count() ||
kEffect_GrVertexAttribBinding != fCommon.fVertexAttribs[attribIndex].fBinding) {
return false;
}
// make sure that the count in the stage and the effect matches
int numAttributes = stage.getVertexAttribIndexCount();
if (numAttributes != effect->get()->numVertexAttribs()) {
return false;
}
// make sure that any shared indices have the same type
const int* attributeIndices = stage.getVertexAttribIndices();
for (int i = 0; i < numAttributes; ++i) {
int attributeIndex = attributeIndices[i];
if (attributeIndex >= kVertexAttribCnt) {
return false;
GrSLType effectSLType = (*effect)->vertexAttribType(i);
GrVertexAttribType attribType = fCommon.fVertexAttribs[attribIndex].fType;
int slVecCount = GrSLTypeVectorCount(effectSLType);
int attribVecCount = GrVertexAttribTypeVectorCount(attribType);
if (slVecCount != attribVecCount ||
(-1 != slTypes[attribIndex] && slTypes[attribIndex] != effectSLType)) {
return false;
}
slTypes[attribIndex] = effectSLType;
}
GrSLType attributeType = effect->get()->vertexAttribType(i);
if (attributeTypes[attributeIndex] != -1 &&
attributeTypes[attributeIndex] != attributeType) {
return false;
}
attributeTypes[attributeIndex] = attributeType;
}
}
return true;
}
void GrDrawState::VertexAttributesUnitTest() {
// not necessarily exhaustive
static bool run;
if (!run) {
run = true;
GrVertexAttribArray<6> attribs;
GrAssert(0 == vertex_size(attribs.begin(), attribs.count()));
GrVertexAttrib currAttrib = {kFloat_GrVertexAttribType, 0};
attribs.push_back(currAttrib);
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()));
currAttrib.set(kVec2f_GrVertexAttribType, attribs[0].fOffset + 4*sizeof(char));
attribs.push_back(currAttrib);
GrAssert(4*sizeof(char) + 2*sizeof(float) == vertex_size(attribs.begin(), attribs.count()));
currAttrib.set(kVec3f_GrVertexAttribType, attribs[1].fOffset + 2*sizeof(float));
attribs.push_back(currAttrib);
GrAssert(4*sizeof(char) + 2*sizeof(float) + 3*sizeof(float) ==
vertex_size(attribs.begin(), attribs.count()));
currAttrib.set(kFloat_GrVertexAttribType, attribs[2].fOffset + 3*sizeof(float));
attribs.push_back(currAttrib);
GrAssert(4*sizeof(char) + 2*sizeof(float) + 3*sizeof(float) + sizeof(float) ==
vertex_size(attribs.begin(), attribs.count()));
currAttrib.set(kVec4f_GrVertexAttribType, attribs[3].fOffset + sizeof(float));
attribs.push_back(currAttrib);
GrAssert(4*sizeof(char) + 2*sizeof(float) + 3*sizeof(float) + sizeof(float) + 4*sizeof(float) ==
vertex_size(attribs.begin(), attribs.count()));
}
}
////////////////////////////////////////////////////////////////////////////////
bool GrDrawState::srcAlphaWillBeOne(GrAttribBindings bindings) const {
bool GrDrawState::srcAlphaWillBeOne() const {
uint32_t validComponentFlags;
GrColor color;
// Check if per-vertex or constant color may have partial alpha
if (bindings & kColor_AttribBindingsBit) {
if (this->hasColorVertexAttribute()) {
validComponentFlags = 0;
color = 0; // not strictly necessary but we get false alarms from tools about uninit.
} else {
@ -278,7 +209,7 @@ bool GrDrawState::srcAlphaWillBeOne(GrAttribBindings bindings) const {
return (kA_GrColorComponentFlag & validComponentFlags) && 0xff == GrColorUnpackA(color);
}
bool GrDrawState::hasSolidCoverage(GrAttribBindings bindings) const {
bool GrDrawState::hasSolidCoverage() const {
// If we're drawing coverage directly then coverage is effectively treated as color.
if (this->isCoverageDrawing()) {
return true;
@ -287,7 +218,7 @@ bool GrDrawState::hasSolidCoverage(GrAttribBindings bindings) const {
GrColor coverage;
uint32_t validComponentFlags;
// Initialize to an unknown starting coverage if per-vertex coverage is specified.
if (bindings & kCoverage_AttribBindingsBit) {
if (this->hasCoverageVertexAttribute()) {
validComponentFlags = 0;
} else {
coverage = fCommon.fCoverage;
@ -329,7 +260,6 @@ bool GrDrawState::canTweakAlphaForCoverage() const {
GrDrawState::BlendOptFlags GrDrawState::getBlendOpts(bool forceCoverage,
GrBlendCoeff* srcCoeff,
GrBlendCoeff* dstCoeff) const {
GrAttribBindings bindings = this->getAttribBindings();
GrBlendCoeff bogusSrcCoeff, bogusDstCoeff;
if (NULL == srcCoeff) {
@ -347,14 +277,14 @@ GrDrawState::BlendOptFlags GrDrawState::getBlendOpts(bool forceCoverage,
*dstCoeff = kOne_GrBlendCoeff;
}
bool srcAIsOne = this->srcAlphaWillBeOne(bindings);
bool srcAIsOne = this->srcAlphaWillBeOne();
bool dstCoeffIsOne = kOne_GrBlendCoeff == *dstCoeff ||
(kSA_GrBlendCoeff == *dstCoeff && srcAIsOne);
bool dstCoeffIsZero = kZero_GrBlendCoeff == *dstCoeff ||
(kISA_GrBlendCoeff == *dstCoeff && srcAIsOne);
bool covIsZero = !this->isCoverageDrawing() &&
!(bindings & GrDrawState::kCoverage_AttribBindingsBit) &&
!this->hasCoverageVertexAttribute() &&
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
@ -371,10 +301,8 @@ GrDrawState::BlendOptFlags GrDrawState::getBlendOpts(bool forceCoverage,
// check for coverage due to constant coverage, per-vertex coverage, or coverage stage
bool hasCoverage = forceCoverage ||
0xffffffff != this->getCoverage() ||
(bindings & GrDrawState::kCoverage_AttribBindingsBit);
for (int s = this->getFirstCoverageStage();
!hasCoverage && s < GrDrawState::kNumStages;
++s) {
this->hasCoverageVertexAttribute();
for (int s = this->getFirstCoverageStage(); !hasCoverage && s < GrDrawState::kNumStages; ++s) {
if (this->isStageEnabled(s)) {
hasCoverage = true;
}

View File

@ -23,11 +23,6 @@
#include "SkMatrix.h"
#include "SkXfermode.h"
/**
* Type used to describe how attributes bind to program usage
*/
typedef int GrAttribBindings;
class GrDrawState : public GrRefCnt {
public:
SK_DECLARE_INST_COUNT(GrDrawState)
@ -45,8 +40,8 @@ public:
* coverage rather than as input to the src/dst color blend step.
*
* The input color to the first enabled color-stage is either the constant color or interpolated
* per-vertex colors, depending upon GrAttribBindings. The input to the first coverage stage is
* either a constant coverage (usually full-coverage) or interpolated per-vertex coverage.
* per-vertex colors. The input to the first coverage stage is either a constant coverage
* (usually full-coverage) or interpolated per-vertex coverage.
*
* See the documentation of kCoverageDrawing_StateBit for information about disabling the
* the color / coverage distinction.
@ -62,9 +57,6 @@ public:
};
GrDrawState() {
#if GR_DEBUG
VertexAttributesUnitTest();
#endif
this->reset();
}
@ -115,53 +107,72 @@ public:
////
enum {
kVertexAttribCnt = 6,
kMaxVertexAttribCnt = kLast_GrVertexAttribBinding + 4,
};
/**
* 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).
* The format of vertices is represented as an array of GrVertexAttribs, with each representing
* the type of the attribute, its offset, and semantic binding (see GrVertexAttrib in
* GrTypesPriv.h).
*
* 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.
* The mapping of attributes with kEffect bindings to GrEffect inputs is specified when
* setEffect is called.
*/
/**
* 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.
* @param count the number of attributes being set, limited to kMaxVertexAttribCnt.
*/
void setVertexAttribs(const GrVertexAttrib attribs[], int count);
const GrVertexAttrib* getVertexAttribs() const { return fVertexAttribs.begin(); }
int getVertexAttribCount() const { return fVertexAttribs.count(); }
const GrVertexAttrib* getVertexAttribs() const { return fCommon.fVertexAttribs.begin(); }
int getVertexAttribCount() const { return fCommon.fVertexAttribs.count(); }
size_t getVertexSize() const;
/**
* Sets default vertex attributes for next draw.
*
* This will also set default vertex attribute indices and bindings
* Sets default vertex attributes for next draw. The default is a single attribute:
* {kVec2f_GrVertexAttribType, 0, kPosition_GrVertexAttribType}
*/
void setDefaultVertexAttribs();
/**
* Getters for index into getVertexAttribs() for particular bindings. -1 is returned if the
* binding does not appear in the current attribs. These bindings should appear only once in
* the attrib array.
*/
int positionAttributeIndex() const {
return fCommon.fFixedFunctionVertexAttribIndices[kPosition_GrVertexAttribBinding];
}
int localCoordAttributeIndex() const {
return fCommon.fFixedFunctionVertexAttribIndices[kLocalCoord_GrVertexAttribBinding];
}
int colorVertexAttributeIndex() const {
return fCommon.fFixedFunctionVertexAttribIndices[kColor_GrVertexAttribBinding];
}
int coverageVertexAttributeIndex() const {
return fCommon.fFixedFunctionVertexAttribIndices[kCoverage_GrVertexAttribBinding];
}
bool hasLocalCoordAttribute() const {
return -1 != fCommon.fFixedFunctionVertexAttribIndices[kLocalCoord_GrVertexAttribBinding];
}
bool hasColorVertexAttribute() const {
return -1 != fCommon.fFixedFunctionVertexAttribIndices[kColor_GrVertexAttribBinding];
}
bool hasCoverageVertexAttribute() const {
return -1 != fCommon.fFixedFunctionVertexAttribIndices[kCoverage_GrVertexAttribBinding];
}
bool validateVertexAttribs() const;
////////////////////////////////////////////////////////////////////////////
// Helpers for picking apart vertex attributes
// 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
* array is a hassle involving casts and simple math. These helpers exist
* to keep GrDrawTarget clients' code a bit nicer looking.
* Accessing positions, local coords, or colors, of a vertex within an array is a hassle
* involving casts and simple math. These helpers exist to keep GrDrawTarget clients' code a bit
* nicer looking.
*/
/**
@ -218,110 +229,15 @@ public:
/// @}
///////////////////////////////////////////////////////////////////////////
/// @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. The
* local coords accessible by effects may either come from positions or
* be specified explicitly.
*/
/**
* Additional Bits that can be specified in GrAttribBindings.
*/
enum AttribBindingsBits {
/** explicit local coords are provided (instead of using pre-view-matrix positions) */
kLocalCoords_AttribBindingsBit = 0x1,
/* program uses colors (GrColor) */
kColor_AttribBindingsBit = 0x2,
/* program uses coverage (GrColor)
*/
kCoverage_AttribBindingsBit = 0x4,
// 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
/**
* Determines whether src alpha is guaranteed to be one for all src pixels
*/
bool srcAlphaWillBeOne(GrAttribBindings) const;
bool srcAlphaWillBeOne() 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,
kLocalCoords_AttribIndex,
kLast_AttribIndex = kLocalCoords_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]; }
bool hasSolidCoverage() const;
/// @}
@ -1068,15 +984,6 @@ public:
if (fRenderTarget.get() != s.fRenderTarget.get() || fCommon != s.fCommon) {
return false;
}
if (fVertexAttribs != s.fVertexAttribs) {
return false;
}
for (int i = 0; i < kAttribIndexCount; ++i) {
if ((i == kPosition_AttribIndex || s.fCommon.fAttribBindings & (1 << 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)) {
@ -1093,10 +1000,6 @@ public:
GrDrawState& operator= (const GrDrawState& s) {
this->setRenderTarget(s.fRenderTarget.get());
fCommon = s.fCommon;
fVertexAttribs = s.fVertexAttribs;
for (int i = 0; i < kAttribIndexCount; i++) {
fAttribIndices[i] = s.fAttribIndices[i];
}
for (int i = 0; i < kNumStages; i++) {
if (s.isStageEnabled(i)) {
this->fStages[i] = s.fStages[i];
@ -1110,33 +1013,44 @@ private:
/** Fields that are identical in GrDrawState and GrDrawState::DeferredState. */
struct CommonState {
// These fields are roughly sorted by decreasing likelihood of being different in op==
GrColor fColor;
GrAttribBindings fAttribBindings;
SkMatrix fViewMatrix;
GrBlendCoeff fSrcBlend;
GrBlendCoeff fDstBlend;
GrColor fBlendConstant;
uint32_t fFlagBits;
GrStencilSettings fStencilSettings;
int fFirstCoverageStage;
GrColor fCoverage;
SkXfermode::Mode fColorFilterMode;
GrColor fColorFilterColor;
DrawFace fDrawFace;
GrColor fColor;
SkMatrix fViewMatrix;
GrBlendCoeff fSrcBlend;
GrBlendCoeff fDstBlend;
GrColor fBlendConstant;
uint32_t fFlagBits;
GrVertexAttribArray<kMaxVertexAttribCnt> fVertexAttribs;
GrStencilSettings fStencilSettings;
int fFirstCoverageStage;
GrColor fCoverage;
SkXfermode::Mode fColorFilterMode;
GrColor fColorFilterColor;
DrawFace fDrawFace;
// This is simply a different representation of info in fVertexAttribs and thus does
// not need to be compared in op==.
int fFixedFunctionVertexAttribIndices[kGrFixedFunctionVertexAttribBindingCnt];
GR_STATIC_ASSERT(kGrVertexAttribBindingCnt <= 8*sizeof(uint32_t));
bool operator== (const CommonState& other) const {
return fColor == other.fColor &&
fAttribBindings == other.fAttribBindings &&
fViewMatrix.cheapEqualTo(other.fViewMatrix) &&
fSrcBlend == other.fSrcBlend &&
fDstBlend == other.fDstBlend &&
fBlendConstant == other.fBlendConstant &&
fFlagBits == other.fFlagBits &&
fStencilSettings == other.fStencilSettings &&
fFirstCoverageStage == other.fFirstCoverageStage &&
fCoverage == other.fCoverage &&
fColorFilterMode == other.fColorFilterMode &&
fColorFilterColor == other.fColorFilterColor &&
fDrawFace == other.fDrawFace;
bool result = fColor == other.fColor &&
fViewMatrix.cheapEqualTo(other.fViewMatrix) &&
fSrcBlend == other.fSrcBlend &&
fDstBlend == other.fDstBlend &&
fBlendConstant == other.fBlendConstant &&
fFlagBits == other.fFlagBits &&
fVertexAttribs == other.fVertexAttribs &&
fStencilSettings == other.fStencilSettings &&
fFirstCoverageStage == other.fFirstCoverageStage &&
fCoverage == other.fCoverage &&
fColorFilterMode == other.fColorFilterMode &&
fColorFilterColor == other.fColorFilterColor &&
fDrawFace == other.fDrawFace;
GrAssert(!result || 0 == memcmp(fFixedFunctionVertexAttribIndices,
other.fFixedFunctionVertexAttribIndices,
sizeof(fFixedFunctionVertexAttribIndices)));
return result;
}
bool operator!= (const CommonState& other) const { return !(*this == other); }
};
@ -1169,10 +1083,6 @@ public:
// TODO: Here we will copy the GrRenderTarget pointer without taking a ref.
fRenderTarget = drawState.fRenderTarget.get();
SkSafeRef(fRenderTarget);
fVertexAttribs = drawState.fVertexAttribs;
for (int i = 0; i < kAttribIndexCount; i++) {
fAttribIndices[i] = drawState.fAttribIndices[i];
}
// Here we ref the effects directly rather than the effect-refs. TODO: When the effect-
// ref gets fully unref'ed it will cause the underlying effect to unref its resources
// and recycle them to the cache (if no one else is holding a ref to the resources).
@ -1186,10 +1096,6 @@ public:
GrAssert(fInitialized);
drawState->fCommon = fCommon;
drawState->setRenderTarget(fRenderTarget);
drawState->fVertexAttribs = fVertexAttribs;
for (int i = 0; i < kAttribIndexCount; i++) {
drawState->fAttribIndices[i] = fAttribIndices[i];
}
for (int i = 0; i < kNumStages; ++i) {
fStages[i].restoreTo(&drawState->fStages[i]);
}
@ -1199,16 +1105,6 @@ public:
if (fRenderTarget != state.fRenderTarget.get() || fCommon != state.fCommon) {
return false;
}
for (int i = 0; i < kAttribIndexCount; ++i) {
if ((i == kPosition_AttribIndex ||
state.fCommon.fAttribBindings & kAttribIndexMasks[i]) &&
fAttribIndices[i] != state.fAttribIndices[i]) {
return false;
}
}
if (fVertexAttribs != state.fVertexAttribs) {
return false;
}
for (int i = 0; i < kNumStages; ++i) {
if (!fStages[i].isEqual(state.fStages[i])) {
return false;
@ -1220,22 +1116,15 @@ public:
private:
GrRenderTarget* fRenderTarget;
CommonState fCommon;
int fAttribIndices[kAttribIndexCount];
GrVertexAttribArray<kVertexAttribCnt> fVertexAttribs;
GrEffectStage::DeferredStage fStages[kNumStages];
GR_DEBUGCODE(bool fInitialized;)
};
private:
// helper array to let us check the current bindings so we know what bound attrib indices
// we care about
static const GrAttribBindings kAttribIndexMasks[kAttribIndexCount];
SkAutoTUnref<GrRenderTarget> fRenderTarget;
CommonState fCommon;
int fAttribIndices[kAttribIndexCount];
GrVertexAttribArray<kVertexAttribCnt> fVertexAttribs;
GrEffectStage fStages[kNumStages];
typedef GrRefCnt INHERITED;

View File

@ -615,18 +615,15 @@ void GrDrawTarget::drawRect(const GrRect& rect,
const SkMatrix* matrix,
const GrRect* localRect,
const SkMatrix* localMatrix) {
GrAttribBindings bindings = 0;
// position + (optional) texture coord
static const GrVertexAttrib kAttribs[] = {
{kVec2f_GrVertexAttribType, 0},
{kVec2f_GrVertexAttribType, sizeof(GrPoint)}
{kVec2f_GrVertexAttribType, 0, kPosition_GrVertexAttribBinding},
{kVec2f_GrVertexAttribType, sizeof(GrPoint), kLocalCoord_GrVertexAttribBinding}
};
int attribCount = 1;
if (NULL != localRect) {
bindings |= GrDrawState::kLocalCoords_AttribBindingsBit;
attribCount = 2;
this->drawState()->setAttribIndex(GrDrawState::kLocalCoords_AttribIndex, 1);
}
GrDrawState::AutoViewMatrixRestore avmr;
@ -635,8 +632,6 @@ void GrDrawTarget::drawRect(const GrRect& rect,
}
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");

View File

@ -77,22 +77,21 @@ void GrInOrderDrawBuffer::drawRect(const GrRect& rect,
const SkMatrix* matrix,
const GrRect* localRect,
const SkMatrix* localMatrix) {
GrAttribBindings bindings = GrDrawState::kDefault_AttribBindings;
GrDrawState::AutoColorRestore acr;
GrDrawState* drawState = this->drawState();
GrColor color = drawState->getColor();
GrVertexAttribArray<3> attribs;
size_t currentOffset = 0;
int colorOffset = -1, localOffset = -1;
// set position attrib
drawState->setAttribIndex(GrDrawState::kPosition_AttribIndex, attribs.count());
GrVertexAttrib currAttrib = {kVec2f_GrVertexAttribType, currentOffset};
attribs.push_back(currAttrib);
currentOffset += sizeof(GrPoint);
static const GrVertexAttrib kPosAttrib =
{kVec2f_GrVertexAttribType, 0, kPosition_GrVertexAttribBinding};
attribs.push_back(kPosAttrib);
size_t currentOffset = sizeof(GrPoint);
int colorOffset = -1;
int localOffset = -1;
// Using per-vertex colors allows batching across colors. (A lot of rects in a row differing
// only in color is a common occurrence in tables). However, having per-vertex colors disables
@ -100,13 +99,11 @@ void GrInOrderDrawBuffer::drawRect(const GrRect& rect,
// optimizations help determine whether coverage and color can be blended correctly when
// 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->caps()->dualSourceBlendingSupport() ||
drawState->hasSolidCoverage(drawState->getAttribBindings())) {
bindings |= GrDrawState::kColor_AttribBindingsBit;
drawState->setAttribIndex(GrDrawState::kColor_AttribIndex, attribs.count());
currAttrib.set(kVec4ub_GrVertexAttribType, currentOffset);
attribs.push_back(currAttrib);
if (this->caps()->dualSourceBlendingSupport() || drawState->hasSolidCoverage()) {
colorOffset = currentOffset;
GrVertexAttrib colorAttrib =
{kVec4ub_GrVertexAttribType, colorOffset, kColor_GrVertexAttribBinding};
attribs.push_back(colorAttrib);
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
@ -116,16 +113,14 @@ void GrInOrderDrawBuffer::drawRect(const GrRect& rect,
}
if (NULL != localRect) {
bindings |= GrDrawState::kLocalCoords_AttribBindingsBit;
drawState->setAttribIndex(GrDrawState::kLocalCoords_AttribIndex, attribs.count());
currAttrib.set(kVec2f_GrVertexAttribType, currentOffset);
attribs.push_back(currAttrib);
localOffset = currentOffset;
GrVertexAttrib localCoordAttrib =
{kVec2f_GrVertexAttribType, localOffset, kLocalCoord_GrVertexAttribBinding};
attribs.push_back(localCoordAttrib);
currentOffset += sizeof(GrPoint);
}
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");

View File

@ -85,11 +85,10 @@ void GrOvalRenderer::drawCircle(GrDrawTarget* target,
// position + edge
static const GrVertexAttrib kVertexAttribs[] = {
{kVec2f_GrVertexAttribType, 0},
{kVec4f_GrVertexAttribType, sizeof(GrPoint)}
{kVec2f_GrVertexAttribType, 0, kPosition_GrVertexAttribBinding},
{kVec4f_GrVertexAttribType, sizeof(GrPoint), kEffect_GrVertexAttribBinding}
};
drawState->setVertexAttribs(kVertexAttribs, SK_ARRAY_COUNT(kVertexAttribs));
drawState->setAttribIndex(GrDrawState::kPosition_AttribIndex, 0);
GrAssert(sizeof(CircleVertex) == drawState->getVertexSize());
GrDrawTarget::AutoReleaseGeometry geo(target, 4, 0);
@ -108,7 +107,6 @@ void GrOvalRenderer::drawCircle(GrDrawTarget* target,
// (kPathMaskStage in GrSWMaskHelper)
kEdgeEffectStage = GrPaint::kTotalStages,
};
drawState->setAttribBindings(GrDrawState::kDefault_AttribBindings);
GrEffectRef* effect = GrCircleEdgeEffect::Create(isStroked);
static const int kCircleEdgeAttrIndex = 1;
@ -185,12 +183,11 @@ void GrOvalRenderer::drawEllipse(GrDrawTarget* target,
// position + edge
static const GrVertexAttrib kVertexAttribs[] = {
{kVec2f_GrVertexAttribType, 0},
{kVec2f_GrVertexAttribType, sizeof(GrPoint)},
{kVec4f_GrVertexAttribType, 2*sizeof(GrPoint)}
{kVec2f_GrVertexAttribType, 0, kPosition_GrVertexAttribBinding},
{kVec2f_GrVertexAttribType, sizeof(GrPoint), kEffect_GrVertexAttribBinding},
{kVec4f_GrVertexAttribType, 2*sizeof(GrPoint), kEffect_GrVertexAttribBinding}
};
drawState->setVertexAttribs(kVertexAttribs, SK_ARRAY_COUNT(kVertexAttribs));
drawState->setAttribIndex(GrDrawState::kPosition_AttribIndex, 0);
GrAssert(sizeof(EllipseVertex) == drawState->getVertexSize());
GrDrawTarget::AutoReleaseGeometry geo(target, 4, 0);
@ -209,7 +206,6 @@ void GrOvalRenderer::drawEllipse(GrDrawTarget* target,
// (kPathMaskStage in GrSWMaskHelper)
kEdgeEffectStage = GrPaint::kTotalStages,
};
drawState->setAttribBindings(GrDrawState::kDefault_AttribBindings);
GrEffectRef* effect = GrEllipseEdgeEffect::Create(isStroked);
static const int kEllipseCenterAttrIndex = 1;

View File

@ -194,10 +194,9 @@ HAS_ATLAS:
if (NULL == fVertices) {
// position + texture coord
static const GrVertexAttrib kVertexAttribs[] = {
{kVec2f_GrVertexAttribType, 0},
{kVec2f_GrVertexAttribType, sizeof(GrPoint)}
{kVec2f_GrVertexAttribType, 0, kPosition_GrVertexAttribBinding},
{kVec2f_GrVertexAttribType, sizeof(GrPoint), kEffect_GrVertexAttribBinding}
};
static const GrAttribBindings kAttribBindings = 0;
// If we need to reserve vertices allow the draw target to suggest
// a number of verts to reserve and whether to perform a flush.
@ -215,8 +214,6 @@ HAS_ATLAS:
fDrawTarget = fContext->getTextTarget(fPaint);
fDrawTarget->drawState()->setVertexAttribs(kVertexAttribs, SK_ARRAY_COUNT(kVertexAttribs));
}
fDrawTarget->drawState()->setAttribIndex(GrDrawState::kPosition_AttribIndex, 0);
fDrawTarget->drawState()->setAttribBindings(kAttribBindings);
fMaxVertices = kDefaultRequestedVerts;
// ignore return, no point in flushing again.
fDrawTarget->geometryHints(&fMaxVertices, NULL);

View File

@ -705,14 +705,17 @@ bool GrGLProgram::bindOutputsAttribsAndLinkProgram(const GrGLShaderBuilder& buil
GL_CALL(BindAttribLocation(fProgramID,
fDesc.fPositionAttributeIndex,
builder.positionAttribute().c_str()));
GL_CALL(BindAttribLocation(fProgramID, fDesc.fColorAttributeIndex, COL_ATTR_NAME));
GL_CALL(BindAttribLocation(fProgramID, fDesc.fCoverageAttributeIndex, COV_ATTR_NAME));
if (fDesc.fAttribBindings & GrDrawState::kLocalCoords_AttribBindingsBit) {
if (-1 != fDesc.fLocalCoordAttributeIndex) {
GL_CALL(BindAttribLocation(fProgramID,
fDesc.fLocalCoordsAttributeIndex,
fDesc.fLocalCoordAttributeIndex,
builder.localCoordsAttribute().c_str()));
}
if (-1 != fDesc.fColorAttributeIndex) {
GL_CALL(BindAttribLocation(fProgramID, fDesc.fColorAttributeIndex, COL_ATTR_NAME));
}
if (-1 != fDesc.fCoverageAttributeIndex) {
GL_CALL(BindAttribLocation(fProgramID, fDesc.fCoverageAttributeIndex, COV_ATTR_NAME));
}
const GrGLShaderBuilder::AttributePair* attribEnd = builder.getEffectAttributes().end();
for (const GrGLShaderBuilder::AttributePair* attrib = builder.getEffectAttributes().begin();
@ -826,8 +829,7 @@ void GrGLProgram::setData(GrGpuGL* gpu,
const GrEffectStage& stage = drawState.getStage(s);
GrAssert(NULL != stage.getEffect());
bool explicitLocalCoords =
(fDesc.fAttribBindings & GrDrawState::kLocalCoords_AttribBindingsBit);
bool explicitLocalCoords = -1 != fDesc.fLocalCoordAttributeIndex;
GrDrawEffect drawEffect(stage, explicitLocalCoords);
fEffects[s]->setData(fUniformManager, drawEffect);
int numSamplers = fUniformHandles.fEffectSamplerUnis[s].count();
@ -847,15 +849,18 @@ void GrGLProgram::setData(GrGpuGL* gpu,
void GrGLProgram::setColor(const GrDrawState& drawState,
GrColor color,
SharedGLState* sharedState) {
if (!(drawState.getAttribBindings() & GrDrawState::kColor_AttribBindingsBit)) {
if (!drawState.hasColorVertexAttribute()) {
switch (fDesc.fColorInput) {
case GrGLProgramDesc::kAttribute_ColorInput:
if (sharedState->fConstAttribColor != color) {
GrAssert(-1 != fDesc.fColorAttributeIndex);
if (sharedState->fConstAttribColor != color ||
sharedState->fConstAttribColorIndex != fDesc.fColorAttributeIndex) {
// OpenGL ES only supports the float varieties of glVertexAttrib
GrGLfloat c[4];
GrColorToRGBAFloat(color, c);
GL_CALL(VertexAttrib4fv(fDesc.fColorAttributeIndex, c));
sharedState->fConstAttribColor = color;
sharedState->fConstAttribColorIndex = fDesc.fColorAttributeIndex;
}
break;
case GrGLProgramDesc::kUniform_ColorInput:
@ -868,28 +873,34 @@ void GrGLProgram::setColor(const GrDrawState& drawState,
fUniformManager.set4fv(fUniformHandles.fColorUni, 0, 1, c);
fColor = color;
}
sharedState->fConstAttribColorIndex = -1;
break;
case GrGLProgramDesc::kSolidWhite_ColorInput:
case GrGLProgramDesc::kTransBlack_ColorInput:
sharedState->fConstAttribColorIndex = -1;
break;
default:
GrCrash("Unknown color type.");
}
} else {
sharedState->fConstAttribColorIndex = -1;
}
}
void GrGLProgram::setCoverage(const GrDrawState& drawState,
GrColor coverage,
SharedGLState* sharedState) {
if (!(drawState.getAttribBindings() & GrDrawState::kCoverage_AttribBindingsBit)) {
if (!drawState.hasCoverageVertexAttribute()) {
switch (fDesc.fCoverageInput) {
case GrGLProgramDesc::kAttribute_ColorInput:
if (sharedState->fConstAttribCoverage != coverage) {
if (sharedState->fConstAttribCoverage != coverage ||
sharedState->fConstAttribCoverageIndex != fDesc.fCoverageAttributeIndex) {
// OpenGL ES only supports the float varieties of glVertexAttrib
GrGLfloat c[4];
GrColorToRGBAFloat(coverage, c);
GL_CALL(VertexAttrib4fv(fDesc.fCoverageAttributeIndex, c));
sharedState->fConstAttribCoverage = coverage;
sharedState->fConstAttribCoverageIndex = fDesc.fCoverageAttributeIndex;
}
break;
case GrGLProgramDesc::kUniform_ColorInput:
@ -902,13 +913,17 @@ void GrGLProgram::setCoverage(const GrDrawState& drawState,
fUniformManager.set4fv(fUniformHandles.fCoverageUni, 0, 1, c);
fCoverage = coverage;
}
sharedState->fConstAttribCoverageIndex = -1;
break;
case GrGLProgramDesc::kSolidWhite_ColorInput:
case GrGLProgramDesc::kTransBlack_ColorInput:
sharedState->fConstAttribCoverageIndex = -1;
break;
default:
GrCrash("Unknown coverage type.");
}
} else {
sharedState->fConstAttribCoverageIndex = -1;
}
}

View File

@ -60,18 +60,23 @@ public:
GrGLuint programID() const { return fProgramID; }
/**
* 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.
* Some GL state that is relevant to programs is not stored per-program. In particular color
* and coverage attributes can be global state. This struct is read and updated by
* GrGLProgram::setColor and GrGLProgram::setCoverage to allow us to avoid setting this state
* redundantly.
*/
struct SharedGLState {
GrColor fConstAttribColor;
int fConstAttribColorIndex;
GrColor fConstAttribCoverage;
int fConstAttribCoverageIndex;
SharedGLState() { this->invalidate(); }
void invalidate() {
fConstAttribColor = GrColor_ILLEGAL;
fConstAttribColorIndex = -1;
fConstAttribCoverage = GrColor_ILLEGAL;
fConstAttribCoverageIndex = -1;
}
};

View File

@ -34,49 +34,42 @@ void GrGLProgramDesc::Build(const GrDrawState& drawState,
// 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->fAttribBindings = drawState.getAttribBindings();
desc->fEmitsPointSize = isPoints;
bool requiresAttributeColors =
!skipColor && SkToBool(desc->fAttribBindings & GrDrawState::kColor_AttribBindingsBit);
bool requiresAttributeCoverage =
!skipCoverage && SkToBool(desc->fAttribBindings & GrDrawState::kCoverage_AttribBindingsBit);
bool requiresColorAttrib = !skipColor && drawState.hasColorVertexAttribute();
bool requiresCoverageAttrib = !skipCoverage && drawState.hasCoverageVertexAttribute();
// we only need the local coords if we're actually going to generate effect code
bool requiresLocalCoordAttrib = !(skipCoverage && skipColor) &&
drawState.hasLocalCoordAttribute();
// fColorInput/fCoverageInput records how colors are specified for the program so we strip the
// bits from the bindings to avoid false negatives when searching for an existing program in the
// cache.
desc->fAttribBindings &=
~(GrDrawState::kColor_AttribBindingsBit | GrDrawState::kCoverage_AttribBindingsBit);
desc->fColorFilterXfermode = skipColor ? SkXfermode::kDst_Mode : drawState.getColorFilterMode();
// no reason to do edge aa or look at per-vertex coverage if coverage is ignored
if (skipCoverage) {
desc->fAttribBindings &= ~(GrDrawState::kCoverage_AttribBindingsBit);
}
bool colorIsTransBlack = SkToBool(blendOpts & GrDrawState::kEmitTransBlack_BlendOptFlag);
bool colorIsSolidWhite = (blendOpts & GrDrawState::kEmitCoverage_BlendOptFlag) ||
(!requiresAttributeColors && 0xffffffff == drawState.getColor());
(!requiresColorAttrib && 0xffffffff == drawState.getColor());
if (colorIsTransBlack) {
desc->fColorInput = kTransBlack_ColorInput;
} else if (colorIsSolidWhite) {
desc->fColorInput = kSolidWhite_ColorInput;
} else if (GR_GL_NO_CONSTANT_ATTRIBUTES && !requiresAttributeColors) {
} else if (GR_GL_NO_CONSTANT_ATTRIBUTES && !requiresColorAttrib) {
desc->fColorInput = kUniform_ColorInput;
} else {
desc->fColorInput = kAttribute_ColorInput;
}
bool covIsSolidWhite = !requiresAttributeCoverage && 0xffffffff == drawState.getCoverage();
bool covIsSolidWhite = !requiresCoverageAttrib && 0xffffffff == drawState.getCoverage();
if (skipCoverage) {
desc->fCoverageInput = kTransBlack_ColorInput;
} else if (covIsSolidWhite) {
desc->fCoverageInput = kSolidWhite_ColorInput;
} else if (GR_GL_NO_CONSTANT_ATTRIBUTES && !requiresAttributeCoverage) {
} else if (GR_GL_NO_CONSTANT_ATTRIBUTES && !requiresCoverageAttrib) {
desc->fCoverageInput = kUniform_ColorInput;
} else {
desc->fCoverageInput = kAttribute_ColorInput;
@ -92,9 +85,7 @@ void GrGLProgramDesc::Build(const GrDrawState& drawState,
lastEnabledStage = s;
const GrEffectRef& effect = *drawState.getStage(s).getEffect();
const GrBackendEffectFactory& factory = effect->getFactory();
bool explicitLocalCoords = (drawState.getAttribBindings() &
GrDrawState::kLocalCoords_AttribBindingsBit);
GrDrawEffect drawEffect(drawState.getStage(s), explicitLocalCoords);
GrDrawEffect drawEffect(drawState.getStage(s), requiresLocalCoordAttrib);
desc->fEffectKeys[s] = factory.glEffectKey(drawEffect, gpu->glCaps());
if (effect->willReadDst()) {
readsDst = true;
@ -139,7 +130,7 @@ void GrGLProgramDesc::Build(const GrDrawState& drawState,
firstCoverageStage = drawState.getFirstCoverageStage();
hasCoverage = true;
} else {
hasCoverage = requiresAttributeCoverage;
hasCoverage = requiresCoverageAttrib;
}
}
@ -174,38 +165,27 @@ void GrGLProgramDesc::Build(const GrDrawState& drawState,
}
}
desc->fPositionAttributeIndex = drawState.getAttribIndex(GrDrawState::kPosition_AttribIndex);
if (requiresAttributeColors) {
desc->fColorAttributeIndex = drawState.getAttribIndex(GrDrawState::kColor_AttribIndex);
desc->fPositionAttributeIndex = drawState.positionAttributeIndex();
desc->fLocalCoordAttributeIndex = drawState.localCoordAttributeIndex();
// For constant color and coverage we need an attribute with an index beyond those already set
int availableAttributeIndex = drawState.getVertexAttribCount();
if (requiresColorAttrib) {
desc->fColorAttributeIndex = drawState.colorVertexAttributeIndex();
} else if (GrGLProgramDesc::kAttribute_ColorInput == desc->fColorInput) {
GrAssert(availableAttributeIndex < GrDrawState::kMaxVertexAttribCnt);
desc->fColorAttributeIndex = availableAttributeIndex;
availableAttributeIndex++;
} else {
desc->fColorAttributeIndex = GrDrawState::kColorOverrideAttribIndexValue;
}
if (requiresAttributeCoverage) {
desc->fCoverageAttributeIndex = drawState.getAttribIndex(GrDrawState::kCoverage_AttribIndex);
} else {
desc->fCoverageAttributeIndex = GrDrawState::kCoverageOverrideAttribIndexValue;
}
if (desc->fAttribBindings & GrDrawState::kLocalCoords_AttribBindingsBit) {
desc->fLocalCoordsAttributeIndex = drawState.getAttribIndex(GrDrawState::kLocalCoords_AttribIndex);
desc->fColorAttributeIndex = -1;
}
#if GR_DEBUG
// Verify valid vertex attribute state. These assertions should probably be done somewhere
// higher up the callstack
const GrVertexAttrib* vertexAttribs = drawState.getVertexAttribs();
GrAssert(desc->fPositionAttributeIndex < GrDrawState::kVertexAttribCnt);
GrAssert(GrGLAttribTypeToLayout(vertexAttribs[desc->fPositionAttributeIndex].fType).fCount == 2);
if (requiresAttributeColors) {
GrAssert(desc->fColorAttributeIndex < GrDrawState::kVertexAttribCnt);
GrAssert(GrGLAttribTypeToLayout(vertexAttribs[desc->fColorAttributeIndex].fType).fCount == 4);
if (requiresCoverageAttrib) {
desc->fCoverageAttributeIndex = drawState.coverageVertexAttributeIndex();
} else if (GrGLProgramDesc::kAttribute_ColorInput == desc->fCoverageInput) {
GrAssert(availableAttributeIndex < GrDrawState::kMaxVertexAttribCnt);
desc->fCoverageAttributeIndex = availableAttributeIndex;
} else {
desc->fCoverageAttributeIndex = -1;
}
if (requiresAttributeCoverage) {
GrAssert(desc->fCoverageAttributeIndex < GrDrawState::kVertexAttribCnt);
GrAssert(GrGLAttribTypeToLayout(vertexAttribs[desc->fCoverageAttributeIndex].fType).fCount == 4);
}
if (desc->fAttribBindings & GrDrawState::kLocalCoords_AttribBindingsBit) {
GrAssert(desc->fLocalCoordsAttributeIndex < GrDrawState::kVertexAttribCnt);
GrAssert(GrGLAttribTypeToLayout(vertexAttribs[desc->fLocalCoordsAttributeIndex].fType).fCount == 2);
}
#endif
}

View File

@ -39,7 +39,8 @@ public:
void setRandom(SkMWCRandom*,
const GrGpuGL* gpu,
const GrTexture* dummyDstTexture,
const GrEffectStage stages[GrDrawState::kNumStages]);
const GrEffectStage stages[GrDrawState::kNumStages],
int currAttribIndex);
/**
* Builds a program descriptor from a GrDrawState. Whether the primitive type is points, the
@ -76,35 +77,34 @@ private:
kDualSrcOutputCnt
};
// should the FS discard if the coverage is zero (to avoid stencil manipulation)
bool fDiscardIfZeroCoverage;
// stripped of bits that don't affect program generation
GrAttribBindings fAttribBindings;
/** Non-zero if this stage has an effect */
GrGLEffect::EffectKey fEffectKeys[GrDrawState::kNumStages];
// To enable experimental geometry shader code (not for use in
// production)
#if GR_GL_EXPERIMENTAL_GS
bool fExperimentalGS;
#endif
// To enable experimental geometry shader code (not for use in
// production)
#if GR_GL_EXPERIMENTAL_GS
bool fExperimentalGS;
#endif
GrGLShaderBuilder::DstReadKey fDstRead; // set by GrGLShaderBuilder if there
// are effects that must read the dst.
// Otherwise, 0.
// should the FS discard if the coverage is zero (to avoid stencil manipulation)
SkBool8 fDiscardIfZeroCoverage;
uint8_t fColorInput; // casts to enum ColorInput
uint8_t fCoverageInput; // casts to enum ColorInput
uint8_t fDualSrcOutput; // casts to enum DualSrcOutput
int8_t fFirstCoverageStage;
SkBool8 fEmitsPointSize;
uint8_t fColorFilterXfermode; // casts to enum SkXfermode::Mode
int8_t fPositionAttributeIndex;
int8_t fLocalCoordAttributeIndex;
int8_t fColorAttributeIndex;
int8_t fCoverageAttributeIndex;
int8_t fLocalCoordsAttributeIndex;
// GrGLProgram and GrGLShaderBuilder read the private fields to generate code. TODO: Move all
// code generation to GrGLShaderBuilder (and maybe add getters rather than friending).

View File

@ -67,15 +67,6 @@ bool GrGLSLSetupFSColorOuput(GrGLSLGeneration gen, const char* nameIfDeclared, G
return declaredOutput;
}
GrSLType GrSLFloatVectorType (int count) {
GR_STATIC_ASSERT(kFloat_GrSLType == 1);
GR_STATIC_ASSERT(kVec2f_GrSLType == 2);
GR_STATIC_ASSERT(kVec3f_GrSLType == 3);
GR_STATIC_ASSERT(kVec4f_GrSLType == 4);
GrAssert(count > 0 && count <= 4);
return (GrSLType)(count);
}
const char* GrGLSLVectorHomogCoord(int count) {
static const char* HOMOGS[] = {"ERROR", "", ".y", ".z", ".w"};
GrAssert(count >= 1 && count < (int)GR_ARRAY_COUNT(HOMOGS));

View File

@ -117,7 +117,7 @@ GrGLShaderBuilder::GrGLShaderBuilder(const GrGLContextInfo& ctxInfo,
fPositionVar = &fVSAttrs.push_back();
fPositionVar->set(kVec2f_GrSLType, GrGLShaderVar::kAttribute_TypeModifier, "aPosition");
if (desc.fAttribBindings & GrDrawState::kLocalCoords_AttribBindingsBit) {
if (-1 != desc.fLocalCoordAttributeIndex) {
fLocalCoordsVar = &fVSAttrs.push_back();
fLocalCoordsVar->set(kVec2f_GrSLType,
GrGLShaderVar::kAttribute_TypeModifier,

View File

@ -180,9 +180,7 @@ GrGpuGL::GrGpuGL(const GrGLContext& ctx, GrContext* context)
fProgramCache = SkNEW_ARGS(ProgramCache, (this->glContext()));
GrAssert(this->glCaps().maxVertexAttributes() >= GrDrawState::kVertexAttribCnt);
GrAssert(this->glCaps().maxVertexAttributes() > GrDrawState::kColorOverrideAttribIndexValue);
GrAssert(this->glCaps().maxVertexAttributes() > GrDrawState::kCoverageOverrideAttribIndexValue);
GrAssert(this->glCaps().maxVertexAttributes() >= GrDrawState::kMaxVertexAttribCnt);
fLastSuccessfulStencilFmtIdx = 0;
if (false) { // avoid bit rot, suppress warning

View File

@ -77,5 +77,4 @@ void gr_run_unittests() {
GR_DEBUGCODE(test_bsearch();)
test_binHashKey();
GrRedBlackTree<int>::UnitTest();
GrDrawState::VertexAttributesUnitTest();
}

View File

@ -24,18 +24,30 @@
void GrGLProgramDesc::setRandom(SkMWCRandom* random,
const GrGpuGL* gpu,
const GrTexture* dstTexture,
const GrEffectStage stages[GrDrawState::kNumStages]) {
fAttribBindings = 0;
const GrEffectStage stages[GrDrawState::kNumStages],
int currAttribIndex) {
fEmitsPointSize = random->nextBool();
fColorInput = random->nextULessThan(kColorInputCnt);
fCoverageInput = random->nextULessThan(kColorInputCnt);
fPositionAttributeIndex = 0;
// if the effects have used up all off the available attributes,
// don't try to use color or coverage attributes as input
do {
fColorInput = random->nextULessThan(kColorInputCnt);
} while (GrDrawState::kMaxVertexAttribCnt <= currAttribIndex &&
kAttribute_ColorInput == fColorInput);
fColorAttributeIndex = (fColorInput == kAttribute_ColorInput) ? currAttribIndex++ : -1;
do {
fCoverageInput = random->nextULessThan(kColorInputCnt);
} while (GrDrawState::kMaxVertexAttribCnt <= currAttribIndex &&
kAttribute_ColorInput == fCoverageInput);
fCoverageAttributeIndex = (fCoverageInput == kAttribute_ColorInput) ? currAttribIndex++ : -1;
fColorFilterXfermode = random->nextULessThan(SkXfermode::kCoeffModesCnt);
fFirstCoverageStage = random->nextULessThan(GrDrawState::kNumStages);
fAttribBindings |= random->nextBool() ? GrDrawState::kCoverage_AttribBindingsBit : 0;
#if GR_GL_EXPERIMENTAL_GS
fExperimentalGS = gpu->caps()->geometryShaderSupport() && random->nextBool();
#endif
@ -48,18 +60,14 @@ void GrGLProgramDesc::setRandom(SkMWCRandom* random,
fDualSrcOutput = kNone_DualSrcOutput;
}
// use separate tex coords?
if (random->nextBool()) {
fAttribBindings |= GrDrawState::kLocalCoords_AttribBindingsBit;
}
bool useLocalCoords = random->nextBool() && currAttribIndex < GrDrawState::kMaxVertexAttribCnt;
fLocalCoordAttributeIndex = useLocalCoords ? currAttribIndex++ : -1;
bool dstRead = false;
for (int s = 0; s < GrDrawState::kNumStages; ++s) {
if (NULL != stages[s].getEffect()) {
const GrBackendEffectFactory& factory = (*stages[s].getEffect())->getFactory();
bool explicitLocalCoords = (fAttribBindings &
GrDrawState::kLocalCoords_AttribBindingsBit);
GrDrawEffect drawEffect(stages[s], explicitLocalCoords);
GrDrawEffect drawEffect(stages[s], useLocalCoords);
fEffectKeys[s] = factory.glEffectKey(drawEffect, gpu->glCaps());
if ((*stages[s].getEffect())->willReadDst()) {
dstRead = true;
@ -70,22 +78,6 @@ void GrGLProgramDesc::setRandom(SkMWCRandom* random,
if (dstRead) {
this->fDstRead = GrGLShaderBuilder::KeyForDstRead(dstTexture, gpu->glCaps());
}
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::kLocalCoords_AttribBindingsBit) {
fLocalCoordsAttributeIndex = attributeIndex;
++attributeIndex;
}
}
bool GrGpuGL::programUnitTest(int maxStages) {
@ -118,7 +110,7 @@ bool GrGpuGL::programUnitTest(int maxStages) {
GrGLProgramDesc pdesc;
GrEffectStage stages[GrDrawState::kNumStages];
int currAttribIndex = GrDrawState::kAttribIndexCount;
int currAttribIndex = 1; // we need to always leave room for position
int attribIndices[2];
GrTexture* dummyTextures[] = {dummyTexture1.get(), dummyTexture2.get()};
for (int s = 0; s < maxStages; ++s) {
@ -131,10 +123,9 @@ bool GrGpuGL::programUnitTest(int maxStages) {
dummyTextures));
int numAttribs = (*effect)->numVertexAttribs();
// If adding this effect would cause to exceed the max attrib count then generate a
// new random effect. The explanation for why this check is correct is a bit
// convoluted and this code will be removed soon.
if (currAttribIndex + numAttribs > GrDrawState::kCoverageOverrideAttribIndexValue) {
// If adding this effect would exceed the max attrib count then generate a
// new random effect.
if (currAttribIndex + numAttribs > GrDrawState::kMaxVertexAttribCnt) {
--s;
continue;
}
@ -145,8 +136,8 @@ bool GrGpuGL::programUnitTest(int maxStages) {
}
}
const GrTexture* dstTexture = random.nextBool() ? dummyTextures[0] : dummyTextures[1];
pdesc.setRandom(&random, this, dstTexture, stages);
pdesc.setRandom(&random, this, dstTexture, stages, currAttribIndex);
const GrEffectStage* stagePtrs[GrDrawState::kNumStages];
for (int s = 0; s < GrDrawState::kNumStages; ++s) {
stagePtrs[s] = &stages[s];