| Index: tests/GpuSampleLocationsTest.cpp
|
| diff --git a/tests/GpuSampleLocationsTest.cpp b/tests/GpuSampleLocationsTest.cpp
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..5207c6b3ddfb29c6a5a423254f9af17531033d99
|
| --- /dev/null
|
| +++ b/tests/GpuSampleLocationsTest.cpp
|
| @@ -0,0 +1,193 @@
|
| +/*
|
| + * Copyright 2016 Google Inc.
|
| + *
|
| + * Use of this source code is governed by a BSD-style license that can be
|
| + * found in the LICENSE file.
|
| + */
|
| +
|
| +#include "SkTypes.h"
|
| +#include "SkPoint.h"
|
| +#include "Test.h"
|
| +#include <vector>
|
| +
|
| +#if SK_SUPPORT_GPU
|
| +
|
| +#include "GrRenderTargetPriv.h"
|
| +#include "gl/GrGLGpu.h"
|
| +#include "gl/debug/DebugGLTestContext.h"
|
| +
|
| +typedef std::vector<SkPoint> SamplePattern;
|
| +
|
| +static const SamplePattern kTestPatterns[] = {
|
| + SamplePattern{ // Intel on mac, msaa8, offscreen.
|
| + {0.562500, 0.312500},
|
| + {0.437500, 0.687500},
|
| + {0.812500, 0.562500},
|
| + {0.312500, 0.187500},
|
| + {0.187500, 0.812500},
|
| + {0.062500, 0.437500},
|
| + {0.687500, 0.937500},
|
| + {0.937500, 0.062500}
|
| + },
|
| +
|
| + SamplePattern{ // Intel on mac, msaa8, on-screen.
|
| + {0.562500, 0.687500},
|
| + {0.437500, 0.312500},
|
| + {0.812500, 0.437500},
|
| + {0.312500, 0.812500},
|
| + {0.187500, 0.187500},
|
| + {0.062500, 0.562500},
|
| + {0.687500, 0.062500},
|
| + {0.937500, 0.937500}
|
| + },
|
| +
|
| + SamplePattern{ // NVIDIA, msaa16.
|
| + {0.062500, 0.000000},
|
| + {0.250000, 0.125000},
|
| + {0.187500, 0.375000},
|
| + {0.437500, 0.312500},
|
| + {0.500000, 0.062500},
|
| + {0.687500, 0.187500},
|
| + {0.750000, 0.437500},
|
| + {0.937500, 0.250000},
|
| + {0.000000, 0.500000},
|
| + {0.312500, 0.625000},
|
| + {0.125000, 0.750000},
|
| + {0.375000, 0.875000},
|
| + {0.562500, 0.562500},
|
| + {0.812500, 0.687500},
|
| + {0.625000, 0.812500},
|
| + {0.875000, 0.937500}
|
| + },
|
| +
|
| + SamplePattern{ // NVIDIA, mixed samples, 16:1.
|
| + {0.250000, 0.125000},
|
| + {0.625000, 0.812500},
|
| + {0.500000, 0.062500},
|
| + {0.812500, 0.687500},
|
| + {0.187500, 0.375000},
|
| + {0.875000, 0.937500},
|
| + {0.125000, 0.750000},
|
| + {0.750000, 0.437500},
|
| + {0.937500, 0.250000},
|
| + {0.312500, 0.625000},
|
| + {0.437500, 0.312500},
|
| + {0.000000, 0.500000},
|
| + {0.375000, 0.875000},
|
| + {0.687500, 0.187500},
|
| + {0.062500, 0.000000},
|
| + {0.562500, 0.562500}
|
| + }
|
| +};
|
| +constexpr int numTestPatterns = SK_ARRAY_COUNT(kTestPatterns);
|
| +
|
| +class TestSampleLocationsInterface : public SkNoncopyable {
|
| +public:
|
| + virtual void overrideSamplePattern(const SamplePattern&) = 0;
|
| + virtual ~TestSampleLocationsInterface() {}
|
| +};
|
| +
|
| +GrRenderTarget* SK_WARN_UNUSED_RESULT create_render_target(GrContext* ctx, GrSurfaceOrigin origin,
|
| + int numSamples) {
|
| + GrSurfaceDesc desc;
|
| + desc.fFlags = kRenderTarget_GrSurfaceFlag;
|
| + desc.fOrigin = origin;
|
| + desc.fWidth = 100;
|
| + desc.fHeight = 100;
|
| + desc.fConfig = kBGRA_8888_GrPixelConfig;
|
| + desc.fSampleCnt = numSamples;
|
| + return ctx->textureProvider()->createTexture(desc, SkBudgeted::kNo, 0, 0)->asRenderTarget();
|
| +}
|
| +
|
| +void assert_equal(skiatest::Reporter* reporter, const SamplePattern& pattern,
|
| + const GrGpu::MultisampleSpecs& specs, bool flipY) {
|
| + GrAlwaysAssert(specs.fSampleLocations);
|
| + if ((int)pattern.size() != specs.fEffectiveSampleCnt) {
|
| + REPORTER_ASSERT_MESSAGE(reporter, false, "Sample pattern has wrong number of samples.");
|
| + return;
|
| + }
|
| + for (int i = 0; i < specs.fEffectiveSampleCnt; ++i) {
|
| + SkPoint expectedLocation = specs.fSampleLocations[i];
|
| + if (flipY) {
|
| + expectedLocation.fY = 1 - expectedLocation.fY;
|
| + }
|
| + if (pattern[i] != expectedLocation) {
|
| + REPORTER_ASSERT_MESSAGE(reporter, false, "Sample pattern has wrong sample location.");
|
| + return;
|
| + }
|
| + }
|
| +}
|
| +
|
| +void test_sampleLocations(skiatest::Reporter* reporter, TestSampleLocationsInterface* testInterface,
|
| + GrContext* ctx) {
|
| + SkRandom rand;
|
| + SkAutoTUnref<GrRenderTarget> bottomUps[numTestPatterns];
|
| + SkAutoTUnref<GrRenderTarget> topDowns[numTestPatterns];
|
| + for (int i = 0; i < numTestPatterns; ++i) {
|
| + int numSamples = (int)kTestPatterns[i].size();
|
| + GrAlwaysAssert(numSamples > 1 && SkIsPow2(numSamples));
|
| + bottomUps[i].reset(create_render_target(ctx, kBottomLeft_GrSurfaceOrigin,
|
| + rand.nextRangeU(1 + numSamples / 2, numSamples)));
|
| + topDowns[i].reset(create_render_target(ctx, kTopLeft_GrSurfaceOrigin,
|
| + rand.nextRangeU(1 + numSamples / 2, numSamples)));
|
| + }
|
| +
|
| + // Ensure all sample locations get queried and/or cached properly.
|
| + GrStencilSettings dummyStencil;
|
| + for (int repeat = 0; repeat < 2; ++repeat) {
|
| + for (int i = 0; i < numTestPatterns; ++i) {
|
| + testInterface->overrideSamplePattern(kTestPatterns[i]);
|
| + assert_equal(reporter, kTestPatterns[i],
|
| + topDowns[i]->renderTargetPriv().getMultisampleSpecs(dummyStencil), false);
|
| + assert_equal(reporter, kTestPatterns[i],
|
| + bottomUps[i]->renderTargetPriv().getMultisampleSpecs(dummyStencil), true);
|
| + }
|
| + }
|
| +}
|
| +
|
| +////////////////////////////////////////////////////////////////////////////////////////////////////
|
| +
|
| +class GLTestSampleLocationsInterface : public TestSampleLocationsInterface, public GrGLInterface {
|
| +public:
|
| + GLTestSampleLocationsInterface() : fTestContext(sk_gpu_test::CreateDebugGLTestContext()) {
|
| + fStandard = fTestContext->gl()->fStandard;
|
| + fExtensions = fTestContext->gl()->fExtensions;
|
| + fFunctions = fTestContext->gl()->fFunctions;
|
| +
|
| + fFunctions.fGetIntegerv = [&](GrGLenum pname, GrGLint* params) {
|
| + GrAlwaysAssert(GR_GL_EFFECTIVE_RASTER_SAMPLES != pname);
|
| + if (GR_GL_SAMPLES == pname) {
|
| + GrAlwaysAssert(!fSamplePattern.empty());
|
| + *params = (int)fSamplePattern.size();
|
| + } else {
|
| + fTestContext->gl()->fFunctions.fGetIntegerv(pname, params);
|
| + }
|
| + };
|
| +
|
| + fFunctions.fGetMultisamplefv = [&](GrGLenum pname, GrGLuint index, GrGLfloat* val) {
|
| + GrAlwaysAssert(GR_GL_SAMPLE_POSITION == pname);
|
| + val[0] = fSamplePattern[index].fX;
|
| + val[1] = fSamplePattern[index].fY;
|
| + };
|
| + }
|
| +
|
| + operator GrBackendContext() {
|
| + return reinterpret_cast<GrBackendContext>(static_cast<GrGLInterface*>(this));
|
| + }
|
| +
|
| + void overrideSamplePattern(const SamplePattern& newPattern) override {
|
| + fSamplePattern = newPattern;
|
| + }
|
| +
|
| +private:
|
| + SkAutoTDelete<sk_gpu_test::GLTestContext> fTestContext;
|
| + SamplePattern fSamplePattern;
|
| +};
|
| +
|
| +DEF_GPUTEST(GLSampleLocations, reporter, /*factory*/) {
|
| + GLTestSampleLocationsInterface testInterface;
|
| + SkAutoTUnref<GrContext> ctx(GrContext::Create(kOpenGL_GrBackend, testInterface));
|
| + test_sampleLocations(reporter, &testInterface, ctx);
|
| +}
|
| +
|
| +#endif
|
|
|