GrVertexLayout GrDrawTarget::GetRectVertexLayout(const GrRect* srcRects[]) { if (NULL == srcRects) { return 0; } GrVertexLayout layout = 0; for (int i = 0; i < GrDrawState::kNumStages; ++i) { int numTC = 0; if (NULL != srcRects[i]) { layout |= StageTexCoordVertexLayoutBit(i, numTC); ++numTC; } } return layout; }
GrVertexLayout GrDrawTarget::GetRectVertexLayout(StageMask stageMask, const GrRect* srcRects[]) { GrVertexLayout layout = 0; for (int i = 0; i < GrDrawState::kNumStages; ++i) { int numTC = 0; if (stageMask & (1 << i)) { if (NULL != srcRects && NULL != srcRects[i]) { layout |= StageTexCoordVertexLayoutBit(i, numTC); ++numTC; } else { layout |= StagePosAsTexCoordVertexLayoutBit(i); } } } return layout; }
void GrDrawTarget::VertexLayoutUnitTest() { // Ensure that our globals mask arrays are correct GrVertexLayout stageTexCoordMasks[GrDrawState::kNumStages]; GrVertexLayout texCoordMasks[GrDrawState::kMaxTexCoords]; gen_mask_arrays(stageTexCoordMasks, texCoordMasks); for (int s = 0; s < GrDrawState::kNumStages; ++s) { GrAssert(stageTexCoordMasks[s] == gStageTexCoordMasks[s]); } for (int t = 0; t < GrDrawState::kMaxTexCoords; ++t) { GrAssert(texCoordMasks[t] == gTexCoordMasks[t]); } // not necessarily exhaustive static bool run; if (!run) { run = true; for (int s = 0; s < GrDrawState::kNumStages; ++s) { GrVertexLayout stageMask = 0; for (int t = 0; t < GrDrawState::kMaxTexCoords; ++t) { stageMask |= StageTexCoordVertexLayoutBit(s,t); } GrAssert(1 == GrDrawState::kMaxTexCoords || !check_layout(stageMask)); GrAssert(gStageTexCoordMasks[s] == stageMask); GrAssert(!check_layout(stageMask)); } for (int t = 0; t < GrDrawState::kMaxTexCoords; ++t) { GrVertexLayout tcMask = 0; GrAssert(!VertexUsesTexCoordIdx(t, 0)); for (int s = 0; s < GrDrawState::kNumStages; ++s) { tcMask |= StageTexCoordVertexLayoutBit(s,t); GrAssert(sizeof(GrPoint) == VertexStageCoordOffset(s, tcMask)); GrAssert(VertexUsesTexCoordIdx(t, tcMask)); GrAssert(2*sizeof(GrPoint) == VertexSize(tcMask)); GrAssert(t == VertexTexCoordsForStage(s, tcMask)); for (int s2 = s + 1; s2 < GrDrawState::kNumStages; ++s2) { GrAssert(-1 == VertexTexCoordsForStage(s2, tcMask)); #if GR_DEBUG GrVertexLayout posAsTex = tcMask; #endif GrAssert(0 == VertexStageCoordOffset(s2, posAsTex)); GrAssert(2*sizeof(GrPoint) == VertexSize(posAsTex)); GrAssert(-1 == VertexTexCoordsForStage(s2, posAsTex)); GrAssert(-1 == VertexEdgeOffset(posAsTex)); } GrAssert(-1 == VertexEdgeOffset(tcMask)); GrAssert(-1 == VertexColorOffset(tcMask)); GrAssert(-1 == VertexCoverageOffset(tcMask)); #if GR_DEBUG GrVertexLayout withColor = tcMask | kColor_VertexLayoutBit; #endif GrAssert(-1 == VertexCoverageOffset(withColor)); GrAssert(2*sizeof(GrPoint) == VertexColorOffset(withColor)); GrAssert(2*sizeof(GrPoint) + sizeof(GrColor) == VertexSize(withColor)); #if GR_DEBUG GrVertexLayout withEdge = tcMask | kEdge_VertexLayoutBit; #endif GrAssert(-1 == VertexColorOffset(withEdge)); GrAssert(2*sizeof(GrPoint) == VertexEdgeOffset(withEdge)); GrAssert(4*sizeof(GrPoint) == VertexSize(withEdge)); #if GR_DEBUG GrVertexLayout withColorAndEdge = withColor | kEdge_VertexLayoutBit; #endif GrAssert(2*sizeof(GrPoint) == VertexColorOffset(withColorAndEdge)); GrAssert(2*sizeof(GrPoint) + sizeof(GrColor) == VertexEdgeOffset(withColorAndEdge)); GrAssert(4*sizeof(GrPoint) + sizeof(GrColor) == VertexSize(withColorAndEdge)); #if GR_DEBUG GrVertexLayout withCoverage = tcMask | kCoverage_VertexLayoutBit; #endif GrAssert(-1 == VertexColorOffset(withCoverage)); GrAssert(2*sizeof(GrPoint) == VertexCoverageOffset(withCoverage)); GrAssert(2*sizeof(GrPoint) + sizeof(GrColor) == VertexSize(withCoverage)); #if GR_DEBUG GrVertexLayout withCoverageAndColor = tcMask | kCoverage_VertexLayoutBit | kColor_VertexLayoutBit; #endif GrAssert(2*sizeof(GrPoint) == VertexColorOffset(withCoverageAndColor)); GrAssert(2*sizeof(GrPoint) + sizeof(GrColor) == VertexCoverageOffset(withCoverageAndColor)); GrAssert(2*sizeof(GrPoint) + 2 * sizeof(GrColor) == VertexSize(withCoverageAndColor)); } GrAssert(gTexCoordMasks[t] == tcMask); GrAssert(check_layout(tcMask)); int stageOffsets[GrDrawState::kNumStages]; int colorOffset; int edgeOffset; int coverageOffset; int size; size = VertexSizeAndOffsetsByStage(tcMask, stageOffsets, &colorOffset, &coverageOffset, &edgeOffset); GrAssert(2*sizeof(GrPoint) == size); GrAssert(-1 == colorOffset); GrAssert(-1 == coverageOffset); GrAssert(-1 == edgeOffset); for (int s = 0; s < GrDrawState::kNumStages; ++s) { GrAssert(sizeof(GrPoint) == stageOffsets[s]); GrAssert(sizeof(GrPoint) == VertexStageCoordOffset(s, tcMask)); } } } }
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 GrGpuGL::programUnitTest() { GrTextureDesc dummyDesc; dummyDesc.fConfig = kSkia8888_PM_GrPixelConfig; dummyDesc.fWidth = 34; dummyDesc.fHeight = 18; SkAutoTUnref<GrTexture> dummyTexture1(this->createTexture(dummyDesc, NULL, 0)); dummyDesc.fConfig = kAlpha_8_GrPixelConfig; dummyDesc.fWidth = 16; dummyDesc.fHeight = 22; SkAutoTUnref<GrTexture> dummyTexture2(this->createTexture(dummyDesc, NULL, 0)); // GrGLSLGeneration glslGeneration = GrGetGLSLGeneration(this->glBinding(), this->glInterface()); static const int STAGE_OPTS[] = { 0, StageDesc::kNoPerspective_OptFlagBit, }; static const int IN_CONFIG_FLAGS[] = { StageDesc::kNone_InConfigFlag, StageDesc::kSmearAlpha_InConfigFlag, }; 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 ProgramDesc pdesc; 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().geometryShaderSupport() && random_bool(&random); #endif bool edgeAA = random_bool(&random); if (edgeAA) { pdesc.fVertexLayout |= GrDrawTarget::kEdge_VertexLayoutBit; if (this->getCaps().shaderDerivativeSupport()) { pdesc.fVertexEdgeType = (GrDrawState::VertexEdgeType) random_int(&random, GrDrawState::kVertexEdgeTypeCnt); } else { pdesc.fVertexEdgeType = GrDrawState::kHairLine_EdgeType; } } else { } pdesc.fColorMatrixEnabled = random_bool(&random); if (this->getCaps().dualSourceBlendingSupport()) { pdesc.fDualSrcOutput = random_int(&random, ProgramDesc::kDualSrcOutputCnt); } else { pdesc.fDualSrcOutput = ProgramDesc::kNone_DualSrcOutput; } SkAutoTUnref<const GrCustomStage> customStages[GrDrawState::kNumStages]; for (int s = 0; s < GrDrawState::kNumStages; ++s) { StageDesc& stage = pdesc.fStages[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); } stage.setEnabled(true); } // use text-formatted verts? if (random_bool(&random)) { pdesc.fVertexLayout |= kTextFormat_VertexLayoutBit; } stage.fCustomStageKey = 0; 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))]; if (stage.isEnabled()) { GrTexture* dummyTextures[] = {dummyTexture1.get(), dummyTexture2.get()}; customStages[s].reset(create_random_effect(&stage, &random, getContext(), dummyTextures)); if (NULL != customStages[s]) { stage.fCustomStageKey = customStages[s]->getFactory().glStageKey(*customStages[s], this->glCaps()); } } } GR_STATIC_ASSERT(sizeof(customStages) == GrDrawState::kNumStages * sizeof(GrCustomStage*)); const GrCustomStage** stages = reinterpret_cast<const GrCustomStage**>(&customStages); SkAutoTUnref<GrGLProgram> program(GrGLProgram::Create(this->glContextInfo(), pdesc, stages)); if (NULL == program.get()) { return false; } } return true; }
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; }
void GrDrawTarget::VertexLayoutUnitTest() { // not necessarily exhaustive static bool run; if (!run) { run = true; for (int s = 0; s < kNumStages; ++s) { GrAssert(!VertexUsesStage(s, 0)); GrAssert(-1 == VertexStageCoordOffset(s, 0)); GrVertexLayout stageMask = 0; for (int t = 0; t < kMaxTexCoords; ++t) { stageMask |= StageTexCoordVertexLayoutBit(s,t); } GrAssert(1 == kMaxTexCoords || !check_layout(stageMask)); GrAssert(stage_tex_coord_mask(s) == stageMask); stageMask |= StagePosAsTexCoordVertexLayoutBit(s); GrAssert(stage_mask(s) == stageMask); GrAssert(!check_layout(stageMask)); } for (int t = 0; t < kMaxTexCoords; ++t) { GrVertexLayout tcMask = 0; GrAssert(!VertexUsesTexCoordIdx(t, 0)); for (int s = 0; s < kNumStages; ++s) { tcMask |= StageTexCoordVertexLayoutBit(s,t); GrAssert(VertexUsesStage(s, tcMask)); GrAssert(sizeof(GrPoint) == VertexStageCoordOffset(s, tcMask)); GrAssert(VertexUsesTexCoordIdx(t, tcMask)); GrAssert(2*sizeof(GrPoint) == VertexSize(tcMask)); GrAssert(t == VertexTexCoordsForStage(s, tcMask)); for (int s2 = s + 1; s2 < kNumStages; ++s2) { GrAssert(-1 == VertexStageCoordOffset(s2, tcMask)); GrAssert(!VertexUsesStage(s2, tcMask)); GrAssert(-1 == VertexTexCoordsForStage(s2, tcMask)); #if GR_DEBUG GrVertexLayout posAsTex = tcMask | StagePosAsTexCoordVertexLayoutBit(s2); #endif GrAssert(0 == VertexStageCoordOffset(s2, posAsTex)); GrAssert(VertexUsesStage(s2, posAsTex)); GrAssert(2*sizeof(GrPoint) == VertexSize(posAsTex)); GrAssert(-1 == VertexTexCoordsForStage(s2, posAsTex)); GrAssert(-1 == VertexEdgeOffset(posAsTex)); } GrAssert(-1 == VertexEdgeOffset(tcMask)); GrAssert(-1 == VertexColorOffset(tcMask)); GrAssert(-1 == VertexCoverageOffset(tcMask)); #if GR_DEBUG GrVertexLayout withColor = tcMask | kColor_VertexLayoutBit; #endif GrAssert(-1 == VertexCoverageOffset(withColor)); GrAssert(2*sizeof(GrPoint) == VertexColorOffset(withColor)); GrAssert(2*sizeof(GrPoint) + sizeof(GrColor) == VertexSize(withColor)); #if GR_DEBUG GrVertexLayout withEdge = tcMask | kEdge_VertexLayoutBit; #endif GrAssert(-1 == VertexColorOffset(withEdge)); GrAssert(2*sizeof(GrPoint) == VertexEdgeOffset(withEdge)); GrAssert(4*sizeof(GrPoint) == VertexSize(withEdge)); #if GR_DEBUG GrVertexLayout withColorAndEdge = withColor | kEdge_VertexLayoutBit; #endif GrAssert(2*sizeof(GrPoint) == VertexColorOffset(withColorAndEdge)); GrAssert(2*sizeof(GrPoint) + sizeof(GrColor) == VertexEdgeOffset(withColorAndEdge)); GrAssert(4*sizeof(GrPoint) + sizeof(GrColor) == VertexSize(withColorAndEdge)); #if GR_DEBUG GrVertexLayout withCoverage = tcMask | kCoverage_VertexLayoutBit; #endif GrAssert(-1 == VertexColorOffset(withCoverage)); GrAssert(2*sizeof(GrPoint) == VertexCoverageOffset(withCoverage)); GrAssert(2*sizeof(GrPoint) + sizeof(GrColor) == VertexSize(withCoverage)); #if GR_DEBUG GrVertexLayout withCoverageAndColor = tcMask | kCoverage_VertexLayoutBit | kColor_VertexLayoutBit; #endif GrAssert(2*sizeof(GrPoint) == VertexColorOffset(withCoverageAndColor)); GrAssert(2*sizeof(GrPoint) + sizeof(GrColor) == VertexCoverageOffset(withCoverageAndColor)); GrAssert(2*sizeof(GrPoint) + 2 * sizeof(GrColor) == VertexSize(withCoverageAndColor)); } GrAssert(tex_coord_idx_mask(t) == tcMask); GrAssert(check_layout(tcMask)); int stageOffsets[kNumStages]; int colorOffset; int edgeOffset; int coverageOffset; int size; size = VertexSizeAndOffsetsByStage(tcMask, stageOffsets, &colorOffset, &coverageOffset, &edgeOffset); GrAssert(2*sizeof(GrPoint) == size); GrAssert(-1 == colorOffset); GrAssert(-1 == coverageOffset); GrAssert(-1 == edgeOffset); for (int s = 0; s < kNumStages; ++s) { GrAssert(VertexUsesStage(s, tcMask)); GrAssert(sizeof(GrPoint) == stageOffsets[s]); GrAssert(sizeof(GrPoint) == VertexStageCoordOffset(s, tcMask)); } } } }
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; }