• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
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 "GrPipelineBuilder.h"
17 #include "GrRenderTargetContext.h"
18 #include "GrRenderTargetPriv.h"
19 #include "GrTypesPriv.h"
20 #include "gl/GrGLGpu.h"
21 #include "gl/debug/DebugGLTestContext.h"
22 
23 typedef std::vector<SkPoint> SamplePattern;
24 
25 static const SamplePattern kTestPatterns[] = {
26     SamplePattern{ // Intel on mac, msaa8, offscreen.
27         {0.562500, 0.312500},
28         {0.437500, 0.687500},
29         {0.812500, 0.562500},
30         {0.312500, 0.187500},
31         {0.187500, 0.812500},
32         {0.062500, 0.437500},
33         {0.687500, 0.937500},
34         {0.937500, 0.062500}
35     },
36 
37     SamplePattern{ // Intel on mac, msaa8, on-screen.
38         {0.562500, 0.687500},
39         {0.437500, 0.312500},
40         {0.812500, 0.437500},
41         {0.312500, 0.812500},
42         {0.187500, 0.187500},
43         {0.062500, 0.562500},
44         {0.687500, 0.062500},
45         {0.937500, 0.937500}
46     },
47 
48     SamplePattern{ // NVIDIA, msaa16.
49         {0.062500, 0.000000},
50         {0.250000, 0.125000},
51         {0.187500, 0.375000},
52         {0.437500, 0.312500},
53         {0.500000, 0.062500},
54         {0.687500, 0.187500},
55         {0.750000, 0.437500},
56         {0.937500, 0.250000},
57         {0.000000, 0.500000},
58         {0.312500, 0.625000},
59         {0.125000, 0.750000},
60         {0.375000, 0.875000},
61         {0.562500, 0.562500},
62         {0.812500, 0.687500},
63         {0.625000, 0.812500},
64         {0.875000, 0.937500}
65     },
66 
67     SamplePattern{ // NVIDIA, mixed samples, 16:1.
68         {0.250000, 0.125000},
69         {0.625000, 0.812500},
70         {0.500000, 0.062500},
71         {0.812500, 0.687500},
72         {0.187500, 0.375000},
73         {0.875000, 0.937500},
74         {0.125000, 0.750000},
75         {0.750000, 0.437500},
76         {0.937500, 0.250000},
77         {0.312500, 0.625000},
78         {0.437500, 0.312500},
79         {0.000000, 0.500000},
80         {0.375000, 0.875000},
81         {0.687500, 0.187500},
82         {0.062500, 0.000000},
83         {0.562500, 0.562500}
84     }
85 };
86 constexpr int numTestPatterns = SK_ARRAY_COUNT(kTestPatterns);
87 
88 class TestSampleLocationsInterface : public SkNoncopyable {
89 public:
90     virtual void overrideSamplePattern(const SamplePattern&) = 0;
~TestSampleLocationsInterface()91     virtual ~TestSampleLocationsInterface() {}
92 };
93 
construct_dummy_pipeline(GrRenderTargetContext * dc,GrPipeline * pipeline)94 static void construct_dummy_pipeline(GrRenderTargetContext* dc, GrPipeline* pipeline) {
95     GrPipelineBuilder dummyBuilder(GrPaint(), GrAAType::kNone);
96     GrScissorState dummyScissor;
97     GrWindowRectsState dummyWindows;
98 
99     GrProcessorSet::FragmentProcessorAnalysis analysis;
100     GrPipeline::InitArgs args;
101     dummyBuilder.getPipelineInitArgs(&args);
102     args.fRenderTarget = dc->accessRenderTarget();
103     args.fAnalysis = &analysis;
104     args.fCaps = dc->caps();
105     args.fDstTexture = GrXferProcessor::DstTexture();
106     pipeline->init(args);
107 }
108 
assert_equal(skiatest::Reporter * reporter,const SamplePattern & pattern,const GrGpu::MultisampleSpecs & specs,bool flipY)109 void assert_equal(skiatest::Reporter* reporter, const SamplePattern& pattern,
110                   const GrGpu::MultisampleSpecs& specs, bool flipY) {
111     GrAlwaysAssert(specs.fSampleLocations);
112     if ((int)pattern.size() != specs.fEffectiveSampleCnt) {
113         REPORT_FAILURE(reporter, "", SkString("Sample pattern has wrong number of samples."));
114         return;
115     }
116     for (int i = 0; i < specs.fEffectiveSampleCnt; ++i) {
117         SkPoint expectedLocation = specs.fSampleLocations[i];
118         if (flipY) {
119             expectedLocation.fY = 1 - expectedLocation.fY;
120         }
121         if (pattern[i] != expectedLocation) {
122             REPORT_FAILURE(reporter, "", SkString("Sample pattern has wrong sample location."));
123             return;
124         }
125     }
126 }
127 
test_sampleLocations(skiatest::Reporter * reporter,TestSampleLocationsInterface * testInterface,GrContext * ctx)128 void test_sampleLocations(skiatest::Reporter* reporter, TestSampleLocationsInterface* testInterface,
129                           GrContext* ctx) {
130     SkRandom rand;
131     sk_sp<GrRenderTargetContext> bottomUps[numTestPatterns];
132     sk_sp<GrRenderTargetContext> topDowns[numTestPatterns];
133     for (int i = 0; i < numTestPatterns; ++i) {
134         int numSamples = (int)kTestPatterns[i].size();
135         GrAlwaysAssert(numSamples > 1 && SkIsPow2(numSamples));
136         bottomUps[i] = ctx->makeRenderTargetContextWithFallback(
137                            SkBackingFit::kExact, 100, 100, kRGBA_8888_GrPixelConfig, nullptr,
138                            rand.nextRangeU(1 + numSamples / 2, numSamples),
139                            kBottomLeft_GrSurfaceOrigin);
140         topDowns[i] = ctx->makeRenderTargetContextWithFallback(
141                           SkBackingFit::kExact, 100, 100, kRGBA_8888_GrPixelConfig, nullptr,
142                           rand.nextRangeU(1 + numSamples / 2, numSamples),
143                           kTopLeft_GrSurfaceOrigin);
144     }
145 
146     // Ensure all sample locations get queried and/or cached properly.
147     for (int repeat = 0; repeat < 2; ++repeat) {
148         for (int i = 0; i < numTestPatterns; ++i) {
149             testInterface->overrideSamplePattern(kTestPatterns[i]);
150             for (GrRenderTargetContext* dc : {bottomUps[i].get(), topDowns[i].get()}) {
151                 GrPipeline dummyPipeline;
152                 construct_dummy_pipeline(dc, &dummyPipeline);
153                 GrRenderTarget* rt = dc->accessRenderTarget();
154                 assert_equal(reporter, kTestPatterns[i],
155                              rt->renderTargetPriv().getMultisampleSpecs(dummyPipeline),
156                              kBottomLeft_GrSurfaceOrigin == rt->origin());
157             }
158         }
159     }
160 
161 }
162 
163 ////////////////////////////////////////////////////////////////////////////////////////////////////
164 
165 class GLTestSampleLocationsInterface : public TestSampleLocationsInterface, public GrGLInterface {
166 public:
GLTestSampleLocationsInterface()167     GLTestSampleLocationsInterface() : fTestContext(sk_gpu_test::CreateDebugGLTestContext()) {
168         fStandard = fTestContext->gl()->fStandard;
169         fExtensions = fTestContext->gl()->fExtensions;
170         fFunctions = fTestContext->gl()->fFunctions;
171 
172         fFunctions.fGetIntegerv = [&](GrGLenum pname, GrGLint* params) {
173             GrAlwaysAssert(GR_GL_EFFECTIVE_RASTER_SAMPLES != pname);
174             if (GR_GL_SAMPLES == pname) {
175                 GrAlwaysAssert(!fSamplePattern.empty());
176                 *params = (int)fSamplePattern.size();
177             } else {
178                 fTestContext->gl()->fFunctions.fGetIntegerv(pname, params);
179             }
180         };
181 
182         fFunctions.fGetMultisamplefv = [&](GrGLenum pname, GrGLuint index, GrGLfloat* val) {
183             GrAlwaysAssert(GR_GL_SAMPLE_POSITION == pname);
184             val[0] = fSamplePattern[index].fX;
185             val[1] = fSamplePattern[index].fY;
186         };
187     }
188 
operator GrBackendContext()189     operator GrBackendContext() {
190         return reinterpret_cast<GrBackendContext>(static_cast<GrGLInterface*>(this));
191     }
192 
overrideSamplePattern(const SamplePattern & newPattern)193     void overrideSamplePattern(const SamplePattern& newPattern) override {
194         fSamplePattern = newPattern;
195     }
196 
197 private:
198     std::unique_ptr<sk_gpu_test::GLTestContext> fTestContext;
199     SamplePattern                               fSamplePattern;
200 };
201 
202 DEF_GPUTEST(GLSampleLocations, reporter, /*factory*/) {
203     GLTestSampleLocationsInterface testInterface;
204     sk_sp<GrContext> ctx(GrContext::Create(kOpenGL_GrBackend, testInterface));
205     test_sampleLocations(reporter, &testInterface, ctx.get());
206 }
207 
208 #endif
209