bool GrGpuGLShaders::programUnitTest() { GrGLSLGeneration glslGeneration = GetGLSLGeneration(this->glBinding(), this->glInterface()); static const int STAGE_OPTS[] = { 0, StageDesc::kNoPerspective_OptFlagBit, StageDesc::kIdentity_CoordMapping }; static const int IN_CONFIG_FLAGS[] = { StageDesc::kNone_InConfigFlag, StageDesc::kSwapRAndB_InConfigFlag, StageDesc::kSwapRAndB_InConfigFlag | StageDesc::kMulRGBByAlpha_InConfigFlag, StageDesc::kMulRGBByAlpha_InConfigFlag, StageDesc::kSmearAlpha_InConfigFlag, }; GrGLProgram program; ProgramDesc& pdesc = program.fProgramDesc; static const int NUM_TESTS = 512; GrRandom 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 pdesc.fVertexLayout = 0; pdesc.fEmitsPointSize = random.nextF() > .5f; pdesc.fColorInput = random_int(&random, ProgramDesc::kColorInputCnt); pdesc.fColorFilterXfermode = random_int(&random, SkXfermode::kCoeffModesCnt); pdesc.fFirstCoverageStage = random_int(&random, GrDrawState::kNumStages); pdesc.fVertexLayout |= random_bool(&random) ? GrDrawTarget::kCoverage_VertexLayoutBit : 0; #if GR_GL_EXPERIMENTAL_GS pdesc.fExperimentalGS = this->getCaps().fGeometryShaderSupport && random_bool(&random); #endif pdesc.fOutputPM = random_int(&random, ProgramDesc::kOutputPMCnt); bool edgeAA = random_bool(&random); if (edgeAA) { bool vertexEdgeAA = random_bool(&random); if (vertexEdgeAA) { pdesc.fVertexLayout |= GrDrawTarget::kEdge_VertexLayoutBit; if (this->getCaps().fShaderDerivativeSupport) { pdesc.fVertexEdgeType = random_bool(&random) ? GrDrawState::kHairQuad_EdgeType : GrDrawState::kHairLine_EdgeType; } else { pdesc.fVertexEdgeType = GrDrawState::kHairLine_EdgeType; } pdesc.fEdgeAANumEdges = 0; } else { pdesc.fEdgeAANumEdges = random_int(&random, 1, this->getMaxEdges()); pdesc.fEdgeAAConcave = random_bool(&random); } } else { pdesc.fEdgeAANumEdges = 0; } if (this->getCaps().fDualSourceBlendingSupport) { pdesc.fDualSrcOutput = random_int(&random, ProgramDesc::kDualSrcOutputCnt); } else { pdesc.fDualSrcOutput = ProgramDesc::kNone_DualSrcOutput; } for (int s = 0; s < GrDrawState::kNumStages; ++s) { // enable the stage? if (random_bool(&random)) { // use separate tex coords? if (random_bool(&random)) { int t = random_int(&random, GrDrawState::kMaxTexCoords); pdesc.fVertexLayout |= StageTexCoordVertexLayoutBit(s, t); } else { pdesc.fVertexLayout |= StagePosAsTexCoordVertexLayoutBit(s); } } // use text-formatted verts? if (random_bool(&random)) { pdesc.fVertexLayout |= kTextFormat_VertexLayoutBit; } StageDesc& stage = pdesc.fStages[s]; stage.fOptFlags = STAGE_OPTS[random_int(&random, GR_ARRAY_COUNT(STAGE_OPTS))]; stage.fInConfigFlags = IN_CONFIG_FLAGS[random_int(&random, GR_ARRAY_COUNT(IN_CONFIG_FLAGS))]; stage.fCoordMapping = random_int(&random, StageDesc::kCoordMappingCnt); stage.fFetchMode = random_int(&random, StageDesc::kFetchModeCnt); // convolution shaders don't work with persp tex matrix if (stage.fFetchMode == StageDesc::kConvolution_FetchMode) { stage.fOptFlags |= StageDesc::kNoPerspective_OptFlagBit; } stage.setEnabled(VertexUsesStage(s, pdesc.fVertexLayout)); switch (stage.fFetchMode) { case StageDesc::kSingle_FetchMode: stage.fKernelWidth = 0; break; case StageDesc::kConvolution_FetchMode: stage.fKernelWidth = random_int(&random, 2, 8); stage.fInConfigFlags &= ~StageDesc::kMulRGBByAlpha_InConfigFlag; break; case StageDesc::k2x2_FetchMode: stage.fKernelWidth = 0; stage.fInConfigFlags &= ~StageDesc::kMulRGBByAlpha_InConfigFlag; break; } } CachedData cachedData; if (!program.genProgram(this->glInterface(), glslGeneration, &cachedData)) { return false; } DeleteProgram(this->glInterface(), &cachedData); } return true; }
bool GrGpuGLShaders::programUnitTest() { GrGLSLGeneration glslGeneration = GrGetGLSLGeneration(this->glBinding(), this->glInterface()); static const int STAGE_OPTS[] = { 0, StageDesc::kNoPerspective_OptFlagBit, StageDesc::kIdentity_CoordMapping }; static const int IN_CONFIG_FLAGS[] = { StageDesc::kNone_InConfigFlag, StageDesc::kSwapRAndB_InConfigFlag, StageDesc::kSwapRAndB_InConfigFlag | StageDesc::kMulRGBByAlpha_RoundUp_InConfigFlag, StageDesc::kMulRGBByAlpha_RoundDown_InConfigFlag, StageDesc::kSmearAlpha_InConfigFlag, StageDesc::kSmearRed_InConfigFlag, }; GrGLProgram program; ProgramDesc& pdesc = program.fProgramDesc; static const int NUM_TESTS = 512; GrRandom 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 pdesc.fVertexLayout = 0; pdesc.fEmitsPointSize = random.nextF() > .5f; pdesc.fColorInput = random_int(&random, ProgramDesc::kColorInputCnt); pdesc.fCoverageInput = random_int(&random, ProgramDesc::kColorInputCnt); pdesc.fColorFilterXfermode = random_int(&random, SkXfermode::kCoeffModesCnt); pdesc.fFirstCoverageStage = random_int(&random, GrDrawState::kNumStages); pdesc.fVertexLayout |= random_bool(&random) ? GrDrawTarget::kCoverage_VertexLayoutBit : 0; #if GR_GL_EXPERIMENTAL_GS pdesc.fExperimentalGS = this->getCaps().fGeometryShaderSupport && random_bool(&random); #endif pdesc.fOutputConfig = random_int(&random, ProgramDesc::kOutputConfigCnt); bool edgeAA = random_bool(&random); if (edgeAA) { pdesc.fVertexLayout |= GrDrawTarget::kEdge_VertexLayoutBit; if (this->getCaps().fShaderDerivativeSupport) { pdesc.fVertexEdgeType = (GrDrawState::VertexEdgeType) random_int(&random, GrDrawState::kVertexEdgeTypeCnt); } else { pdesc.fVertexEdgeType = GrDrawState::kHairLine_EdgeType; } } else { } pdesc.fColorMatrixEnabled = random_bool(&random); if (this->getCaps().fDualSourceBlendingSupport) { pdesc.fDualSrcOutput = random_int(&random, ProgramDesc::kDualSrcOutputCnt); } else { pdesc.fDualSrcOutput = ProgramDesc::kNone_DualSrcOutput; } GrCustomStage* customStages[GrDrawState::kNumStages]; for (int s = 0; s < GrDrawState::kNumStages; ++s) { // enable the stage? if (random_bool(&random)) { // use separate tex coords? if (random_bool(&random)) { int t = random_int(&random, GrDrawState::kMaxTexCoords); pdesc.fVertexLayout |= StageTexCoordVertexLayoutBit(s, t); } else { pdesc.fVertexLayout |= StagePosAsTexCoordVertexLayoutBit(s); } } // use text-formatted verts? if (random_bool(&random)) { pdesc.fVertexLayout |= kTextFormat_VertexLayoutBit; } StageDesc& stage = pdesc.fStages[s]; stage.fCustomStageKey = 0; customStages[s] = NULL; stage.fOptFlags = STAGE_OPTS[random_int(&random, GR_ARRAY_COUNT(STAGE_OPTS))]; stage.fInConfigFlags = IN_CONFIG_FLAGS[random_int(&random, GR_ARRAY_COUNT(IN_CONFIG_FLAGS))]; stage.fCoordMapping = random_int(&random, StageDesc::kCoordMappingCnt); stage.fFetchMode = random_int(&random, StageDesc::kFetchModeCnt); // convolution shaders don't work with persp tex matrix if (stage.fFetchMode == StageDesc::kConvolution_FetchMode || stage.fFetchMode == StageDesc::kDilate_FetchMode || stage.fFetchMode == StageDesc::kErode_FetchMode) { stage.fOptFlags |= StageDesc::kNoPerspective_OptFlagBit; } stage.setEnabled(VertexUsesStage(s, pdesc.fVertexLayout)); static const uint32_t kMulByAlphaMask = StageDesc::kMulRGBByAlpha_RoundUp_InConfigFlag | StageDesc::kMulRGBByAlpha_RoundDown_InConfigFlag; switch (stage.fFetchMode) { case StageDesc::kSingle_FetchMode: stage.fKernelWidth = 0; break; case StageDesc::kConvolution_FetchMode: case StageDesc::kDilate_FetchMode: case StageDesc::kErode_FetchMode: stage.fKernelWidth = random_int(&random, 2, 8); stage.fInConfigFlags &= ~kMulByAlphaMask; break; case StageDesc::k2x2_FetchMode: stage.fKernelWidth = 0; stage.fInConfigFlags &= ~kMulByAlphaMask; break; } // TODO: is there a more elegant way to express this? if (stage.fFetchMode == StageDesc::kConvolution_FetchMode) { int direction = random_int(&random, 2); float kernel[MAX_KERNEL_WIDTH]; for (int i = 0; i < stage.fKernelWidth; i++) { kernel[i] = random.nextF(); } customStages[s] = new GrConvolutionEffect( (GrSamplerState::FilterDirection)direction, stage.fKernelWidth, kernel); stage.fCustomStageKey = customStages[s]->getFactory()->stageKey(customStages[s]); } } CachedData cachedData; if (!program.genProgram(this->glContextInfo(), customStages, &cachedData)) { return false; } DeleteProgram(this->glInterface(), &cachedData); } return true; }
bool GrGpuGLShaders::programUnitTest() { GrGLProgram::GLSLVersion glslVersion = get_glsl_version(this->glBinding(), this->glInterface()); static const int STAGE_OPTS[] = { 0, StageDesc::kNoPerspective_OptFlagBit, StageDesc::kIdentity_CoordMapping }; GrGLProgram program; ProgramDesc& pdesc = program.fProgramDesc; static const int NUM_TESTS = 512; // GrRandoms nextU() values have patterns in the low bits // So using nextU() % array_count might never take some values. GrRandom 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 pdesc.fVertexLayout = 0; pdesc.fEmitsPointSize = random.nextF() > .5f; pdesc.fColorType = static_cast<int>(random.nextF() * ProgramDesc::kColorTypeCnt); int idx = (int)(random.nextF() * (SkXfermode::kCoeffModesCnt)); pdesc.fColorFilterXfermode = (SkXfermode::Mode)idx; idx = (int)(random.nextF() * (GrDrawState::kNumStages + 1)); pdesc.fFirstCoverageStage = idx; pdesc.fVertexLayout |= (random.nextF() > .5f) ? GrDrawTarget::kCoverage_VertexLayoutBit : 0; #if GR_GL_EXPERIMENTAL_GS pdesc.fExperimentalGS = this->getCaps().fGeometryShaderSupport && random.nextF() > .5f; #endif bool edgeAA = random.nextF() > .5f; if (edgeAA) { bool vertexEdgeAA = random.nextF() > .5f; if (vertexEdgeAA) { pdesc.fVertexLayout |= GrDrawTarget::kEdge_VertexLayoutBit; if (this->getCaps().fShaderDerivativeSupport) { pdesc.fVertexEdgeType = random.nextF() > 0.5f ? GrDrawState::kHairQuad_EdgeType : GrDrawState::kHairLine_EdgeType; } else { pdesc.fVertexEdgeType = GrDrawState::kHairLine_EdgeType; } pdesc.fEdgeAANumEdges = 0; } else { pdesc.fEdgeAANumEdges = static_cast<int>(1 + random.nextF() * this->getMaxEdges()); pdesc.fEdgeAAConcave = random.nextF() > .5f; } } else { pdesc.fEdgeAANumEdges = 0; } if (this->getCaps().fDualSourceBlendingSupport) { pdesc.fDualSrcOutput = (ProgramDesc::DualSrcOutput) (int)(random.nextF() * ProgramDesc::kDualSrcOutputCnt); } else { pdesc.fDualSrcOutput = ProgramDesc::kNone_DualSrcOutput; } for (int s = 0; s < GrDrawState::kNumStages; ++s) { // enable the stage? if (random.nextF() > .5f) { // use separate tex coords? if (random.nextF() > .5f) { int t = (int)(random.nextF() * GrDrawState::kMaxTexCoords); pdesc.fVertexLayout |= StageTexCoordVertexLayoutBit(s, t); } else { pdesc.fVertexLayout |= StagePosAsTexCoordVertexLayoutBit(s); } } // use text-formatted verts? if (random.nextF() > .5f) { pdesc.fVertexLayout |= kTextFormat_VertexLayoutBit; } idx = (int)(random.nextF() * GR_ARRAY_COUNT(STAGE_OPTS)); StageDesc& stage = pdesc.fStages[s]; stage.fOptFlags = STAGE_OPTS[idx]; stage.fModulation = random_val(&random, StageDesc::kModulationCnt); stage.fCoordMapping = random_val(&random, StageDesc::kCoordMappingCnt); stage.fFetchMode = random_val(&random, StageDesc::kFetchModeCnt); // convolution shaders don't work with persp tex matrix if (stage.fFetchMode == StageDesc::kConvolution_FetchMode) { stage.fOptFlags |= StageDesc::kNoPerspective_OptFlagBit; } stage.setEnabled(VertexUsesStage(s, pdesc.fVertexLayout)); stage.fKernelWidth = static_cast<int8_t>(4 * random.nextF() + 2); } CachedData cachedData; if (!program.genProgram(this->glInterface(), glslVersion, &cachedData)) { return false; } DeleteProgram(this->glInterface(), &cachedData); } return true; }