blob: 31ada9d968f9824c401e8e9e81c9cd9f93d387e6 [file] [log] [blame]
csmartdalton0d28e572016-07-06 09:59:43 -07001/*
2 * Copyright 2016 Google Inc.
3 *
4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file.
6 */
7
8#include "SkTypes.h"
9#include "SkPoint.h"
10#include "Test.h"
11#include <vector>
12
13#if SK_SUPPORT_GPU
14
csmartdaltonc633abb2016-11-01 08:55:55 -070015#include "GrRenderTargetContext.h"
csmartdalton0d28e572016-07-06 09:59:43 -070016#include "GrRenderTargetPriv.h"
csmartdaltonc633abb2016-11-01 08:55:55 -070017#include "GrPipelineBuilder.h"
csmartdalton0d28e572016-07-06 09:59:43 -070018#include "gl/GrGLGpu.h"
19#include "gl/debug/DebugGLTestContext.h"
20
21typedef std::vector<SkPoint> SamplePattern;
22
23static const SamplePattern kTestPatterns[] = {
24 SamplePattern{ // Intel on mac, msaa8, offscreen.
25 {0.562500, 0.312500},
26 {0.437500, 0.687500},
27 {0.812500, 0.562500},
28 {0.312500, 0.187500},
29 {0.187500, 0.812500},
30 {0.062500, 0.437500},
31 {0.687500, 0.937500},
32 {0.937500, 0.062500}
33 },
34
35 SamplePattern{ // Intel on mac, msaa8, on-screen.
36 {0.562500, 0.687500},
37 {0.437500, 0.312500},
38 {0.812500, 0.437500},
39 {0.312500, 0.812500},
40 {0.187500, 0.187500},
41 {0.062500, 0.562500},
42 {0.687500, 0.062500},
43 {0.937500, 0.937500}
44 },
45
46 SamplePattern{ // NVIDIA, msaa16.
47 {0.062500, 0.000000},
48 {0.250000, 0.125000},
49 {0.187500, 0.375000},
50 {0.437500, 0.312500},
51 {0.500000, 0.062500},
52 {0.687500, 0.187500},
53 {0.750000, 0.437500},
54 {0.937500, 0.250000},
55 {0.000000, 0.500000},
56 {0.312500, 0.625000},
57 {0.125000, 0.750000},
58 {0.375000, 0.875000},
59 {0.562500, 0.562500},
60 {0.812500, 0.687500},
61 {0.625000, 0.812500},
62 {0.875000, 0.937500}
63 },
64
65 SamplePattern{ // NVIDIA, mixed samples, 16:1.
66 {0.250000, 0.125000},
67 {0.625000, 0.812500},
68 {0.500000, 0.062500},
69 {0.812500, 0.687500},
70 {0.187500, 0.375000},
71 {0.875000, 0.937500},
72 {0.125000, 0.750000},
73 {0.750000, 0.437500},
74 {0.937500, 0.250000},
75 {0.312500, 0.625000},
76 {0.437500, 0.312500},
77 {0.000000, 0.500000},
78 {0.375000, 0.875000},
79 {0.687500, 0.187500},
80 {0.062500, 0.000000},
81 {0.562500, 0.562500}
82 }
83};
84constexpr int numTestPatterns = SK_ARRAY_COUNT(kTestPatterns);
85
86class TestSampleLocationsInterface : public SkNoncopyable {
87public:
88 virtual void overrideSamplePattern(const SamplePattern&) = 0;
89 virtual ~TestSampleLocationsInterface() {}
90};
91
csmartdaltonc633abb2016-11-01 08:55:55 -070092static GrPipeline* construct_dummy_pipeline(GrRenderTargetContext* dc, void* storage) {
93 GrPipelineBuilder dummyBuilder;
94 GrScissorState dummyScissor;
95 GrWindowRectsState dummyWindows;
96 GrXPOverridesForBatch dummyOverrides;
97
98 GrPipeline::CreateArgs args;
99 args.fPipelineBuilder = &dummyBuilder;
100 args.fRenderTargetContext = dc;
101 args.fCaps = dc->caps();
102 args.fOpts = GrPipelineOptimizations();
103 args.fScissor = &dummyScissor;
104 args.fWindowRectsState = &dummyWindows;
105 args.fHasStencilClip = false;
106 args.fDstTexture = GrXferProcessor::DstTexture();
107
108 GrPipeline::CreateAt(storage, args, &dummyOverrides);
109 return reinterpret_cast<GrPipeline*>(storage);
csmartdalton0d28e572016-07-06 09:59:43 -0700110}
111
112void assert_equal(skiatest::Reporter* reporter, const SamplePattern& pattern,
113 const GrGpu::MultisampleSpecs& specs, bool flipY) {
114 GrAlwaysAssert(specs.fSampleLocations);
115 if ((int)pattern.size() != specs.fEffectiveSampleCnt) {
csmartdaltonc633abb2016-11-01 08:55:55 -0700116 REPORT_FAILURE(reporter, "", SkString("Sample pattern has wrong number of samples."));
csmartdalton0d28e572016-07-06 09:59:43 -0700117 return;
118 }
119 for (int i = 0; i < specs.fEffectiveSampleCnt; ++i) {
120 SkPoint expectedLocation = specs.fSampleLocations[i];
121 if (flipY) {
122 expectedLocation.fY = 1 - expectedLocation.fY;
123 }
124 if (pattern[i] != expectedLocation) {
csmartdaltonc633abb2016-11-01 08:55:55 -0700125 REPORT_FAILURE(reporter, "", SkString("Sample pattern has wrong sample location."));
csmartdalton0d28e572016-07-06 09:59:43 -0700126 return;
127 }
128 }
129}
130
131void test_sampleLocations(skiatest::Reporter* reporter, TestSampleLocationsInterface* testInterface,
132 GrContext* ctx) {
133 SkRandom rand;
csmartdaltonc633abb2016-11-01 08:55:55 -0700134 sk_sp<GrRenderTargetContext> bottomUps[numTestPatterns];
135 sk_sp<GrRenderTargetContext> topDowns[numTestPatterns];
csmartdalton0d28e572016-07-06 09:59:43 -0700136 for (int i = 0; i < numTestPatterns; ++i) {
137 int numSamples = (int)kTestPatterns[i].size();
138 GrAlwaysAssert(numSamples > 1 && SkIsPow2(numSamples));
csmartdaltonc633abb2016-11-01 08:55:55 -0700139 bottomUps[i] = ctx->makeRenderTargetContextWithFallback(
140 SkBackingFit::kExact, 100, 100, kRGBA_8888_GrPixelConfig, nullptr,
141 rand.nextRangeU(1 + numSamples / 2, numSamples),
142 kBottomLeft_GrSurfaceOrigin);
143 topDowns[i] = ctx->makeRenderTargetContextWithFallback(
144 SkBackingFit::kExact, 100, 100, kRGBA_8888_GrPixelConfig, nullptr,
145 rand.nextRangeU(1 + numSamples / 2, numSamples),
146 kTopLeft_GrSurfaceOrigin);
csmartdalton0d28e572016-07-06 09:59:43 -0700147 }
148
149 // Ensure all sample locations get queried and/or cached properly.
csmartdaltonc633abb2016-11-01 08:55:55 -0700150 SkAlignedSTStorage<1, GrPipeline> pipelineStorage;
csmartdalton0d28e572016-07-06 09:59:43 -0700151 for (int repeat = 0; repeat < 2; ++repeat) {
152 for (int i = 0; i < numTestPatterns; ++i) {
153 testInterface->overrideSamplePattern(kTestPatterns[i]);
csmartdaltonc633abb2016-11-01 08:55:55 -0700154 for (GrRenderTargetContext* dc : {bottomUps[i].get(), topDowns[i].get()}) {
155 GrPipeline* dummyPipe = construct_dummy_pipeline(dc, pipelineStorage.get());
156 GrRenderTarget* rt = dc->accessRenderTarget();
157 assert_equal(reporter, kTestPatterns[i],
158 rt->renderTargetPriv().getMultisampleSpecs(*dummyPipe),
159 kBottomLeft_GrSurfaceOrigin == rt->origin());
160 dummyPipe->~GrPipeline();
161 }
csmartdalton0d28e572016-07-06 09:59:43 -0700162 }
163 }
csmartdaltonc633abb2016-11-01 08:55:55 -0700164
csmartdalton0d28e572016-07-06 09:59:43 -0700165}
166
167////////////////////////////////////////////////////////////////////////////////////////////////////
168
169class GLTestSampleLocationsInterface : public TestSampleLocationsInterface, public GrGLInterface {
170public:
171 GLTestSampleLocationsInterface() : fTestContext(sk_gpu_test::CreateDebugGLTestContext()) {
172 fStandard = fTestContext->gl()->fStandard;
173 fExtensions = fTestContext->gl()->fExtensions;
174 fFunctions = fTestContext->gl()->fFunctions;
175
176 fFunctions.fGetIntegerv = [&](GrGLenum pname, GrGLint* params) {
177 GrAlwaysAssert(GR_GL_EFFECTIVE_RASTER_SAMPLES != pname);
178 if (GR_GL_SAMPLES == pname) {
179 GrAlwaysAssert(!fSamplePattern.empty());
180 *params = (int)fSamplePattern.size();
181 } else {
182 fTestContext->gl()->fFunctions.fGetIntegerv(pname, params);
183 }
184 };
185
186 fFunctions.fGetMultisamplefv = [&](GrGLenum pname, GrGLuint index, GrGLfloat* val) {
187 GrAlwaysAssert(GR_GL_SAMPLE_POSITION == pname);
188 val[0] = fSamplePattern[index].fX;
189 val[1] = fSamplePattern[index].fY;
190 };
191 }
192
193 operator GrBackendContext() {
194 return reinterpret_cast<GrBackendContext>(static_cast<GrGLInterface*>(this));
195 }
196
197 void overrideSamplePattern(const SamplePattern& newPattern) override {
198 fSamplePattern = newPattern;
199 }
200
201private:
Ben Wagner145dbcd2016-11-03 14:40:50 -0400202 std::unique_ptr<sk_gpu_test::GLTestContext> fTestContext;
csmartdalton0d28e572016-07-06 09:59:43 -0700203 SamplePattern fSamplePattern;
204};
205
206DEF_GPUTEST(GLSampleLocations, reporter, /*factory*/) {
207 GLTestSampleLocationsInterface testInterface;
Hal Canary342b7ac2016-11-04 11:49:42 -0400208 sk_sp<GrContext> ctx(GrContext::Create(kOpenGL_GrBackend, testInterface));
209 test_sampleLocations(reporter, &testInterface, ctx.get());
csmartdalton0d28e572016-07-06 09:59:43 -0700210}
211
212#endif