skia2/tests/GLProgramsTest.cpp
scroggo@google.com a0c2bc2438 Make flattenables no longer depend on global static initializers.
Instead, force all builds to call InitializeFlattenables.

Remove the make_debugger script, which was created to force
rebuilding without global static initializers so that all flattenables
would be linked. It is no longer necessary since all flattenables
will be linked thanks to InitializeFlattenables, which now can (and
must) be called when global static initializers are turned on.

BUG=https://code.google.com/p/skia/issues/detail?id=903
BUG=https://code.google.com/p/skia/issues/detail?id=902

Review URL: https://codereview.appspot.com/6548044

git-svn-id: http://skia.googlecode.com/svn/trunk@5642 2bbb7eff-a529-9590-31e7-b0007b416f81
2012-09-21 17:54:46 +00:00

198 lines
7.0 KiB
C++

/*
* Copyright 2011 Google Inc.
*
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
// This is a GPU-backend specific test. It relies on static intializers to work
#include "SkTypes.h"
#if SK_SUPPORT_GPU && SK_ALLOW_STATIC_GLOBAL_INITIALIZERS
#include "gl/GrGpuGL.h"
#include "GrProgramStageFactory.h"
#include "effects/GrConfigConversionEffect.h"
#include "GrRandom.h"
#include "Test.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);
}
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.
const GrCustomStage* create_random_effect(StageDesc* stageDesc,
GrRandom* random,
GrContext* context,
GrTexture* dummyTextures[]) {
// The new code uses SkRandom not GrRandom.
// TODO: Remove GrRandom.
SkRandom sk_random;
sk_random.setSeed(random->nextU());
GrCustomStage* stage = GrCustomStageTestFactory::CreateStage(&sk_random,
context,
dummyTextures);
GrAssert(stage);
return stage;
}
}
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 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))];
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;
}
static void GLProgramsTest(skiatest::Reporter* reporter, GrContext* context) {
GrGpuGL* shadersGpu = static_cast<GrGpuGL*>(context->getGpu());
REPORTER_ASSERT(reporter, shadersGpu->programUnitTest());
}
#include "TestClassDef.h"
DEFINE_GPUTESTCLASS("GLPrograms", GLProgramsTestClass, GLProgramsTest)
// This is evil evil evil. The linker may throw away whole translation units as dead code if it
// thinks none of the functions are called. It will do this even if there are static initilializers
// in the unit that could pass pointers to functions from the unit out to other translation units!
// We force some of the effects that would otherwise be discarded to link here.
#include "SkLightingImageFilter.h"
#include "SkMagnifierImageFilter.h"
void forceLinking();
void forceLinking() {
SkLightingImageFilter::CreateDistantLitDiffuse(SkPoint3(0,0,0), 0, 0, 0);
SkMagnifierImageFilter mag(SkRect::MakeWH(SK_Scalar1, SK_Scalar1), SK_Scalar1);
GrConfigConversionEffect::Create(NULL, false);
}
#endif