2016-07-06 16:59:43 +00:00
|
|
|
/*
|
|
|
|
* 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
|
|
|
|
|
2017-01-17 17:39:53 +00:00
|
|
|
#include "GrAppliedClip.h"
|
|
|
|
#include "GrPipelineBuilder.h"
|
2016-11-01 15:55:55 +00:00
|
|
|
#include "GrRenderTargetContext.h"
|
2016-07-06 16:59:43 +00:00
|
|
|
#include "GrRenderTargetPriv.h"
|
2016-12-09 20:10:07 +00:00
|
|
|
#include "GrTypesPriv.h"
|
2016-07-06 16:59:43 +00:00
|
|
|
#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() {}
|
|
|
|
};
|
|
|
|
|
2016-11-01 15:55:55 +00:00
|
|
|
static GrPipeline* construct_dummy_pipeline(GrRenderTargetContext* dc, void* storage) {
|
2016-12-09 20:10:07 +00:00
|
|
|
GrPipelineBuilder dummyBuilder(GrPaint(), GrAAType::kNone);
|
2016-11-01 15:55:55 +00:00
|
|
|
GrScissorState dummyScissor;
|
|
|
|
GrWindowRectsState dummyWindows;
|
2016-12-21 14:20:25 +00:00
|
|
|
GrPipelineOptimizations dummyOverrides;
|
2016-11-01 15:55:55 +00:00
|
|
|
|
2017-01-17 17:39:53 +00:00
|
|
|
GrAppliedClip dummyAppliedClip(SkRect::MakeLargest());
|
2016-11-01 15:55:55 +00:00
|
|
|
GrPipeline::CreateArgs args;
|
2017-01-19 14:55:19 +00:00
|
|
|
dummyBuilder.initPipelineCreateArgs(&args);
|
2016-11-01 15:55:55 +00:00
|
|
|
args.fRenderTargetContext = dc;
|
|
|
|
args.fCaps = dc->caps();
|
2017-01-17 17:39:53 +00:00
|
|
|
args.fAppliedClip = &dummyAppliedClip;
|
2016-11-01 15:55:55 +00:00
|
|
|
args.fDstTexture = GrXferProcessor::DstTexture();
|
|
|
|
|
|
|
|
GrPipeline::CreateAt(storage, args, &dummyOverrides);
|
|
|
|
return reinterpret_cast<GrPipeline*>(storage);
|
2016-07-06 16:59:43 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void assert_equal(skiatest::Reporter* reporter, const SamplePattern& pattern,
|
|
|
|
const GrGpu::MultisampleSpecs& specs, bool flipY) {
|
|
|
|
GrAlwaysAssert(specs.fSampleLocations);
|
|
|
|
if ((int)pattern.size() != specs.fEffectiveSampleCnt) {
|
2016-11-01 15:55:55 +00:00
|
|
|
REPORT_FAILURE(reporter, "", SkString("Sample pattern has wrong number of samples."));
|
2016-07-06 16:59:43 +00:00
|
|
|
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) {
|
2016-11-01 15:55:55 +00:00
|
|
|
REPORT_FAILURE(reporter, "", SkString("Sample pattern has wrong sample location."));
|
2016-07-06 16:59:43 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void test_sampleLocations(skiatest::Reporter* reporter, TestSampleLocationsInterface* testInterface,
|
|
|
|
GrContext* ctx) {
|
|
|
|
SkRandom rand;
|
2016-11-01 15:55:55 +00:00
|
|
|
sk_sp<GrRenderTargetContext> bottomUps[numTestPatterns];
|
|
|
|
sk_sp<GrRenderTargetContext> topDowns[numTestPatterns];
|
2016-07-06 16:59:43 +00:00
|
|
|
for (int i = 0; i < numTestPatterns; ++i) {
|
|
|
|
int numSamples = (int)kTestPatterns[i].size();
|
|
|
|
GrAlwaysAssert(numSamples > 1 && SkIsPow2(numSamples));
|
2016-11-01 15:55:55 +00:00
|
|
|
bottomUps[i] = ctx->makeRenderTargetContextWithFallback(
|
|
|
|
SkBackingFit::kExact, 100, 100, kRGBA_8888_GrPixelConfig, nullptr,
|
|
|
|
rand.nextRangeU(1 + numSamples / 2, numSamples),
|
|
|
|
kBottomLeft_GrSurfaceOrigin);
|
|
|
|
topDowns[i] = ctx->makeRenderTargetContextWithFallback(
|
|
|
|
SkBackingFit::kExact, 100, 100, kRGBA_8888_GrPixelConfig, nullptr,
|
|
|
|
rand.nextRangeU(1 + numSamples / 2, numSamples),
|
|
|
|
kTopLeft_GrSurfaceOrigin);
|
2016-07-06 16:59:43 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// Ensure all sample locations get queried and/or cached properly.
|
2016-11-01 15:55:55 +00:00
|
|
|
SkAlignedSTStorage<1, GrPipeline> pipelineStorage;
|
2016-07-06 16:59:43 +00:00
|
|
|
for (int repeat = 0; repeat < 2; ++repeat) {
|
|
|
|
for (int i = 0; i < numTestPatterns; ++i) {
|
|
|
|
testInterface->overrideSamplePattern(kTestPatterns[i]);
|
2016-11-01 15:55:55 +00:00
|
|
|
for (GrRenderTargetContext* dc : {bottomUps[i].get(), topDowns[i].get()}) {
|
|
|
|
GrPipeline* dummyPipe = construct_dummy_pipeline(dc, pipelineStorage.get());
|
|
|
|
GrRenderTarget* rt = dc->accessRenderTarget();
|
|
|
|
assert_equal(reporter, kTestPatterns[i],
|
|
|
|
rt->renderTargetPriv().getMultisampleSpecs(*dummyPipe),
|
|
|
|
kBottomLeft_GrSurfaceOrigin == rt->origin());
|
|
|
|
dummyPipe->~GrPipeline();
|
|
|
|
}
|
2016-07-06 16:59:43 +00:00
|
|
|
}
|
|
|
|
}
|
2016-11-01 15:55:55 +00:00
|
|
|
|
2016-07-06 16:59:43 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
|
|
|
|
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:
|
2016-11-03 18:40:50 +00:00
|
|
|
std::unique_ptr<sk_gpu_test::GLTestContext> fTestContext;
|
2016-07-06 16:59:43 +00:00
|
|
|
SamplePattern fSamplePattern;
|
|
|
|
};
|
|
|
|
|
|
|
|
DEF_GPUTEST(GLSampleLocations, reporter, /*factory*/) {
|
|
|
|
GLTestSampleLocationsInterface testInterface;
|
2016-11-04 15:49:42 +00:00
|
|
|
sk_sp<GrContext> ctx(GrContext::Create(kOpenGL_GrBackend, testInterface));
|
|
|
|
test_sampleLocations(reporter, &testInterface, ctx.get());
|
2016-07-06 16:59:43 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
#endif
|