From 7e5c6249f18d80553183de050948befaf6e90c6a Mon Sep 17 00:00:00 2001 From: "bsalomon@google.com" Date: Fri, 1 Jun 2012 19:28:26 +0000 Subject: [PATCH] Move GrGpuGL::programUnitTest into its own file Review URL: http://codereview.appspot.com/6272043/ git-svn-id: http://skia.googlecode.com/svn/trunk@4124 2bbb7eff-a529-9590-31e7-b0007b416f81 --- gyp/gpu.gyp | 1 + src/gpu/gl/GrGpuGL.cpp | 4 - src/gpu/gl/GrGpuGL_program.cpp | 223 -------------------------------- src/gpu/gl/GrGpuGL_unittest.cpp | 220 +++++++++++++++++++++++++++++++ 4 files changed, 221 insertions(+), 227 deletions(-) create mode 100644 src/gpu/gl/GrGpuGL_unittest.cpp diff --git a/gyp/gpu.gyp b/gyp/gpu.gyp index bd415b482..100ad8275 100644 --- a/gyp/gpu.gyp +++ b/gyp/gpu.gyp @@ -317,6 +317,7 @@ '../src/gpu/gl/GrGpuGL.cpp', '../src/gpu/gl/GrGpuGL.h', '../src/gpu/gl/GrGpuGL_program.cpp', + '../src/gpu/gl/GrGpuGL_unittest.cpp', '../src/gpu/gl/debug/GrGLCreateDebugInterface.cpp', '../src/gpu/gl/debug/GrFakeRefObj.h', diff --git a/src/gpu/gl/GrGpuGL.cpp b/src/gpu/gl/GrGpuGL.cpp index 7b44035f2..004702feb 100644 --- a/src/gpu/gl/GrGpuGL.cpp +++ b/src/gpu/gl/GrGpuGL.cpp @@ -174,10 +174,6 @@ GrGpuGL::GrGpuGL(const GrGLContextInfo& ctxInfo) : fGLContextInfo(ctxInfo) { fProgramData = NULL; fProgramCache = new ProgramCache(this->glContextInfo()); -#if 0 - this->programUnitTest(); -#endif - fLastSuccessfulStencilFmtIdx = 0; fCanPreserveUnpremulRoundtrip = kUnknown_CanPreserveUnpremulRoundtrip; } diff --git a/src/gpu/gl/GrGpuGL_program.cpp b/src/gpu/gl/GrGpuGL_program.cpp index c349407b9..afbe809e9 100644 --- a/src/gpu/gl/GrGpuGL_program.cpp +++ b/src/gpu/gl/GrGpuGL_program.cpp @@ -7,17 +7,9 @@ #include "GrGpuGL.h" -#include "effects/GrConvolutionEffect.h" -#include "effects/GrMorphologyEffect.h" - #include "GrCustomStage.h" #include "GrGLProgramStage.h" -#include "GrGLSL.h" #include "GrGpuVertex.h" -#include "GrNoncopyable.h" -#include "GrProgramStageFactory.h" -#include "GrRandom.h" -#include "GrStringBuilder.h" #define SKIP_CACHE_CHECK true #define GR_UINT32_MAX static_cast(-1) @@ -116,221 +108,6 @@ void GrGpuGL::abandonResources(){ #define GL_CALL(X) GR_GL_CALL(this->glInterface(), X) -namespace { - -// GrRandoms nextU() values have patterns in the low bits -// So using nextU() % array_count might never take some values. -int random_int(GrRandom* r, int count) { - return (int)(r->nextF() * count); -} - -// min is inclusive, max is exclusive -int random_int(GrRandom* r, int min, int max) { - return (int)(r->nextF() * (max-min)) + min; -} - -bool random_bool(GrRandom* r) { - return r->nextF() > .5f; -} - -typedef GrGLProgram::StageDesc StageDesc; -// TODO: Effects should be able to register themselves for inclusion in the -// randomly generated shaders. They should be able to configure themselves -// randomly. -GrCustomStage* create_random_effect(StageDesc* stageDesc, - GrRandom* random) { - enum EffectType { - kConvolution_EffectType, - kErode_EffectType, - kDilate_EffectType, - - kEffectCount - }; - - // TODO: Remove this when generator doesn't apply this non-custom-stage - // notion to custom stages automatically. - static const uint32_t kMulByAlphaMask = - StageDesc::kMulRGBByAlpha_RoundUp_InConfigFlag | - StageDesc::kMulRGBByAlpha_RoundDown_InConfigFlag; - - static const Gr1DKernelEffect::Direction gKernelDirections[] = { - Gr1DKernelEffect::kX_Direction, - Gr1DKernelEffect::kY_Direction - }; - - // TODO: When matrices are property of the custom-stage then remove the - // no-persp flag code below. - int effect = random_int(random, kEffectCount); - switch (effect) { - case kConvolution_EffectType: { - int direction = random_int(random, 2); - int kernelRadius = random_int(random, 1, 4); - float kernel[GrConvolutionEffect::kMaxKernelWidth]; - for (int i = 0; i < GrConvolutionEffect::kMaxKernelWidth; i++) { - kernel[i] = random->nextF(); - } - // does not work with perspective or mul-by-alpha-mask - stageDesc->fOptFlags |= StageDesc::kNoPerspective_OptFlagBit; - stageDesc->fInConfigFlags &= ~kMulByAlphaMask; - return new GrConvolutionEffect(gKernelDirections[direction], - kernelRadius, - kernel); - } - case kErode_EffectType: { - int direction = random_int(random, 2); - int kernelRadius = random_int(random, 1, 4); - // does not work with perspective or mul-by-alpha-mask - stageDesc->fOptFlags |= StageDesc::kNoPerspective_OptFlagBit; - stageDesc->fInConfigFlags &= ~kMulByAlphaMask; - return new GrMorphologyEffect(gKernelDirections[direction], - kernelRadius, - GrContext::kErode_MorphologyType); - } - case kDilate_EffectType: { - int direction = random_int(random, 2); - int kernelRadius = random_int(random, 1, 4); - // does not work with perspective or mul-by-alpha-mask - stageDesc->fOptFlags |= StageDesc::kNoPerspective_OptFlagBit; - stageDesc->fInConfigFlags &= ~kMulByAlphaMask; - return new GrMorphologyEffect(gKernelDirections[direction], - kernelRadius, - GrContext::kDilate_MorphologyType); - } - default: - GrCrash("Unexpected custom effect type"); - } - return NULL; -} - -} - -bool GrGpuGL::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; - } - - SkAutoTUnref 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; - - 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); - stage.setEnabled(VertexUsesStage(s, pdesc.fVertexLayout)); - static const uint32_t kMulByAlphaMask = - StageDesc::kMulRGBByAlpha_RoundUp_InConfigFlag | - StageDesc::kMulRGBByAlpha_RoundDown_InConfigFlag; - - if (StageDesc::k2x2_FetchMode == stage.fFetchMode) { - stage.fInConfigFlags &= ~kMulByAlphaMask; - } - - bool useCustomEffect = random_bool(&random); - if (useCustomEffect) { - customStages[s].reset(create_random_effect(&stage, &random)); - if (NULL != customStages[s]) { - stage.fCustomStageKey = - customStages[s]->getFactory().glStageKey(*customStages[s]); - } - } - } - CachedData cachedData; - GR_STATIC_ASSERT(sizeof(customStages) == - GrDrawState::kNumStages * sizeof(GrCustomStage*)); - GrCustomStage** stages = reinterpret_cast(&customStages); - if (!program.genProgram(this->glContextInfo(), stages, &cachedData)) { - return false; - } - DeleteProgram(this->glInterface(), &cachedData); - } - return true; -} - void GrGpuGL::flushViewMatrix() { const GrMatrix& vm = this->getDrawState().getViewMatrix(); if (!fProgramData->fViewMatrix.cheapEqualTo(vm)) { diff --git a/src/gpu/gl/GrGpuGL_unittest.cpp b/src/gpu/gl/GrGpuGL_unittest.cpp new file mode 100644 index 000000000..3f923f7d5 --- /dev/null +++ b/src/gpu/gl/GrGpuGL_unittest.cpp @@ -0,0 +1,220 @@ +#include "GrGpuGL.h" + +#include "effects/GrConvolutionEffect.h" +#include "effects/GrMorphologyEffect.h" +#include "GrProgramStageFactory.h" +#include "GrRandom.h" + +namespace { + +// GrRandoms nextU() values have patterns in the low bits +// So using nextU() % array_count might never take some values. +int random_int(GrRandom* r, int count) { + return (int)(r->nextF() * count); +} + +// min is inclusive, max is exclusive +int random_int(GrRandom* r, int min, int max) { + return (int)(r->nextF() * (max-min)) + min; +} + +bool random_bool(GrRandom* r) { + return r->nextF() > .5f; +} + +typedef GrGLProgram::StageDesc StageDesc; +// TODO: Effects should be able to register themselves for inclusion in the +// randomly generated shaders. They should be able to configure themselves +// randomly. +GrCustomStage* create_random_effect(StageDesc* stageDesc, + GrRandom* random) { + enum EffectType { + kConvolution_EffectType, + kErode_EffectType, + kDilate_EffectType, + + kEffectCount + }; + + // TODO: Remove this when generator doesn't apply this non-custom-stage + // notion to custom stages automatically. + static const uint32_t kMulByAlphaMask = + StageDesc::kMulRGBByAlpha_RoundUp_InConfigFlag | + StageDesc::kMulRGBByAlpha_RoundDown_InConfigFlag; + + static const Gr1DKernelEffect::Direction gKernelDirections[] = { + Gr1DKernelEffect::kX_Direction, + Gr1DKernelEffect::kY_Direction + }; + + // TODO: When matrices are property of the custom-stage then remove the + // no-persp flag code below. + int effect = random_int(random, kEffectCount); + switch (effect) { + case kConvolution_EffectType: { + int direction = random_int(random, 2); + int kernelRadius = random_int(random, 1, 4); + float kernel[GrConvolutionEffect::kMaxKernelWidth]; + for (int i = 0; i < GrConvolutionEffect::kMaxKernelWidth; i++) { + kernel[i] = random->nextF(); + } + // does not work with perspective or mul-by-alpha-mask + stageDesc->fOptFlags |= StageDesc::kNoPerspective_OptFlagBit; + stageDesc->fInConfigFlags &= ~kMulByAlphaMask; + return new GrConvolutionEffect(gKernelDirections[direction], + kernelRadius, + kernel); + } + case kErode_EffectType: { + int direction = random_int(random, 2); + int kernelRadius = random_int(random, 1, 4); + // does not work with perspective or mul-by-alpha-mask + stageDesc->fOptFlags |= StageDesc::kNoPerspective_OptFlagBit; + stageDesc->fInConfigFlags &= ~kMulByAlphaMask; + return new GrMorphologyEffect(gKernelDirections[direction], + kernelRadius, + GrContext::kErode_MorphologyType); + } + case kDilate_EffectType: { + int direction = random_int(random, 2); + int kernelRadius = random_int(random, 1, 4); + // does not work with perspective or mul-by-alpha-mask + stageDesc->fOptFlags |= StageDesc::kNoPerspective_OptFlagBit; + stageDesc->fInConfigFlags &= ~kMulByAlphaMask; + return new GrMorphologyEffect(gKernelDirections[direction], + kernelRadius, + GrContext::kDilate_MorphologyType); + } + default: + GrCrash("Unexpected custom effect type"); + } + return NULL; +} +} + +bool GrGpuGL::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; + } + + SkAutoTUnref 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; + + 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); + stage.setEnabled(VertexUsesStage(s, pdesc.fVertexLayout)); + static const uint32_t kMulByAlphaMask = + StageDesc::kMulRGBByAlpha_RoundUp_InConfigFlag | + StageDesc::kMulRGBByAlpha_RoundDown_InConfigFlag; + + if (StageDesc::k2x2_FetchMode == stage.fFetchMode) { + stage.fInConfigFlags &= ~kMulByAlphaMask; + } + + bool useCustomEffect = random_bool(&random); + if (useCustomEffect) { + customStages[s].reset(create_random_effect(&stage, &random)); + if (NULL != customStages[s]) { + stage.fCustomStageKey = + customStages[s]->getFactory().glStageKey(*customStages[s]); + } + } + } + CachedData cachedData; + GR_STATIC_ASSERT(sizeof(customStages) == + GrDrawState::kNumStages * sizeof(GrCustomStage*)); + GrCustomStage** stages = reinterpret_cast(&customStages); + if (!program.genProgram(this->glContextInfo(), stages, &cachedData)) { + return false; + } + DeleteProgram(this->glInterface(), &cachedData); + } + return true; +}