/** * Retrieves the final matrix that a transform needs to apply to its source coords. */ static SkMatrix get_transform_matrix(const GrPendingFragmentStage& stage, bool useExplicitLocalCoords, int transformIdx) { const GrCoordTransform& coordTransform = stage.getProcessor()->coordTransform(transformIdx); SkMatrix combined; if (kLocal_GrCoordSet == coordTransform.sourceCoords()) { // If we have explicit local coords then we shouldn't need a coord change. const SkMatrix& ccm = useExplicitLocalCoords ? SkMatrix::I() : stage.getCoordChangeMatrix(); combined.setConcat(coordTransform.getMatrix(), ccm); } else { combined = coordTransform.getMatrix(); } if (coordTransform.reverseY()) { // combined.postScale(1,-1); // combined.postTranslate(0,1); combined.set(SkMatrix::kMSkewY, combined[SkMatrix::kMPersp0] - combined[SkMatrix::kMSkewY]); combined.set(SkMatrix::kMScaleY, combined[SkMatrix::kMPersp1] - combined[SkMatrix::kMScaleY]); combined.set(SkMatrix::kMTransY, combined[SkMatrix::kMPersp2] - combined[SkMatrix::kMTransY]); } return combined; }
void GrGLNvprProgramBuilder::emitTransforms(const GrPendingFragmentStage& processorStage, GrGLProcessor::TransformedCoordsArray* outCoords, GrGLInstalledFragProc* ifp) { const GrFragmentProcessor* effect = processorStage.getProcessor(); int numTransforms = effect->numTransforms(); ifp->fTransforms.push_back_n(numTransforms); for (int t = 0; t < numTransforms; t++) { GrSLType varyingType = processorStage.isPerspectiveCoordTransform(t) ? kVec3f_GrSLType : kVec2f_GrSLType; const char* varyingName = "MatrixCoord"; SkString suffixedVaryingName; if (0 != t) { suffixedVaryingName.append(varyingName); suffixedVaryingName.appendf("_%i", t); varyingName = suffixedVaryingName.c_str(); } GrGLVertToFrag v(varyingType); ifp->fTransforms[t].fHandle = this->addSeparableVarying(varyingName, &v); ifp->fTransforms[t].fType = varyingType; SkNEW_APPEND_TO_TARRAY(outCoords, GrGLProcessor::TransformedCoords, (SkString(v.fsIn()), varyingType)); } }
void GrGLNvprProgram::setTransformData(const GrPrimitiveProcessor& primProc, const GrPendingFragmentStage& proc, int index, GrGLInstalledFragProc* ip) { GrGLPathProcessor* pathProc = static_cast<GrGLPathProcessor*>(fGeometryProcessor.get()->fGLProc.get()); pathProc->setTransformData(primProc, index, proc.processor()->coordTransforms(), fGpu->glPathRendering(), fProgramID); }
void GrGLProgram::setTransformData(const GrPrimitiveProcessor& primProc, const GrPendingFragmentStage& processor, int index, GrGLInstalledFragProc* ip) { GrGLGeometryProcessor* gp = static_cast<GrGLGeometryProcessor*>(fGeometryProcessor.get()->fGLProc.get()); gp->setTransformData(primProc, fProgramDataManager, index, processor.processor()->coordTransforms()); }
void GrGLProgram::setTransformData(const GrPendingFragmentStage& processor, GrGLInstalledFragProc* ip) { SkTArray<GrGLInstalledFragProc::Transform, true>& transforms = ip->fTransforms; int numTransforms = transforms.count(); SkASSERT(numTransforms == processor.getProcessor()->numTransforms()); for (int t = 0; t < numTransforms; ++t) { SkASSERT(transforms[t].fHandle.isValid()); const SkMatrix& matrix = get_transform_matrix(processor, ip->fLocalCoordAttrib, t); if (!transforms[t].fCurrentValue.cheapEqualTo(matrix)) { fProgramDataManager.setSkMatrix(transforms[t].fHandle.convertToUniformHandle(), matrix); transforms[t].fCurrentValue = matrix; } } }
// TODO Processors cannot output zeros because an empty string is all 1s // the fix is to allow effects to take the GrGLSLExpr4 directly void GrGLProgramBuilder::emitAndInstallProc(const GrPendingFragmentStage& proc, int index, const GrGLSLExpr4& input, GrGLSLExpr4* output) { // Program builders have a bit of state we need to clear with each effect AutoStageAdvance adv(this); this->nameExpression(output, "output"); // Enclose custom code in a block to avoid namespace conflicts SkString openBrace; openBrace.printf("{ // Stage %d, %s\n", fStageIndex, proc.name()); fFS.codeAppend(openBrace.c_str()); this->emitAndInstallProc(proc, index, output->c_str(), input.isOnes() ? NULL : input.c_str()); fFS.codeAppend("}"); }
void GrGLProgramBuilder::emitAndInstallProc(const GrPendingFragmentStage& fs, int index, const char* outColor, const char* inColor) { GrGLInstalledFragProc* ifp = SkNEW(GrGLInstalledFragProc); const GrFragmentProcessor& fp = *fs.processor(); ifp->fGLProc.reset(fp.createGLInstance()); SkSTArray<4, GrGLProcessor::TextureSampler> samplers(fp.numTextures()); this->emitSamplers(fp, &samplers, ifp); ifp->fGLProc->emitCode(this, fp, outColor, inColor, fOutCoords[index], samplers); // We have to check that effects and the code they emit are consistent, ie if an effect // asks for dst color, then the emit code needs to follow suit verify(fp); fFragmentProcessors->fProcs.push_back(ifp); }