aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorGravatar joshualitt <joshualitt@chromium.org>2014-10-09 07:25:36 -0700
committerGravatar Commit bot <commit-bot@chromium.org>2014-10-09 07:25:36 -0700
commit651713408c5a5d9565665967ad09981250c7a8c9 (patch)
treeb0e890cd8389dd1ee2876763527f25ef044677a2
parent99d5915a02817659a0eec9f5addfdcf0a03d1aa2 (diff)
gl programs rewrite
-rw-r--r--include/gpu/GrProcessor.h2
-rw-r--r--include/gpu/GrTypes.h4
-rw-r--r--src/effects/SkColorFilters.cpp8
-rw-r--r--src/gpu/GrDrawState.cpp7
-rw-r--r--src/gpu/GrDrawState.h5
-rw-r--r--src/gpu/GrDrawTarget.h15
-rw-r--r--src/gpu/gl/GrGLProgramDesc.cpp150
-rw-r--r--src/gpu/gl/GrGLProgramDesc.h45
-rw-r--r--src/gpu/gl/GrGpuGL_program.cpp18
-rw-r--r--tests/GLProgramsTest.cpp632
10 files changed, 510 insertions, 376 deletions
diff --git a/include/gpu/GrProcessor.h b/include/gpu/GrProcessor.h
index 2dbead1c22..c1755a8954 100644
--- a/include/gpu/GrProcessor.h
+++ b/include/gpu/GrProcessor.h
@@ -42,6 +42,8 @@ public:
uint32_t fValidFlags;
bool fIsSingleComponent;
+ InvariantOutput() : fColor(0), fValidFlags(0), fIsSingleComponent(false) {}
+
bool isOpaque() const {
return ((fValidFlags & kA_GrColorComponentFlag) && 0xFF == GrColorUnpackA(fColor));
}
diff --git a/include/gpu/GrTypes.h b/include/gpu/GrTypes.h
index 22b2e224f6..1f5f9179b9 100644
--- a/include/gpu/GrTypes.h
+++ b/include/gpu/GrTypes.h
@@ -222,8 +222,10 @@ enum GrBlendCoeff {
kConstA_GrBlendCoeff, //<! constant color alpha
kIConstA_GrBlendCoeff, //<! one minus constant color alpha
- kPublicGrBlendCoeffCount
+ kFirstPublicGrBlendCoeff = kZero_GrBlendCoeff,
+ kLastPublicGrBlendCoeff = kIConstA_GrBlendCoeff,
};
+static const int kPublicGrBlendCoeffCount = kLastPublicGrBlendCoeff + 1;
/**
* Formats for masks, used by the font cache.
diff --git a/src/effects/SkColorFilters.cpp b/src/effects/SkColorFilters.cpp
index ba62817f56..8e10d73a0e 100644
--- a/src/effects/SkColorFilters.cpp
+++ b/src/effects/SkColorFilters.cpp
@@ -406,7 +406,13 @@ GrFragmentProcessor* ModeColorFilterEffect::TestCreate(SkRandom* rand,
while (SkXfermode::kDst_Mode == mode) {
mode = static_cast<SkXfermode::Mode>(rand->nextRangeU(0, SkXfermode::kLastCoeffMode));
}
- GrColor color = rand->nextU();
+
+ // pick a random premul color
+ uint8_t alpha = rand->nextULessThan(256);
+ GrColor color = GrColorPackRGBA(rand->nextRangeU(0, alpha),
+ rand->nextRangeU(0, alpha),
+ rand->nextRangeU(0, alpha),
+ alpha);
return ModeColorFilterEffect::Create(color, mode);
}
diff --git a/src/gpu/GrDrawState.cpp b/src/gpu/GrDrawState.cpp
index 6831fad1f9..5e177b8b12 100644
--- a/src/gpu/GrDrawState.cpp
+++ b/src/gpu/GrDrawState.cpp
@@ -404,7 +404,7 @@ bool GrDrawState::hasSolidCoverage() const {
if (this->hasCoverageVertexAttribute()) {
inout.fValidFlags = 0;
} else {
- inout.fColor = fCoverage;
+ inout.fColor = this->getCoverageColor();
inout.fValidFlags = kRGBA_GrColorComponentFlags;
}
@@ -413,6 +413,7 @@ bool GrDrawState::hasSolidCoverage() const {
const GrGeometryProcessor* gp = fGeometryProcessor->getProcessor();
gp->computeInvariantOutput(&inout);
}
+
for (int s = 0; s < this->numCoverageStages(); ++s) {
const GrProcessor* processor = this->getCoverageStage(s).getProcessor();
processor->computeInvariantOutput(&inout);
@@ -640,8 +641,8 @@ GrDrawState::~GrDrawState() {
////////////////////////////////////////////////////////////////////////////////
GrDrawState::BlendOptFlags GrDrawState::getBlendOpts(bool forceCoverage,
- GrBlendCoeff* srcCoeff,
- GrBlendCoeff* dstCoeff) const {
+ GrBlendCoeff* srcCoeff,
+ GrBlendCoeff* dstCoeff) const {
GrBlendCoeff bogusSrcCoeff, bogusDstCoeff;
if (NULL == srcCoeff) {
srcCoeff = &bogusSrcCoeff;
diff --git a/src/gpu/GrDrawState.h b/src/gpu/GrDrawState.h
index 5575b12966..03af7b532f 100644
--- a/src/gpu/GrDrawState.h
+++ b/src/gpu/GrDrawState.h
@@ -684,7 +684,10 @@ public:
/// Hints that when provided can enable optimizations.
////
- enum Hints { kVertexColorsAreOpaque_Hint = 0x1, };
+ enum Hints {
+ kVertexColorsAreOpaque_Hint = 0x1,
+ kLast_Hint = kVertexColorsAreOpaque_Hint
+ };
void setHint(Hints hint, bool value) { fHints = value ? (fHints | hint) : (fHints & ~hint); }
diff --git a/src/gpu/GrDrawTarget.h b/src/gpu/GrDrawTarget.h
index dd2224bdbd..552314bca3 100644
--- a/src/gpu/GrDrawTarget.h
+++ b/src/gpu/GrDrawTarget.h
@@ -855,6 +855,14 @@ protected:
GrDeviceCoordTexture fDstCopy;
};
+ // Makes a copy of the dst if it is necessary for the draw. Returns false if a copy is required
+ // but couldn't be made. Otherwise, returns true. This method needs to be protected because it
+ // needs to be accessed by GLPrograms to setup a correct drawstate
+ bool setupDstReadIfNecessary(DrawInfo* info) {
+ return this->setupDstReadIfNecessary(&info->fDstCopy, info->getDevBounds());
+ }
+ bool setupDstReadIfNecessary(GrDeviceCoordTexture* dstCopy, const SkRect* drawBounds);
+
private:
// A subclass can optionally overload this function to be notified before
// vertex and index space is reserved.
@@ -913,13 +921,6 @@ private:
void releasePreviousVertexSource();
void releasePreviousIndexSource();
- // Makes a copy of the dst if it is necessary for the draw. Returns false if a copy is required
- // but couldn't be made. Otherwise, returns true.
- bool setupDstReadIfNecessary(DrawInfo* info) {
- return this->setupDstReadIfNecessary(&info->fDstCopy, info->getDevBounds());
- }
- bool setupDstReadIfNecessary(GrDeviceCoordTexture* dstCopy, const SkRect* drawBounds);
-
// Check to see if this set of draw commands has been sent out
virtual bool isIssued(uint32_t drawID) { return true; }
diff --git a/src/gpu/gl/GrGLProgramDesc.cpp b/src/gpu/gl/GrGLProgramDesc.cpp
index ec09527182..0c85c99a8a 100644
--- a/src/gpu/gl/GrGLProgramDesc.cpp
+++ b/src/gpu/gl/GrGLProgramDesc.cpp
@@ -140,11 +140,11 @@ static uint32_t* get_processor_meta_key(const GrProcessorStage& processorStage,
return key;
}
-bool GrGLProgramDesc::GetProcessorKey(const GrProcessorStage& stage,
- const GrGLCaps& caps,
- bool useExplicitLocalCoords,
- GrProcessorKeyBuilder* b,
- uint16_t* processorKeySize) {
+static bool get_fp_key(const GrProcessorStage& stage,
+ const GrGLCaps& caps,
+ bool useExplicitLocalCoords,
+ GrProcessorKeyBuilder* b,
+ uint16_t* processorKeySize) {
const GrProcessor& effect = *stage.getProcessor();
const GrBackendProcessorFactory& factory = effect.getFactory();
factory.getGLProcessorKey(effect, caps, b);
@@ -160,11 +160,11 @@ bool GrGLProgramDesc::GetProcessorKey(const GrProcessorStage& stage,
return true;
}
-bool GrGLProgramDesc::GetGeometryProcessorKey(const GrGeometryStage& stage,
- const GrGLCaps& caps,
- bool useExplicitLocalCoords,
- GrProcessorKeyBuilder* b,
- uint16_t* processorKeySize) {
+static bool get_gp_key(const GrGeometryStage& stage,
+ const GrGLCaps& caps,
+ bool useExplicitLocalCoords,
+ GrProcessorKeyBuilder* b,
+ uint16_t* processorKeySize) {
const GrProcessor& effect = *stage.getProcessor();
const GrBackendProcessorFactory& factory = effect.getFactory();
factory.getGLProcessorKey(effect, caps, b);
@@ -191,6 +191,54 @@ bool GrGLProgramDesc::GetGeometryProcessorKey(const GrGeometryStage& stage,
return true;
}
+struct GeometryProcessorKeyBuilder {
+ typedef GrGeometryStage StagedProcessor;
+ static bool GetProcessorKey(const GrGeometryStage& gpStage,
+ const GrGLCaps& caps,
+ bool requiresLocalCoordAttrib,
+ GrProcessorKeyBuilder* b,
+ uint16_t* processorKeySize) {
+ return get_gp_key(gpStage, caps, requiresLocalCoordAttrib, b, processorKeySize);
+ }
+};
+
+struct FragmentProcessorKeyBuilder {
+ typedef GrFragmentStage StagedProcessor;
+ static bool GetProcessorKey(const GrFragmentStage& fpStage,
+ const GrGLCaps& caps,
+ bool requiresLocalCoordAttrib,
+ GrProcessorKeyBuilder* b,
+ uint16_t* processorKeySize) {
+ return get_fp_key(fpStage, caps, requiresLocalCoordAttrib, b, processorKeySize);
+ }
+};
+
+
+template <class ProcessorKeyBuilder>
+bool
+GrGLProgramDesc::BuildStagedProcessorKey(const typename ProcessorKeyBuilder::StagedProcessor& stage,
+ const GrGLCaps& caps,
+ bool requiresLocalCoordAttrib,
+ GrGLProgramDesc* desc,
+ int* offsetAndSizeIndex) {
+ GrProcessorKeyBuilder b(&desc->fKey);
+ uint16_t processorKeySize;
+ uint32_t processorOffset = desc->fKey.count();
+ if (processorOffset > SK_MaxU16 ||
+ !ProcessorKeyBuilder::GetProcessorKey(stage, caps, requiresLocalCoordAttrib, &b,
+ &processorKeySize)){
+ desc->fKey.reset();
+ return false;
+ }
+
+ uint16_t* offsetAndSize =
+ reinterpret_cast<uint16_t*>(desc->fKey.begin() + kEffectKeyOffsetsAndLengthOffset +
+ *offsetAndSizeIndex * 2 * sizeof(uint16_t));
+ offsetAndSize[0] = SkToU16(processorOffset);
+ offsetAndSize[1] = processorKeySize;
+ ++(*offsetAndSizeIndex);
+ return true;
+}
bool GrGLProgramDesc::Build(const GrOptDrawState& optState,
GrGpu::DrawType drawType,
@@ -224,90 +272,51 @@ bool GrGLProgramDesc::Build(const GrOptDrawState& optState,
int offsetAndSizeIndex = 0;
- KeyHeader* header = desc->header();
- // make sure any padding in the header is zeroed.
- memset(desc->header(), 0, kHeaderSize);
-
// We can only have one effect which touches the vertex shader
if (optState.hasGeometryProcessor()) {
- uint16_t* offsetAndSize =
- reinterpret_cast<uint16_t*>(desc->fKey.begin() + kEffectKeyOffsetsAndLengthOffset +
- offsetAndSizeIndex * 2 * sizeof(uint16_t));
-
- GrProcessorKeyBuilder b(&desc->fKey);
- uint16_t processorKeySize;
- uint32_t processorOffset = desc->fKey.count();
const GrGeometryStage& gpStage = *optState.getGeometryProcessor();
- if (processorOffset > SK_MaxU16 ||
- !GetGeometryProcessorKey(gpStage, gpu->glCaps(), requiresLocalCoordAttrib, &b,
- &processorKeySize)) {
- desc->fKey.reset();
+ if (!BuildStagedProcessorKey<GeometryProcessorKeyBuilder>(gpStage,
+ gpu->glCaps(),
+ requiresLocalCoordAttrib,
+ desc,
+ &offsetAndSizeIndex)) {
return false;
}
-
- offsetAndSize[0] = SkToU16(processorOffset);
- offsetAndSize[1] = processorKeySize;
- ++offsetAndSizeIndex;
*geometryProcessor = &gpStage;
- header->fHasGeometryProcessor = true;
}
for (int s = 0; s < optState.numColorStages(); ++s) {
- uint16_t* offsetAndSize =
- reinterpret_cast<uint16_t*>(desc->fKey.begin() + kEffectKeyOffsetsAndLengthOffset +
- offsetAndSizeIndex * 2 * sizeof(uint16_t));
-
- GrProcessorKeyBuilder b(&desc->fKey);
- uint16_t processorKeySize;
- uint32_t processorOffset = desc->fKey.count();
- if (processorOffset > SK_MaxU16 ||
- !GetProcessorKey(optState.getColorStage(s), gpu->glCaps(),
- requiresLocalCoordAttrib, &b, &processorKeySize)) {
- desc->fKey.reset();
+ if (!BuildStagedProcessorKey<FragmentProcessorKeyBuilder>(optState.getColorStage(s),
+ gpu->glCaps(),
+ requiresLocalCoordAttrib,
+ desc,
+ &offsetAndSizeIndex)) {
return false;
}
-
- offsetAndSize[0] = SkToU16(processorOffset);
- offsetAndSize[1] = processorKeySize;
- ++offsetAndSizeIndex;
}
for (int s = 0; s < optState.numCoverageStages(); ++s) {
- uint16_t* offsetAndSize =
- reinterpret_cast<uint16_t*>(desc->fKey.begin() + kEffectKeyOffsetsAndLengthOffset +
- offsetAndSizeIndex * 2 * sizeof(uint16_t));
-
- GrProcessorKeyBuilder b(&desc->fKey);
- uint16_t processorKeySize;
- uint32_t processorOffset = desc->fKey.count();
- if (processorOffset > SK_MaxU16 ||
- !GetProcessorKey(optState.getCoverageStage(s), gpu->glCaps(),
- requiresLocalCoordAttrib, &b, &processorKeySize)) {
- desc->fKey.reset();
+ if (!BuildStagedProcessorKey<FragmentProcessorKeyBuilder>(optState.getCoverageStage(s),
+ gpu->glCaps(),
+ requiresLocalCoordAttrib,
+ desc,
+ &offsetAndSizeIndex)) {
return false;
}
-
- offsetAndSize[0] = SkToU16(processorOffset);
- offsetAndSize[1] = processorKeySize;
- ++offsetAndSizeIndex;
}
+ // --------DO NOT MOVE HEADER ABOVE THIS LINE--------------------------------------------------
// Because header is a pointer into the dynamic array, we can't push any new data into the key
// below here.
+ KeyHeader* header = desc->header();
+
+ // make sure any padding in the header is zeroed.
+ memset(header, 0, kHeaderSize);
+ header->fHasGeometryProcessor = optState.hasGeometryProcessor();
header->fEmitsPointSize = GrGpu::kDrawPoints_DrawType == drawType;
- // Currently the experimental GS will only work with triangle prims (and it doesn't do anything
- // other than pass through values from the VS to the FS anyway).
-#if GR_GL_EXPERIMENTAL_GS
-#if 0
- header->fExperimentalGS = gpu->caps().geometryShaderSupport();
-#else
- header->fExperimentalGS = false;
-#endif
-#endif
-
if (gpu->caps()->pathRenderingSupport() &&
GrGpu::IsPathRenderingDrawType(drawType) &&
gpu->glPathRendering()->texturingMode() == GrGLPathRendering::FixedFunction_TexturingMode) {
@@ -399,7 +408,6 @@ bool GrGLProgramDesc::Build(const GrOptDrawState& optState,
header->fColorEffectCnt = colorStages->count();
header->fCoverageEffectCnt = coverageStages->count();
-
desc->finalize();
return true;
}
diff --git a/src/gpu/gl/GrGLProgramDesc.h b/src/gpu/gl/GrGLProgramDesc.h
index faa59f329f..9bf7553b61 100644
--- a/src/gpu/gl/GrGLProgramDesc.h
+++ b/src/gpu/gl/GrGLProgramDesc.h
@@ -15,15 +15,6 @@
class GrGpuGL;
-#ifdef SK_DEBUG
- // Optionally compile the experimental GS code. Set to SK_DEBUG so that debug build bots will
- // execute the code.
- #define GR_GL_EXPERIMENTAL_GS 1
-#else
- #define GR_GL_EXPERIMENTAL_GS 0
-#endif
-
-
/** This class describes a program to generate. It also serves as a program cache key. Very little
of this is GL-specific. The GL-specific parts could be factored out into a subclass. */
class GrGLProgramDesc {
@@ -44,18 +35,6 @@ public:
// Gets the a checksum of the key. Can be used as a hash value for a fast lookup in a cache.
uint32_t getChecksum() const { return *this->atOffset<uint32_t, kChecksumOffset>(); }
- // For unit testing.
- bool setRandom(SkRandom*,
- GrGpuGL*,
- const GrRenderTarget* dummyDstRenderTarget,
- const GrTexture* dummyDstCopyTexture,
- const GrGeometryStage* geometryProcessor,
- const GrFragmentStage* stages[],
- int numColorStages,
- int numCoverageStages,
- int currAttribIndex,
- GrGpu::DrawType);
-
/**
* Builds a program descriptor from a GrOptDrawState. Whether the primitive type is points, and
* the caps of the GrGpuGL are also inputs. It also outputs the color and coverage stages
@@ -129,13 +108,6 @@ private:
GrOptDrawState::PrimaryOutputType fPrimaryOutputType : 8;
GrOptDrawState::SecondaryOutputType fSecondaryOutputType : 8;
-
- // To enable experimental geometry shader code (not for use in
- // production)
-#if GR_GL_EXPERIMENTAL_GS
- SkBool8 fExperimentalGS;
-#endif
-
int8_t fPositionAttributeIndex;
int8_t fLocalCoordAttributeIndex;
int8_t fColorAttributeIndex;
@@ -176,18 +148,13 @@ private:
KeyHeader* header() { return this->atOffset<KeyHeader, kHeaderOffset>(); }
- // Shared code between setRandom() and Build().
- static bool GetProcessorKey(const GrProcessorStage& stage,
- const GrGLCaps& caps,
- bool useExplicitLocalCoords,
- GrProcessorKeyBuilder* b,
- uint16_t* effectKeySize);
-
- static bool GetGeometryProcessorKey(const GrGeometryStage& stage,
+ // a helper class to handle getting an individual processor's key
+ template <class ProcessorKeyBuilder>
+ static bool BuildStagedProcessorKey(const typename ProcessorKeyBuilder::StagedProcessor& stage,
const GrGLCaps& caps,
- bool useExplicitLocalCoords,
- GrProcessorKeyBuilder* b,
- uint16_t* effectKeySize);
+ bool requiresLocalCoordAttrib,
+ GrGLProgramDesc* desc,
+ int* offsetAndSizeIndex);
void finalize();
const KeyHeader& getHeader() const { return *this->atOffset<KeyHeader, kHeaderOffset>(); }
diff --git a/src/gpu/gl/GrGpuGL_program.cpp b/src/gpu/gl/GrGpuGL_program.cpp
index 891b49a1f8..7dba5316a4 100644
--- a/src/gpu/gl/GrGpuGL_program.cpp
+++ b/src/gpu/gl/GrGpuGL_program.cpp
@@ -242,15 +242,15 @@ bool GrGpuGL::flushGraphicsState(DrawType type, const GrDeviceCoordTexture* dstC
SkSTArray<8, const GrFragmentStage*, true> coverageStages;
GrGLProgramDesc desc;
if (!GrGLProgramDesc::Build(*optState.get(),
- type,
- srcCoeff,
- dstCoeff,
- this,
- dstCopy,
- &geometryProcessor,
- &colorStages,
- &coverageStages,
- &desc)) {
+ type,
+ srcCoeff,
+ dstCoeff,
+ this,
+ dstCopy,
+ &geometryProcessor,
+ &colorStages,
+ &coverageStages,
+ &desc)) {
SkDEBUGFAIL("Failed to generate GL program descriptor");
return false;
}
diff --git a/tests/GLProgramsTest.cpp b/tests/GLProgramsTest.cpp
index c31aa1e0da..4d1c59734b 100644
--- a/tests/GLProgramsTest.cpp
+++ b/tests/GLProgramsTest.cpp
@@ -12,7 +12,7 @@
#if SK_SUPPORT_GPU && SK_ALLOW_STATIC_GLOBAL_INITIALIZERS
-#include "GrBackendProcessorFactory.h"
+#include "GrTBackendProcessorFactory.h"
#include "GrContextFactory.h"
#include "GrOptDrawState.h"
#include "effects/GrConfigConversionEffect.h"
@@ -23,180 +23,122 @@
#include "SkRandom.h"
#include "Test.h"
-static void get_stage_stats(const GrFragmentStage stage, bool* readsDst,
- bool* readsFragPosition, bool* requiresVertexShader) {
- if (stage.getProcessor()->willReadDstColor()) {
- *readsDst = true;
- }
- if (stage.getProcessor()->willReadFragmentPosition()) {
- *readsFragPosition = true;
- }
-}
+/*
+ * A dummy effect which just tries to insert a massive key and verify that it can retrieve the
+ * whole thing correctly
+ */
+static const uint32_t kMaxKeySize = 1024;
-bool GrGLProgramDesc::setRandom(SkRandom* random,
- GrGpuGL* gpu,
- const GrRenderTarget* dstRenderTarget,
- const GrTexture* dstCopyTexture,
- const GrGeometryStage* geometryProcessor,
- const GrFragmentStage* stages[],
- int numColorStages,
- int numCoverageStages,
- int currAttribIndex,
- GrGpu::DrawType drawType) {
- bool isPathRendering = GrGpu::IsPathRenderingDrawType(drawType);
- bool useLocalCoords = !isPathRendering &&
- random->nextBool() &&
- currAttribIndex < GrDrawState::kMaxVertexAttribCnt;
-
- int numStages = numColorStages + numCoverageStages;
- fKey.reset();
-
- GR_STATIC_ASSERT(0 == kEffectKeyOffsetsAndLengthOffset % sizeof(uint32_t));
-
- // Make room for everything up to and including the array of offsets to effect keys.
- fKey.push_back_n(kEffectKeyOffsetsAndLengthOffset + 2 * sizeof(uint16_t) * (numStages +
- (geometryProcessor ? 1 : 0)));
-
- bool dstRead = false;
- bool fragPos = false;
- bool vertexShader = SkToBool(geometryProcessor);
- int offset = 0;
- if (geometryProcessor) {
- const GrGeometryStage* stage = geometryProcessor;
- uint16_t* offsetAndSize = reinterpret_cast<uint16_t*>(fKey.begin() +
- kEffectKeyOffsetsAndLengthOffset +
- offset * 2 * sizeof(uint16_t));
- uint32_t effectKeyOffset = fKey.count();
- if (effectKeyOffset > SK_MaxU16) {
- fKey.reset();
- return false;
- }
- GrProcessorKeyBuilder b(&fKey);
- uint16_t effectKeySize;
- if (!GetProcessorKey(*stage, gpu->glCaps(), useLocalCoords, &b, &effectKeySize)) {
- fKey.reset();
- return false;
- }
- vertexShader = true;
- fragPos = stage->getProcessor()->willReadFragmentPosition();
- offsetAndSize[0] = effectKeyOffset;
- offsetAndSize[1] = effectKeySize;
- offset++;
- }
+class GLBigKeyProcessor;
- for (int s = 0; s < numStages; ++s, ++offset) {
- const GrFragmentStage* stage = stages[s];
- uint16_t* offsetAndSize = reinterpret_cast<uint16_t*>(fKey.begin() +
- kEffectKeyOffsetsAndLengthOffset +
- offset * 2 * sizeof(uint16_t));
- uint32_t effectKeyOffset = fKey.count();
- if (effectKeyOffset > SK_MaxU16) {
- fKey.reset();
- return false;
- }
- GrProcessorKeyBuilder b(&fKey);
- uint16_t effectKeySize;
- if (!GetProcessorKey(*stages[s], gpu->glCaps(), useLocalCoords, &b, &effectKeySize)) {
- fKey.reset();
- return false;
- }
- get_stage_stats(*stage, &dstRead, &fragPos, &vertexShader);
- offsetAndSize[0] = effectKeyOffset;
- offsetAndSize[1] = effectKeySize;
+class BigKeyProcessor : public GrFragmentProcessor {
+public:
+ static GrFragmentProcessor* Create() {
+ GR_CREATE_STATIC_FRAGMENT_PROCESSOR(gBigKeyProcessor, BigKeyProcessor, ())
+ return SkRef(gBigKeyProcessor);
}
- KeyHeader* header = this->header();
- memset(header, 0, kHeaderSize);
- header->fEmitsPointSize = random->nextBool();
+ static const char* Name() { return "Big ol' Key"; }
- header->fPositionAttributeIndex = 0;
+ virtual const GrBackendFragmentProcessorFactory& getFactory() const SK_OVERRIDE {
+ return GrTBackendFragmentProcessorFactory<BigKeyProcessor>::getInstance();
+ }
- // if the effects have used up all off the available attributes,
- // don't try to use color or coverage attributes as input
- do {
- header->fColorInput = static_cast<GrGLProgramDesc::ColorInput>(
- random->nextULessThan(kColorInputCnt));
- } while ((GrDrawState::kMaxVertexAttribCnt <= currAttribIndex || isPathRendering) &&
- kAttribute_ColorInput == header->fColorInput);
- header->fColorAttributeIndex = (header->fColorInput == kAttribute_ColorInput) ?
- currAttribIndex++ :
- -1;
+ typedef GLBigKeyProcessor GLProcessor;
- do {
- header->fCoverageInput = static_cast<GrGLProgramDesc::ColorInput>(
- random->nextULessThan(kColorInputCnt));
- } while ((GrDrawState::kMaxVertexAttribCnt <= currAttribIndex || isPathRendering) &&
- kAttribute_ColorInput == header->fCoverageInput);
- header->fCoverageAttributeIndex = (header->fCoverageInput == kAttribute_ColorInput) ?
- currAttribIndex++ :
- -1;
- bool useGS = random->nextBool();
-#if GR_GL_EXPERIMENTAL_GS
- header->fExperimentalGS = gpu->caps()->geometryShaderSupport() && useGS;
-#else
- (void) useGS;
-#endif
+private:
+ BigKeyProcessor() { }
+ virtual bool onIsEqual(const GrProcessor&) const SK_OVERRIDE { return true; }
+ virtual void onComputeInvariantOutput(InvariantOutput* inout) const SK_OVERRIDE { }
- header->fLocalCoordAttributeIndex = useLocalCoords ? currAttribIndex++ : -1;
+ GR_DECLARE_FRAGMENT_PROCESSOR_TEST;
- header->fColorEffectCnt = numColorStages;
- header->fCoverageEffectCnt = numCoverageStages;
+ typedef GrFragmentProcessor INHERITED;
+};
- if (dstRead) {
- header->fDstReadKey = SkToU8(GrGLFragmentShaderBuilder::KeyForDstRead(dstCopyTexture,
- gpu->glCaps()));
- } else {
- header->fDstReadKey = 0;
- }
- if (fragPos) {
- header->fFragPosKey = SkToU8(GrGLFragmentShaderBuilder::KeyForFragmentPosition(dstRenderTarget,
- gpu->glCaps()));
- } else {
- header->fFragPosKey = 0;
- }
+GR_DEFINE_FRAGMENT_PROCESSOR_TEST(BigKeyProcessor);
- header->fUseFragShaderOnly = isPathRendering && gpu->glPathRendering()->texturingMode() ==
- GrGLPathRendering::FixedFunction_TexturingMode;
- header->fHasGeometryProcessor = vertexShader;
+GrFragmentProcessor* BigKeyProcessor::TestCreate(SkRandom*,
+ GrContext*,
+ const GrDrawTargetCaps&,
+ GrTexture*[]) {
+ return BigKeyProcessor::Create();
+}
- GrOptDrawState::PrimaryOutputType primaryOutput;
- GrOptDrawState::SecondaryOutputType secondaryOutput;
- if (!dstRead) {
- primaryOutput = GrOptDrawState::kModulate_PrimaryOutputType;
- } else {
- primaryOutput = static_cast<GrOptDrawState::PrimaryOutputType>(
- random->nextULessThan(GrOptDrawState::kPrimaryOutputTypeCnt));
+class GLBigKeyProcessor : public GrGLFragmentProcessor {
+public:
+ GLBigKeyProcessor(const GrBackendProcessorFactory& factory, const GrProcessor&)
+ : INHERITED(factory) {}
+
+ virtual void emitCode(GrGLProgramBuilder* builder,
+ const GrFragmentProcessor& fp,
+ const GrProcessorKey& key,
+ const char* outputColor,
+ const char* inputColor,
+ const TransformedCoordsArray&,
+ const TextureSamplerArray&) {
+ for (uint32_t i = 0; i < kMaxKeySize; i++) {
+ SkASSERT(key.get32(i) == i);
+ }
}
- if (GrOptDrawState::kCombineWithDst_PrimaryOutputType == primaryOutput ||
- !gpu->caps()->dualSourceBlendingSupport()) {
- secondaryOutput = GrOptDrawState::kNone_SecondaryOutputType;
- } else {
- secondaryOutput = static_cast<GrOptDrawState::SecondaryOutputType>(
- random->nextULessThan(GrOptDrawState::kSecondaryOutputTypeCnt));
+ static void GenKey(const GrProcessor& processor, const GrGLCaps&, GrProcessorKeyBuilder* b) {
+ for (uint32_t i = 0; i < kMaxKeySize; i++) {
+ b->add32(i);
+ }
}
- header->fPrimaryOutputType = primaryOutput;
- header->fSecondaryOutputType = secondaryOutput;
+private:
+ typedef GrGLFragmentProcessor INHERITED;
+};
- this->finalize();
- return true;
+/*
+ * Begin test code
+ */
+static const int kRenderTargetHeight = 1;
+static const int kRenderTargetWidth = 1;
+
+static GrRenderTarget* random_render_target(GrGpuGL* gpu,
+ const GrCacheID& cacheId,
+ SkRandom* random) {
+ // setup render target
+ GrTextureParams params;
+ GrTextureDesc texDesc;
+ texDesc.fWidth = kRenderTargetWidth;
+ texDesc.fHeight = kRenderTargetHeight;
+ texDesc.fFlags = kRenderTarget_GrTextureFlagBit;
+ texDesc.fConfig = kRGBA_8888_GrPixelConfig;
+ texDesc.fOrigin = random->nextBool() == true ? kTopLeft_GrSurfaceOrigin :
+ kBottomLeft_GrSurfaceOrigin;
+
+ GrTexture* texture = gpu->getContext()->findAndRefTexture(texDesc, cacheId, &params);
+ if (NULL == texture) {
+ texture = gpu->getContext()->createTexture(&params, texDesc, cacheId, 0, 0);
+ if (NULL == texture) {
+ return NULL;
+ }
+ }
+ return texture->asRenderTarget();
}
// TODO clean this up, we have to do this to test geometry processors but there has got to be
// a better way. In the mean time, we actually fill out these generic vertex attribs below with
// the correct vertex attribs from the GP. We have to ensure, however, we don't try to add more
-// than two attributes.
-GrVertexAttrib genericVertexAttribs[] = {
+// than two attributes. In addition, we 'pad' the below array with GPs up to 6 entries, 4 fixed
+// function vertex attributes and 2 GP custom attributes.
+GrVertexAttrib kGenericVertexAttribs[] = {
{ kVec2f_GrVertexAttribType, 0, kPosition_GrVertexAttribBinding },
{ kVec2f_GrVertexAttribType, 0, kGeometryProcessor_GrVertexAttribBinding },
+ { kVec2f_GrVertexAttribType, 0, kGeometryProcessor_GrVertexAttribBinding },
+ { kVec2f_GrVertexAttribType, 0, kGeometryProcessor_GrVertexAttribBinding },
+ { kVec2f_GrVertexAttribType, 0, kGeometryProcessor_GrVertexAttribBinding },
{ kVec2f_GrVertexAttribType, 0, kGeometryProcessor_GrVertexAttribBinding }
};
/*
* convert sl type to vertexattrib type, not a complete implementation, only use for debugging
*/
-GrVertexAttribType convert_sltype_to_attribtype(GrSLType type) {
+static GrVertexAttribType convert_sltype_to_attribtype(GrSLType type) {
switch (type) {
case kFloat_GrSLType:
return kFloat_GrVertexAttribType;
@@ -211,11 +153,227 @@ GrVertexAttribType convert_sltype_to_attribtype(GrSLType type) {
return kFloat_GrVertexAttribType;
}
}
-// TODO end test hack
+// end test hack
+
+static void setup_random_ff_attribute(GrVertexAttribBinding binding, GrVertexAttribType type,
+ SkRandom* random, int* attribIndex, int* runningStride) {
+ if (random->nextBool()) {
+ kGenericVertexAttribs[*attribIndex].fType = type;
+ kGenericVertexAttribs[*attribIndex].fOffset = *runningStride;
+ kGenericVertexAttribs[*attribIndex].fBinding = binding;
+ *runningStride += GrVertexAttribTypeSize(kGenericVertexAttribs[(*attribIndex)++].fType);
+ }
+}
+static void set_random_gp(GrGpuGL* gpu, SkRandom* random, GrTexture* dummyTextures[]) {
+ GrProgramElementRef<const GrGeometryProcessor> gp(
+ GrProcessorTestFactory<GrGeometryProcessor>::CreateStage(random,
+ gpu->getContext(),
+ *gpu->caps(),
+ dummyTextures));
+ SkASSERT(gp);
+
+ // we have to set dummy vertex attributes, first we setup the fixed function attributes
+ // always leave the position attribute untouched in the array
+ int attribIndex = 1;
+ int runningStride = GrVertexAttribTypeSize(kGenericVertexAttribs[0].fType);
+
+ // local coords
+ setup_random_ff_attribute(kLocalCoord_GrVertexAttribBinding, kVec2f_GrVertexAttribType,
+ random, &attribIndex, &runningStride);
+
+ // color
+ setup_random_ff_attribute(kColor_GrVertexAttribBinding, kVec4f_GrVertexAttribType,
+ random, &attribIndex, &runningStride);
+
+ // coverage
+ setup_random_ff_attribute(kCoverage_GrVertexAttribBinding, kVec4f_GrVertexAttribType,
+ random, &attribIndex, &runningStride);
+
+ // Update the geometry processor attributes
+ const GrGeometryProcessor::VertexAttribArray& v = gp->getVertexAttribs();
+ int numGPAttribs = v.count();
+ SkASSERT(numGPAttribs <= GrGeometryProcessor::kMaxVertexAttribs &&
+ GrGeometryProcessor::kMaxVertexAttribs == 2);
+
+ // we actually can't overflow if kMaxVertexAttribs == 2, but GCC 4.8 wants more proof
+ int maxIndex = SK_ARRAY_COUNT(kGenericVertexAttribs);
+ for (int i = 0; i < numGPAttribs && i + attribIndex < maxIndex; i++) {
+ kGenericVertexAttribs[i + attribIndex].fType =
+ convert_sltype_to_attribtype(v[i].getType());
+ kGenericVertexAttribs[i + attribIndex].fOffset = runningStride;
+ kGenericVertexAttribs[i + attribIndex].fBinding = kGeometryProcessor_GrVertexAttribBinding;
+ runningStride += GrVertexAttribTypeSize(kGenericVertexAttribs[i + attribIndex].fType);
+ }
-bool GrGpuGL::programUnitTest(int maxStages) {
+ // update the vertex attributes with the ds
+ GrDrawState* ds = gpu->drawState();
+ ds->setVertexAttribs<kGenericVertexAttribs>(attribIndex + numGPAttribs, runningStride);
+ ds->setGeometryProcessor(gp);
+}
+
+static void set_random_color_coverage_stages(GrGpuGL* gpu,
+ int maxStages,
+ bool usePathRendering,
+ SkRandom* random,
+ GrTexture* dummyTextures[]) {
+ int numProcs = random->nextULessThan(maxStages + 1);
+ int numColorProcs = random->nextULessThan(numProcs + 1);
+
+ int currTextureCoordSet = 0;
+ for (int s = 0; s < numProcs;) {
+ GrProgramElementRef<GrFragmentProcessor> fp(
+ GrProcessorTestFactory<GrFragmentProcessor>::CreateStage(random,
+ gpu->getContext(),
+ *gpu->caps(),
+ dummyTextures));
+ SkASSERT(fp);
+
+ // don't add dst color reads to coverage stage
+ if (s >= numColorProcs && fp->willReadDstColor()) {
+ continue;
+ }
+
+ // If adding this effect would exceed the max texture coord set count then generate a
+ // new random effect.
+ if (usePathRendering && gpu->glPathRendering()->texturingMode() ==
+ GrGLPathRendering::FixedFunction_TexturingMode) {;
+ int numTransforms = fp->numTransforms();
+ if (currTextureCoordSet + numTransforms >
+ gpu->glCaps().maxFixedFunctionTextureCoords()) {
+ continue;
+ }
+ currTextureCoordSet += numTransforms;
+ }
+
+ // finally add the stage to the correct pipeline in the drawstate
+ GrDrawState* ds = gpu->drawState();
+ if (s < numColorProcs) {
+ ds->addColorProcessor(fp);
+ } else {
+ ds->addCoverageProcessor(fp);
+ }
+ ++s;
+ }
+}
+
+// There are only a few cases of random colors which interest us
+enum ColorMode {
+ kAllOnes_ColorMode,
+ kAllZeros_ColorMode,
+ kAlphaOne_ColorMode,
+ kRandom_ColorMode,
+ kLast_ColorMode = kRandom_ColorMode
+};
+
+static void set_random_color(GrGpuGL* gpu, SkRandom* random) {
+ ColorMode colorMode = ColorMode(random->nextULessThan(kLast_ColorMode + 1));
+ GrColor color;
+ switch (colorMode) {
+ case kAllOnes_ColorMode:
+ color = GrColorPackRGBA(0xFF, 0xFF, 0xFF, 0xFF);
+ break;
+ case kAllZeros_ColorMode:
+ color = GrColorPackRGBA(0, 0, 0, 0);
+ break;
+ case kAlphaOne_ColorMode:
+ color = GrColorPackRGBA(random->nextULessThan(256),
+ random->nextULessThan(256),
+ random->nextULessThan(256),
+ 0xFF);
+ break;
+ case kRandom_ColorMode:
+ uint8_t alpha = random->nextULessThan(256);
+ color = GrColorPackRGBA(random->nextRangeU(0, alpha),
+ random->nextRangeU(0, alpha),
+ random->nextRangeU(0, alpha),
+ alpha);
+ break;
+ }
+ GrColorIsPMAssert(color);
+ gpu->drawState()->setColor(color);
+}
+
+// There are only a few cases of random coverages which interest us
+enum CoverageMode {
+ kZero_CoverageMode,
+ kFF_CoverageMode,
+ kRandom_CoverageMode,
+ kLast_CoverageMode = kRandom_CoverageMode
+};
+
+static void set_random_coverage(GrGpuGL* gpu, SkRandom* random) {
+ CoverageMode coverageMode = CoverageMode(random->nextULessThan(kLast_CoverageMode + 1));
+ uint8_t coverage;
+ switch (coverageMode) {
+ case kZero_CoverageMode:
+ coverage = 0;
+ break;
+ case kFF_CoverageMode:
+ coverage = 0xFF;
+ break;
+ case kRandom_CoverageMode:
+ coverage = uint8_t(random->nextU());
+ break;
+ }
+ gpu->drawState()->setCoverage(coverage);
+}
+
+static void set_random_hints(GrGpuGL* gpu, SkRandom* random) {
+ for (int i = 1; i <= GrDrawState::kLast_Hint; i <<= 1) {
+ gpu->drawState()->setHint(GrDrawState::Hints(i), random->nextBool());
+ }
+}
+
+static void set_random_state(GrGpuGL* gpu, SkRandom* random) {
+ int state = 0;
+ for (int i = 1; i <= GrDrawState::kLastPublicStateBit; i <<= 1) {
+ state |= random->nextBool() * i;
+ }
+ gpu->drawState()->enableState(state);
+}
+
+// this function will randomly pick non-self referencing blend modes
+static void set_random_blend_func(GrGpuGL* gpu, SkRandom* random) {
+ GrBlendCoeff src;
+ do {
+ src = GrBlendCoeff(random->nextRangeU(kFirstPublicGrBlendCoeff, kLastPublicGrBlendCoeff));
+ } while (GrBlendCoeffRefsSrc(src));
+ GrBlendCoeff dst;
+ do {
+ dst = GrBlendCoeff(random->nextRangeU(kFirstPublicGrBlendCoeff, kLastPublicGrBlendCoeff));
+ } while (GrBlendCoeffRefsDst(dst));
+
+ gpu->drawState()->setBlendFunc(src, dst);
+}
+
+// right now, the only thing we seem to care about in drawState's stencil is 'doesWrite()'
+static void set_random_stencil(GrGpuGL* gpu, SkRandom* random) {
+ GR_STATIC_CONST_SAME_STENCIL(kDoesWriteStencil,
+ kReplace_StencilOp,
+ kReplace_StencilOp,
+ kAlways_StencilFunc,
+ 0xffff,
+ 0xffff,
+ 0xffff);
+ GR_STATIC_CONST_SAME_STENCIL(kDoesNotWriteStencil,
+ kKeep_StencilOp,
+ kKeep_StencilOp,
+ kNever_StencilFunc,
+ 0xffff,
+ 0xffff,
+ 0xffff);
+
+ if (random->nextBool()) {
+ gpu->drawState()->setStencil(kDoesWriteStencil);
+ } else {
+ gpu->drawState()->setStencil(kDoesNotWriteStencil);
+ }
+}
+
+bool GrGpuGL::programUnitTest(int maxStages) {
+ // setup dummy textures
GrTextureDesc dummyDesc;
dummyDesc.fFlags = kRenderTarget_GrTextureFlagBit;
dummyDesc.fConfig = kSkia8888_GrPixelConfig;
@@ -229,130 +387,116 @@ bool GrGpuGL::programUnitTest(int maxStages) {
SkAutoTUnref<GrTexture> dummyTexture2(this->createTexture(dummyDesc, NULL, 0));
if (!dummyTexture1 || ! dummyTexture2) {
+ SkDebugf("Could not allocate dummy textures");
return false;
}
- static const int NUM_TESTS = 512;
+ GrTexture* dummyTextures[] = {dummyTexture1.get(), dummyTexture2.get()};
- SkRandom random;
- for (int t = 0; t < NUM_TESTS; ++t) {
+ // Setup texture cache id key
+ const GrCacheID::Domain glProgramsDomain = GrCacheID::GenerateDomain();
+ GrCacheID::Key key;
+ memset(&key, 0, sizeof(key));
+ key.fData32[0] = kRenderTargetWidth;
+ key.fData32[1] = kRenderTargetHeight;
+ GrCacheID glProgramsCacheID(glProgramsDomain, key);
-#if 0
- GrPrintf("\nTest Program %d\n-------------\n", t);
- static const int stop = -1;
- if (t == stop) {
- int breakpointhere = 9;
- }
-#endif
+ // setup clip
+ SkRect screen =
+ SkRect::MakeWH(SkIntToScalar(kRenderTargetWidth), SkIntToScalar(kRenderTargetHeight));
- GrGLProgramDesc pdesc;
+ SkClipStack stack;
+ stack.clipDevRect(screen, SkRegion::kReplace_Op, false);
- int currAttribIndex = 1; // we need to always leave room for position
- int currTextureCoordSet = 0;
- GrTexture* dummyTextures[] = {dummyTexture1.get(), dummyTexture2.get()};
+ // wrap the SkClipStack in a GrClipData
+ GrClipData clipData;
+ clipData.fClipStack = &stack;
+ this->setClip(&clipData);
- int numStages = random.nextULessThan(maxStages + 1);
- int numColorStages = random.nextULessThan(numStages + 1);
- int numCoverageStages = numStages - numColorStages;
+ SkRandom random;
+ static const int NUM_TESTS = 512;
+ for (int t = 0; t < NUM_TESTS;) {
+ // setup random render target(can fail)
+ GrRenderTarget* rtPtr = random_render_target(this, glProgramsCacheID, &random);
+ if (!rtPtr) {
+ SkDebugf("Could not allocate render target");
+ return false;
+ }
+ GrTGpuResourceRef<GrRenderTarget> rt(SkRef(rtPtr), kWrite_GrIOType);
- SkAutoSTMalloc<8, const GrFragmentStage*> stages(numStages);
+ GrDrawState* ds = this->drawState();
+ ds->setRenderTarget(rt.get());
+ // if path rendering we have to setup a couple of things like the draw type
bool usePathRendering = this->glCaps().pathRenderingSupport() && random.nextBool();
GrGpu::DrawType drawType = usePathRendering ? GrGpu::kDrawPath_DrawType :
GrGpu::kDrawPoints_DrawType;
- SkAutoTDelete<GrGeometryStage> geometryProcessor;
+ // twiddle drawstate knobs randomly
bool hasGeometryProcessor = usePathRendering ? false : random.nextBool();
if (hasGeometryProcessor) {
- while (true) {
- SkAutoTUnref<const GrGeometryProcessor> effect(
- GrProcessorTestFactory<GrGeometryProcessor>::CreateStage(&random, this->getContext(), *this->caps(),
- dummyTextures));
- SkASSERT(effect);
- // Only geometryProcessor can use vertex shader
- GrGeometryStage* stage = SkNEW_ARGS(GrGeometryStage, (effect.get()));
- geometryProcessor.reset(stage);
-
- // we have to set dummy vertex attribs
- const GrGeometryProcessor::VertexAttribArray& v = effect->getVertexAttribs();
- int numVertexAttribs = v.count();
-
- SkASSERT(GrGeometryProcessor::kMaxVertexAttribs == 2 &&
- GrGeometryProcessor::kMaxVertexAttribs >= numVertexAttribs);
- size_t runningStride = GrVertexAttribTypeSize(genericVertexAttribs[0].fType);
- for (int i = 0; i < numVertexAttribs; i++) {
- genericVertexAttribs[i + 1].fOffset = runningStride;
- genericVertexAttribs[i + 1].fType =
- convert_sltype_to_attribtype(v[i].getType());
- runningStride += GrVertexAttribTypeSize(genericVertexAttribs[i + 1].fType);
- }
-
- // update the vertex attributes with the ds
- GrDrawState* ds = this->drawState();
- ds->setVertexAttribs<genericVertexAttribs>(numVertexAttribs + 1, runningStride);
- currAttribIndex = numVertexAttribs + 1;
- break;
- }
+ set_random_gp(this, &random, dummyTextures);
}
- for (int s = 0; s < numStages;) {
- SkAutoTUnref<const GrFragmentProcessor> effect(
- GrProcessorTestFactory<GrFragmentProcessor>::CreateStage(
- &random,
- this->getContext(),
- *this->caps(),
- dummyTextures));
- SkASSERT(effect);
-
- // If adding this effect would exceed the max texture coord set count then generate a
- // new random effect.
- if (usePathRendering && this->glPathRendering()->texturingMode() ==
- GrGLPathRendering::FixedFunction_TexturingMode) {;
- int numTransforms = effect->numTransforms();
- if (currTextureCoordSet + numTransforms > this->glCaps().maxFixedFunctionTextureCoords()) {
- continue;
- }
- currTextureCoordSet += numTransforms;
- }
- GrFragmentStage* stage = SkNEW_ARGS(GrFragmentStage, (effect.get()));
-
- stages[s] = stage;
- ++s;
+ set_random_color_coverage_stages(this, maxStages - hasGeometryProcessor, usePathRendering,
+ &random, dummyTextures);
+ set_random_color(this, &random);
+ set_random_coverage(this, &random);
+ set_random_hints(this, &random);
+ set_random_state(this, &random);
+ set_random_blend_func(this, &random);
+ set_random_stencil(this, &random);
+
+ // create optimized draw state, setup readDst texture if required, and build a descriptor
+ // and program. ODS creation can fail, so we have to check
+ SkAutoTUnref<GrOptDrawState> ods(GrOptDrawState::Create(this->getDrawState(),
+ *this->caps(),
+ drawType));
+ if (!ods.get()) {
+ ds->reset();
+ continue;
}
- const GrTexture* dstTexture = random.nextBool() ? dummyTextures[0] : dummyTextures[1];
- if (!pdesc.setRandom(&random,
- this,
- dummyTextures[0]->asRenderTarget(),
- dstTexture,
- geometryProcessor.get(),
- stages.get(),
- numColorStages,
- numCoverageStages,
- currAttribIndex,
- drawType)) {
+ const GrGeometryStage* geometryProcessor = NULL;
+ SkSTArray<8, const GrFragmentStage*, true> colorStages;
+ SkSTArray<8, const GrFragmentStage*, true> coverageStages;
+ GrGLProgramDesc desc;
+ GrDeviceCoordTexture dstCopy;
+
+ if (!this->setupDstReadIfNecessary(&dstCopy, NULL)) {
+ SkDebugf("Couldn't setup dst read texture");
return false;
}
-
- SkAutoTUnref<GrOptDrawState> optState(GrOptDrawState::Create(this->getDrawState(),
- *this->caps(),
- drawType));
- SkAutoTUnref<GrGLProgram> program(
- GrGLProgramBuilder::CreateProgram(*optState,
- pdesc,
- drawType,
- geometryProcessor,
- stages,
- stages + numColorStages,
- this));
- for (int s = 0; s < numStages; ++s) {
- SkDELETE(stages[s]);
+ if (!GrGLProgramDesc::Build(*ods,
+ drawType,
+ ods->getSrcBlendCoeff(),
+ ods->getDstBlendCoeff(),
+ this,
+ dstCopy.texture() ? &dstCopy : NULL,
+ &geometryProcessor,
+ &colorStages,
+ &coverageStages,
+ &desc)) {
+ SkDebugf("Failed to generate GL program descriptor");
+ return false;
}
+ SkAutoTUnref<GrGLProgram> program(GrGLProgramBuilder::CreateProgram(*ods,
+ desc,
+ drawType,
+ geometryProcessor,
+ colorStages.begin(),
+ coverageStages.begin(),
+ this));
if (NULL == program.get()) {
+ SkDebugf("Failed to create program!");
return false;
}
// We have to reset the drawstate because we might have added a gp
- this->drawState()->reset();
+ ds->reset();
+
+ // because occasionally optimized drawstate creation will fail for valid reasons, we only
+ // want to increment on success
+ ++t;
}
return true;
}