blob: 56764cfc9bf8e30680c489a728787f816baffda6 [file] [log] [blame]
Robert Phillips7f861922018-01-30 13:13:42 +00001/*
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
15#include "GrAppliedClip.h"
16#include "GrRenderTargetContext.h"
17#include "GrRenderTargetPriv.h"
18#include "GrTypesPriv.h"
19#include "gl/GrGLGpu.h"
20#include "gl/debug/DebugGLTestContext.h"
21
22typedef std::vector<SkPoint> SamplePattern;
23
24static const SamplePattern kTestPatterns[] = {
25 SamplePattern{ // Intel on mac, msaa8, offscreen.
26 {0.562500, 0.312500},
27 {0.437500, 0.687500},
28 {0.812500, 0.562500},
29 {0.312500, 0.187500},
30 {0.187500, 0.812500},
31 {0.062500, 0.437500},
32 {0.687500, 0.937500},
33 {0.937500, 0.062500}
34 },
35
36 SamplePattern{ // Intel on mac, msaa8, on-screen.
37 {0.562500, 0.687500},
38 {0.437500, 0.312500},
39 {0.812500, 0.437500},
40 {0.312500, 0.812500},
41 {0.187500, 0.187500},
42 {0.062500, 0.562500},
43 {0.687500, 0.062500},
44 {0.937500, 0.937500}
45 },
46
47 SamplePattern{ // NVIDIA, msaa16.
48 {0.062500, 0.000000},
49 {0.250000, 0.125000},
50 {0.187500, 0.375000},
51 {0.437500, 0.312500},
52 {0.500000, 0.062500},
53 {0.687500, 0.187500},
54 {0.750000, 0.437500},
55 {0.937500, 0.250000},
56 {0.000000, 0.500000},
57 {0.312500, 0.625000},
58 {0.125000, 0.750000},
59 {0.375000, 0.875000},
60 {0.562500, 0.562500},
61 {0.812500, 0.687500},
62 {0.625000, 0.812500},
63 {0.875000, 0.937500}
64 },
65
66 SamplePattern{ // NVIDIA, mixed samples, 16:1.
67 {0.250000, 0.125000},
68 {0.625000, 0.812500},
69 {0.500000, 0.062500},
70 {0.812500, 0.687500},
71 {0.187500, 0.375000},
72 {0.875000, 0.937500},
73 {0.125000, 0.750000},
74 {0.750000, 0.437500},
75 {0.937500, 0.250000},
76 {0.312500, 0.625000},
77 {0.437500, 0.312500},
78 {0.000000, 0.500000},
79 {0.375000, 0.875000},
80 {0.687500, 0.187500},
81 {0.062500, 0.000000},
82 {0.562500, 0.562500}
83 }
84};
85constexpr int numTestPatterns = SK_ARRAY_COUNT(kTestPatterns);
86
87class TestSampleLocationsInterface : public SkNoncopyable {
88public:
89 virtual void overrideSamplePattern(const SamplePattern&) = 0;
90 virtual ~TestSampleLocationsInterface() {}
91};
92
93void assert_equal(skiatest::Reporter* reporter, const SamplePattern& pattern,
94 const GrGpu::MultisampleSpecs& specs, bool flipY) {
95 GrAlwaysAssert(specs.fSampleLocations);
96 if ((int)pattern.size() != specs.fEffectiveSampleCnt) {
97 REPORT_FAILURE(reporter, "", SkString("Sample pattern has wrong number of samples."));
98 return;
99 }
100 for (int i = 0; i < specs.fEffectiveSampleCnt; ++i) {
101 SkPoint expectedLocation = specs.fSampleLocations[i];
102 if (flipY) {
103 expectedLocation.fY = 1 - expectedLocation.fY;
104 }
105 if (pattern[i] != expectedLocation) {
106 REPORT_FAILURE(reporter, "", SkString("Sample pattern has wrong sample location."));
107 return;
108 }
109 }
110}
111
Brian Salomonbdecacf2018-02-02 20:32:49 -0500112static int pick_random_sample_count(int testPatternSize, SkRandom* rand, const GrCaps* caps) {
113 GrAlwaysAssert(testPatternSize > 1 && SkIsPow2(testPatternSize));
114 int randSampCnt = rand->nextRangeU(1 + testPatternSize / 2, testPatternSize);
115 do {
116 int cnt = caps->getRenderTargetSampleCount(randSampCnt, kRGBA_8888_GrPixelConfig);
117 if (cnt) {
118 return cnt;
119 }
120 --randSampCnt;
121 } while (randSampCnt);
122 // This test assumes an MSAA kRGBA_8888 RTC can be created.
123 GrAlwaysAssert(false);
124 return 0;
125}
126
Robert Phillips7f861922018-01-30 13:13:42 +0000127void test_sampleLocations(skiatest::Reporter* reporter, TestSampleLocationsInterface* testInterface,
128 GrContext* ctx) {
129 SkRandom rand;
130 sk_sp<GrRenderTargetContext> bottomUps[numTestPatterns];
131 sk_sp<GrRenderTargetContext> topDowns[numTestPatterns];
132 for (int i = 0; i < numTestPatterns; ++i) {
Brian Salomonbdecacf2018-02-02 20:32:49 -0500133 int patternSize = (int)kTestPatterns[i].size();
134 int randNumSamples = pick_random_sample_count(patternSize, &rand, ctx->caps());
Robert Phillips7f861922018-01-30 13:13:42 +0000135 bottomUps[i] = ctx->makeDeferredRenderTargetContext(
Brian Salomonbdecacf2018-02-02 20:32:49 -0500136 SkBackingFit::kExact, 100, 100, kRGBA_8888_GrPixelConfig, nullptr, randNumSamples,
137 GrMipMapped::kNo, kBottomLeft_GrSurfaceOrigin);
138 randNumSamples = pick_random_sample_count(patternSize, &rand, ctx->caps());
Robert Phillips7f861922018-01-30 13:13:42 +0000139 topDowns[i] = ctx->makeDeferredRenderTargetContext(
Brian Salomonbdecacf2018-02-02 20:32:49 -0500140 SkBackingFit::kExact, 100, 100, kRGBA_8888_GrPixelConfig, nullptr, randNumSamples,
141 GrMipMapped::kNo, kTopLeft_GrSurfaceOrigin);
Robert Phillips7f861922018-01-30 13:13:42 +0000142 }
143
144 // Ensure all sample locations get queried and/or cached properly.
145 for (int repeat = 0; repeat < 2; ++repeat) {
146 for (int i = 0; i < numTestPatterns; ++i) {
147 testInterface->overrideSamplePattern(kTestPatterns[i]);
148 for (GrRenderTargetContext* rtc : {bottomUps[i].get(), topDowns[i].get()}) {
149 GrPipeline dummyPipeline(rtc->asRenderTargetProxy(),
150 GrPipeline::ScissorState::kDisabled,
151 SkBlendMode::kSrcOver);
152 GrRenderTarget* rt = rtc->accessRenderTarget();
153 assert_equal(reporter, kTestPatterns[i],
154 rt->renderTargetPriv().getMultisampleSpecs(dummyPipeline),
155 kBottomLeft_GrSurfaceOrigin == rtc->asSurfaceProxy()->origin());
156 }
157 }
158 }
159
160}
161
162////////////////////////////////////////////////////////////////////////////////////////////////////
163
164class GLTestSampleLocationsInterface : public TestSampleLocationsInterface, public GrGLInterface {
165public:
166 GLTestSampleLocationsInterface() : fTestContext(sk_gpu_test::CreateDebugGLTestContext()) {
167 fStandard = fTestContext->gl()->fStandard;
168 fExtensions = fTestContext->gl()->fExtensions;
169 fFunctions = fTestContext->gl()->fFunctions;
170
171 fFunctions.fGetIntegerv = [&](GrGLenum pname, GrGLint* params) {
172 GrAlwaysAssert(GR_GL_EFFECTIVE_RASTER_SAMPLES != pname);
173 if (GR_GL_SAMPLES == pname) {
174 GrAlwaysAssert(!fSamplePattern.empty());
175 *params = (int)fSamplePattern.size();
176 } else {
177 fTestContext->gl()->fFunctions.fGetIntegerv(pname, params);
178 }
179 };
180
181 fFunctions.fGetMultisamplefv = [&](GrGLenum pname, GrGLuint index, GrGLfloat* val) {
182 GrAlwaysAssert(GR_GL_SAMPLE_POSITION == pname);
183 val[0] = fSamplePattern[index].fX;
184 val[1] = fSamplePattern[index].fY;
185 };
186 }
187
188 operator GrBackendContext() {
189 return reinterpret_cast<GrBackendContext>(static_cast<GrGLInterface*>(this));
190 }
191
192 void overrideSamplePattern(const SamplePattern& newPattern) override {
193 fSamplePattern = newPattern;
194 }
195
196private:
197 std::unique_ptr<sk_gpu_test::GLTestContext> fTestContext;
198 SamplePattern fSamplePattern;
199};
200
201DEF_GPUTEST(GLSampleLocations, reporter, /* options */) {
202 auto testInterface = sk_make_sp<GLTestSampleLocationsInterface>();
203 sk_sp<GrContext> ctx(GrContext::MakeGL(testInterface));
204
205 // This test relies on at least 2 samples.
Brian Salomonbdecacf2018-02-02 20:32:49 -0500206 int supportedSample = ctx->caps()->getRenderTargetSampleCount(2, kRGBA_8888_GrPixelConfig);
Robert Phillips7f861922018-01-30 13:13:42 +0000207 if (supportedSample < 2) {
208 return;
209 }
210 test_sampleLocations(reporter, testInterface.get(), ctx.get());
211}
212
213#endif