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 "GrRenderTargetContext.h" 17 #include "GrRenderTargetPriv.h" 18 #include "GrTypesPriv.h" 19 #include "gl/GrGLGpu.h" 20 #include "gl/debug/DebugGLTestContext.h" 21 22 typedef std::vector<SkPoint> SamplePattern; 23 24 static 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 }; 85 constexpr int numTestPatterns = SK_ARRAY_COUNT(kTestPatterns); 86 87 class TestSampleLocationsInterface : public SkNoncopyable { 88 public: 89 virtual void overrideSamplePattern(const SamplePattern&) = 0; 90 virtual ~TestSampleLocationsInterface() {} 91 }; 92 93 void 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 112 static 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->getSampleCount(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 127 void 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) { 133 int patternSize = (int)kTestPatterns[i].size(); 134 int randNumSamples = pick_random_sample_count(patternSize, &rand, ctx->caps()); 135 bottomUps[i] = ctx->makeDeferredRenderTargetContext( 136 SkBackingFit::kExact, 100, 100, kRGBA_8888_GrPixelConfig, nullptr, randNumSamples, 137 GrMipMapped::kNo, kBottomLeft_GrSurfaceOrigin); 138 randNumSamples = pick_random_sample_count(patternSize, &rand, ctx->caps()); 139 topDowns[i] = ctx->makeDeferredRenderTargetContext( 140 SkBackingFit::kExact, 100, 100, kRGBA_8888_GrPixelConfig, nullptr, randNumSamples, 141 GrMipMapped::kNo, kTopLeft_GrSurfaceOrigin); 142 } 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 164 class GLTestSampleLocationsInterface : public TestSampleLocationsInterface, public GrGLInterface { 165 public: 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 196 private: 197 std::unique_ptr<sk_gpu_test::GLTestContext> fTestContext; 198 SamplePattern fSamplePattern; 199 }; 200 201 DEF_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. 206 int supportedSample = ctx->caps()->getSampleCount(2, kRGBA_8888_GrPixelConfig); 207 if (supportedSample < 2) { 208 return; 209 } 210 test_sampleLocations(reporter, testInterface.get(), ctx.get()); 211 } 212 213 #endif 214