Chromium Code Reviews| Index: tests/GLProgramsTest.cpp |
| diff --git a/tests/GLProgramsTest.cpp b/tests/GLProgramsTest.cpp |
| index a16173b9652f772de9ee8eeefe9a3a0117173d54..ac3ebd6a8e97437fec3ea07f6aea97a5fe4309f5 100644 |
| --- a/tests/GLProgramsTest.cpp |
| +++ b/tests/GLProgramsTest.cpp |
| @@ -22,180 +22,50 @@ |
| #include "SkRandom.h" |
| #include "Test.h" |
| -static void get_stage_stats(const GrFragmentStage stage, bool* readsDst, |
| - bool* readsFragPosition, bool* requiresVertexShader) { |
| - if (stage.getFragmentProcessor()->willReadDstColor()) { |
| - *readsDst = true; |
| - } |
| - if (stage.getProcessor()->willReadFragmentPosition()) { |
| - *readsFragPosition = true; |
| - } |
| -} |
| - |
| -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++; |
| - } |
| - |
| - 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; |
| +static const int kRenderTargetHeight = 1; |
| +static const int kRenderTargetWidth = 1; |
| + |
| +static GrRenderTarget* random_render_target(GrGpuGL* gpu, |
| + const GrCacheID& cacheId, |
|
egdaniel
2014/10/06 14:19:02
move param up and onto same line
|
| + 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, ¶ms); |
| + if (NULL == texture) { |
| + texture = gpu->getContext()->createTexture(¶ms, texDesc, cacheId, 0, 0); |
| + if (NULL == texture) { |
| + SkDEBUGFAIL("Could not allocate render target"); |
|
bsalomon
2014/10/06 14:29:04
Maybe just SkDebugf? Hopefully this ripples up and
|
| + return NULL; |
| } |
| - get_stage_stats(*stage, &dstRead, &fragPos, &vertexShader); |
| - offsetAndSize[0] = effectKeyOffset; |
| - offsetAndSize[1] = effectKeySize; |
| - } |
| - |
| - KeyHeader* header = this->header(); |
| - memset(header, 0, kHeaderSize); |
| - header->fEmitsPointSize = random->nextBool(); |
| - |
| - header->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 { |
| - 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; |
| - |
| - 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 |
| - |
| - header->fLocalCoordAttributeIndex = useLocalCoords ? currAttribIndex++ : -1; |
| - |
| - header->fColorEffectCnt = numColorStages; |
| - header->fCoverageEffectCnt = numCoverageStages; |
| - |
| - 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; |
| - } |
| - |
| - header->fUseFragShaderOnly = isPathRendering && gpu->glPathRendering()->texturingMode() == |
| - GrGLPathRendering::FixedFunction_TexturingMode; |
| - header->fHasGeometryProcessor = vertexShader; |
| - |
| - GrOptDrawState::PrimaryOutputType primaryOutput; |
| - GrOptDrawState::SecondaryOutputType secondaryOutput; |
| - if (!dstRead) { |
| - primaryOutput = GrOptDrawState::kModulate_PrimaryOutputType; |
| - } else { |
| - primaryOutput = static_cast<GrOptDrawState::PrimaryOutputType>( |
| - random->nextULessThan(GrOptDrawState::kPrimaryOutputTypeCnt)); |
| - } |
| - |
| - if (GrOptDrawState::kCombineWithDst_PrimaryOutputType == primaryOutput || |
| - !gpu->caps()->dualSourceBlendingSupport()) { |
| - secondaryOutput = GrOptDrawState::kNone_SecondaryOutputType; |
| - } else { |
| - secondaryOutput = static_cast<GrOptDrawState::SecondaryOutputType>( |
| - random->nextULessThan(GrOptDrawState::kSecondaryOutputTypeCnt)); |
| - } |
| - |
| - header->fPrimaryOutputType = primaryOutput; |
| - header->fSecondaryOutputType = secondaryOutput; |
| - |
| - this->finalize(); |
| - return true; |
| + 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. |
| +// than two attributes. In addition, we 'pad' the below array with GPs up to 6 entries. |
|
egdaniel
2014/10/06 14:19:02
add into comment that the 6 comes from 4 ff va's a
|
| GrVertexAttrib genericVertexAttribs[] = { |
|
egdaniel
2014/10/06 14:19:02
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; |
| @@ -212,9 +82,233 @@ GrVertexAttribType convert_sltype_to_attribtype(GrSLType type) { |
| } |
| // TODO end test hack |
|
egdaniel
2014/10/06 14:19:02
What is this TODO for?
|
| +static void setup_random_ff_attribute(GrVertexAttribBinding binding, GrVertexAttribType type, |
| + SkRandom* random, int* attribIndex, int* runningStride) { |
| + if (random->nextBool()) { |
| + genericVertexAttribs[*attribIndex].fType = type; |
| + genericVertexAttribs[*attribIndex].fOffset = *runningStride; |
| + genericVertexAttribs[*attribIndex].fBinding = binding; |
| + *runningStride += GrVertexAttribTypeSize(genericVertexAttribs[(*attribIndex)++].fType); |
| + } |
| +} |
| -bool GrGpuGL::programUnitTest(int maxStages) { |
| +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(genericVertexAttribs[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); |
| + for (int i = 0; i < numGPAttribs; i++) { |
| + genericVertexAttribs[i + attribIndex].fType = |
| + convert_sltype_to_attribtype(v[i].getType()); |
| + genericVertexAttribs[i + attribIndex].fOffset = runningStride; |
| + genericVertexAttribs[i + attribIndex].fBinding = kGeometryProcessor_GrVertexAttribBinding; |
| + runningStride += GrVertexAttribTypeSize(genericVertexAttribs[i + attribIndex].fType); |
| + } |
| + |
| + // update the vertex attributes with the ds |
| + GrDrawState* ds = gpu->drawState(); |
| + ds->setVertexAttribs<genericVertexAttribs>(attribIndex + numGPAttribs, runningStride); |
| + ds->setGeometryProcessor(gp); |
| +} |
| +void set_random_color_coverage_stages(GrGpuGL* gpu, |
|
egdaniel
2014/10/06 14:19:02
put some of these params on same line
bsalomon
2014/10/06 14:29:04
static?
bsalomon
2014/10/06 14:29:04
we definitely have mixed styles. In a lot of place
|
| + 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); |
| +} |
| + |
| +// there is only one hint right now, but we have to make sure more hints aren't added without |
| +// testing them |
| +static void set_random_hints(GrGpuGL* gpu, SkRandom* random) { |
| + GR_STATIC_ASSERT(GrDrawState::kLast_Hint == GrDrawState::kVertexColorsAreOpaque_Hint); |
| + |
| + gpu->drawState()->setHint(GrDrawState::kVertexColorsAreOpaque_Hint, random->nextBool()); |
|
bsalomon
2014/10/06 14:29:04
Maybe just go ahead with
if (int i = 1, i <= kLa
|
| +} |
| + |
| +#define SET_RANDOM_BIT(flag) \ |
| + (random->nextBool() << pow++) & (flag) |
| + |
| +// similar to the above, we have to prevent random state bits from being added without testing |
| +static void set_random_state(GrGpuGL* gpu, SkRandom* random) { |
| + GR_STATIC_ASSERT(GrDrawState::kLastPublicStateBit == GrDrawState::kCoverageDrawing_StateBit); |
|
bsalomon
2014/10/06 14:29:04
loop?
|
| + |
| + uint32_t state = 0; |
| + uint32_t pow = 0; |
| + state |= SET_RANDOM_BIT(GrDrawState::kDither_StateBit); |
| + state |= SET_RANDOM_BIT(GrDrawState::kHWAntialias_StateBit); |
| + state |= SET_RANDOM_BIT(GrDrawState::kClip_StateBit); |
| + state |= SET_RANDOM_BIT(GrDrawState::kNoColorWrites_StateBit); |
| + state |= SET_RANDOM_BIT(GrDrawState::kCoverageDrawing_StateBit); |
| + 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; |
| @@ -231,121 +325,97 @@ bool GrGpuGL::programUnitTest(int maxStages) { |
| return false; |
| } |
| - static const int NUM_TESTS = 512; |
| - |
| - SkRandom random; |
| - for (int t = 0; t < NUM_TESTS; ++t) { |
| - |
| -#if 0 |
| - GrPrintf("\nTest Program %d\n-------------\n", t); |
| - static const int stop = -1; |
| - if (t == stop) { |
| - int breakpointhere = 9; |
| - } |
| -#endif |
| + GrTexture* dummyTextures[] = {dummyTexture1.get(), dummyTexture2.get()}; |
| - GrGLProgramDesc pdesc; |
| + // 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); |
| - int currAttribIndex = 1; // we need to always leave room for position |
| - int currTextureCoordSet = 0; |
| - GrTexture* dummyTextures[] = {dummyTexture1.get(), dummyTexture2.get()}; |
| + // setup clip |
| + SkRect screen = |
| + SkRect::MakeWH(SkIntToScalar(kRenderTargetWidth), SkIntToScalar(kRenderTargetHeight)); |
| - int numStages = random.nextULessThan(maxStages + 1); |
| - int numColorStages = random.nextULessThan(numStages + 1); |
| - int numCoverageStages = numStages - numColorStages; |
| + SkClipStack stack; |
| + stack.clipDevRect(screen, SkRegion::kReplace_Op, false); |
| - SkAutoSTMalloc<8, const GrFragmentStage*> stages(numStages); |
| + // wrap the SkClipStack in a GrClipData |
| + GrClipData clipData; |
| + clipData.fClipStack = &stack; |
| + this->setClip(&clipData); |
| + SkRandom random; |
| + static const int NUM_TESTS = 512; |
| + for (int t = 0; t < NUM_TESTS; ++t) { |
| + // setup random render target |
| + GrTGpuResourceRef<GrRenderTarget> rt( |
| + SkRef(random_render_target(this, |
| + glProgramsCacheID, |
| + &random)), |
| + GrIORef::kWrite_IOType); |
| + 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; |
| - } |
| - } |
| - 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_gp(this, &random, dummyTextures); |
| } |
| - 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)) { |
| + set_random_color_coverage_stages(this, maxStages, 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 |
| + SkAutoTUnref<GrOptDrawState> ods(ds->createOptState(*this->caps())); |
| + 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)) { |
| + SkDEBUGFAIL("Couldn't setup dst read texture"); |
| return false; |
| } |
| - |
| - SkAutoTUnref<GrGLProgram> program(GrGLProgram::Create(this, |
| - pdesc, |
| - geometryProcessor.get(), |
| - stages, |
| - stages + numColorStages)); |
| - 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)) { |
| + SkDEBUGFAIL("Failed to generate GL program descriptor"); |
| + return false; |
| } |
| + SkAutoTUnref<GrGLProgram> program(SkSafeRef(GrGLProgram::Create(this, |
| + desc, |
| + geometryProcessor, |
| + colorStages.begin(), |
| + coverageStages.begin()))); |
| if (NULL == program.get()) { |
| + SkDEBUGFAIL("Failed to create program!"); |
| return false; |
| } |
| // We have to reset the drawstate because we might have added a gp |
| - this->drawState()->reset(); |
| + ds->reset(); |
| } |
| return true; |
| } |