void GrOptDrawState::getStageStats() { // We will need a local coord attrib if there is one currently set on the optState and we are // actually generating some effect code fRequiresLocalCoordAttrib = this->hasLocalCoordAttribute() && this->numTotalStages() > 0; fReadsDst = false; fReadsFragPosition = false; for (int s = 0; s < this->numColorStages(); ++s) { const GrFragmentStage& stage = this->getColorStage(s); get_stage_stats(stage, &fReadsDst, &fReadsFragPosition); } for (int s = 0; s < this->numCoverageStages(); ++s) { const GrFragmentStage& stage = this->getCoverageStage(s); get_stage_stats(stage, &fReadsDst, &fReadsFragPosition); } if (this->hasGeometryProcessor()) { const GrGeometryStage& stage = *this->getGeometryProcessor(); fReadsFragPosition = fReadsFragPosition || stage.getProcessor()->willReadFragmentPosition(); } }
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; } 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; }