blob: 5207c6b3ddfb29c6a5a423254f9af17531033d99 [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
15#include "GrRenderTargetPriv.h"
16#include "gl/GrGLGpu.h"
17#include "gl/debug/DebugGLTestContext.h"
18
19typedef std::vector<SkPoint> SamplePattern;
20
21static const SamplePattern kTestPatterns[] = {
22 SamplePattern{ // Intel on mac, msaa8, offscreen.
23 {0.562500, 0.312500},
24 {0.437500, 0.687500},
25 {0.812500, 0.562500},
26 {0.312500, 0.187500},
27 {0.187500, 0.812500},
28 {0.062500, 0.437500},
29 {0.687500, 0.937500},
30 {0.937500, 0.062500}
31 },
32
33 SamplePattern{ // Intel on mac, msaa8, on-screen.
34 {0.562500, 0.687500},
35 {0.437500, 0.312500},
36 {0.812500, 0.437500},
37 {0.312500, 0.812500},
38 {0.187500, 0.187500},
39 {0.062500, 0.562500},
40 {0.687500, 0.062500},
41 {0.937500, 0.937500}
42 },
43
44 SamplePattern{ // NVIDIA, msaa16.
45 {0.062500, 0.000000},
46 {0.250000, 0.125000},
47 {0.187500, 0.375000},
48 {0.437500, 0.312500},
49 {0.500000, 0.062500},
50 {0.687500, 0.187500},
51 {0.750000, 0.437500},
52 {0.937500, 0.250000},
53 {0.000000, 0.500000},
54 {0.312500, 0.625000},
55 {0.125000, 0.750000},
56 {0.375000, 0.875000},
57 {0.562500, 0.562500},
58 {0.812500, 0.687500},
59 {0.625000, 0.812500},
60 {0.875000, 0.937500}
61 },
62
63 SamplePattern{ // NVIDIA, mixed samples, 16:1.
64 {0.250000, 0.125000},
65 {0.625000, 0.812500},
66 {0.500000, 0.062500},
67 {0.812500, 0.687500},
68 {0.187500, 0.375000},
69 {0.875000, 0.937500},
70 {0.125000, 0.750000},
71 {0.750000, 0.437500},
72 {0.937500, 0.250000},
73 {0.312500, 0.625000},
74 {0.437500, 0.312500},
75 {0.000000, 0.500000},
76 {0.375000, 0.875000},
77 {0.687500, 0.187500},
78 {0.062500, 0.000000},
79 {0.562500, 0.562500}
80 }
81};
82constexpr int numTestPatterns = SK_ARRAY_COUNT(kTestPatterns);
83
84class TestSampleLocationsInterface : public SkNoncopyable {
85public:
86 virtual void overrideSamplePattern(const SamplePattern&) = 0;
87 virtual ~TestSampleLocationsInterface() {}
88};
89
90GrRenderTarget* SK_WARN_UNUSED_RESULT create_render_target(GrContext* ctx, GrSurfaceOrigin origin,
91 int numSamples) {
92 GrSurfaceDesc desc;
93 desc.fFlags = kRenderTarget_GrSurfaceFlag;
94 desc.fOrigin = origin;
95 desc.fWidth = 100;
96 desc.fHeight = 100;
97 desc.fConfig = kBGRA_8888_GrPixelConfig;
98 desc.fSampleCnt = numSamples;
99 return ctx->textureProvider()->createTexture(desc, SkBudgeted::kNo, 0, 0)->asRenderTarget();
100}
101
102void assert_equal(skiatest::Reporter* reporter, const SamplePattern& pattern,
103 const GrGpu::MultisampleSpecs& specs, bool flipY) {
104 GrAlwaysAssert(specs.fSampleLocations);
105 if ((int)pattern.size() != specs.fEffectiveSampleCnt) {
106 REPORTER_ASSERT_MESSAGE(reporter, false, "Sample pattern has wrong number of samples.");
107 return;
108 }
109 for (int i = 0; i < specs.fEffectiveSampleCnt; ++i) {
110 SkPoint expectedLocation = specs.fSampleLocations[i];
111 if (flipY) {
112 expectedLocation.fY = 1 - expectedLocation.fY;
113 }
114 if (pattern[i] != expectedLocation) {
115 REPORTER_ASSERT_MESSAGE(reporter, false, "Sample pattern has wrong sample location.");
116 return;
117 }
118 }
119}
120
121void test_sampleLocations(skiatest::Reporter* reporter, TestSampleLocationsInterface* testInterface,
122 GrContext* ctx) {
123 SkRandom rand;
124 SkAutoTUnref<GrRenderTarget> bottomUps[numTestPatterns];
125 SkAutoTUnref<GrRenderTarget> topDowns[numTestPatterns];
126 for (int i = 0; i < numTestPatterns; ++i) {
127 int numSamples = (int)kTestPatterns[i].size();
128 GrAlwaysAssert(numSamples > 1 && SkIsPow2(numSamples));
129 bottomUps[i].reset(create_render_target(ctx, kBottomLeft_GrSurfaceOrigin,
130 rand.nextRangeU(1 + numSamples / 2, numSamples)));
131 topDowns[i].reset(create_render_target(ctx, kTopLeft_GrSurfaceOrigin,
132 rand.nextRangeU(1 + numSamples / 2, numSamples)));
133 }
134
135 // Ensure all sample locations get queried and/or cached properly.
136 GrStencilSettings dummyStencil;
137 for (int repeat = 0; repeat < 2; ++repeat) {
138 for (int i = 0; i < numTestPatterns; ++i) {
139 testInterface->overrideSamplePattern(kTestPatterns[i]);
140 assert_equal(reporter, kTestPatterns[i],
141 topDowns[i]->renderTargetPriv().getMultisampleSpecs(dummyStencil), false);
142 assert_equal(reporter, kTestPatterns[i],
143 bottomUps[i]->renderTargetPriv().getMultisampleSpecs(dummyStencil), true);
144 }
145 }
146}
147
148////////////////////////////////////////////////////////////////////////////////////////////////////
149
150class GLTestSampleLocationsInterface : public TestSampleLocationsInterface, public GrGLInterface {
151public:
152 GLTestSampleLocationsInterface() : fTestContext(sk_gpu_test::CreateDebugGLTestContext()) {
153 fStandard = fTestContext->gl()->fStandard;
154 fExtensions = fTestContext->gl()->fExtensions;
155 fFunctions = fTestContext->gl()->fFunctions;
156
157 fFunctions.fGetIntegerv = [&](GrGLenum pname, GrGLint* params) {
158 GrAlwaysAssert(GR_GL_EFFECTIVE_RASTER_SAMPLES != pname);
159 if (GR_GL_SAMPLES == pname) {
160 GrAlwaysAssert(!fSamplePattern.empty());
161 *params = (int)fSamplePattern.size();
162 } else {
163 fTestContext->gl()->fFunctions.fGetIntegerv(pname, params);
164 }
165 };
166
167 fFunctions.fGetMultisamplefv = [&](GrGLenum pname, GrGLuint index, GrGLfloat* val) {
168 GrAlwaysAssert(GR_GL_SAMPLE_POSITION == pname);
169 val[0] = fSamplePattern[index].fX;
170 val[1] = fSamplePattern[index].fY;
171 };
172 }
173
174 operator GrBackendContext() {
175 return reinterpret_cast<GrBackendContext>(static_cast<GrGLInterface*>(this));
176 }
177
178 void overrideSamplePattern(const SamplePattern& newPattern) override {
179 fSamplePattern = newPattern;
180 }
181
182private:
183 SkAutoTDelete<sk_gpu_test::GLTestContext> fTestContext;
184 SamplePattern fSamplePattern;
185};
186
187DEF_GPUTEST(GLSampleLocations, reporter, /*factory*/) {
188 GLTestSampleLocationsInterface testInterface;
189 SkAutoTUnref<GrContext> ctx(GrContext::Create(kOpenGL_GrBackend, testInterface));
190 test_sampleLocations(reporter, &testInterface, ctx);
191}
192
193#endif