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 23typedef std::vector<SkPoint> SamplePattern; 24 25static 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}; 86constexpr int numTestPatterns = SK_ARRAY_COUNT(kTestPatterns); 87 88class TestSampleLocationsInterface : public SkNoncopyable { 89public: 90 virtual void overrideSamplePattern(const SamplePattern&) = 0; 91 virtual ~TestSampleLocationsInterface() {} 92}; 93 94static 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 109void 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 128void 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 165class GLTestSampleLocationsInterface : public TestSampleLocationsInterface, public GrGLInterface { 166public: 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 189 operator GrBackendContext() { 190 return reinterpret_cast<GrBackendContext>(static_cast<GrGLInterface*>(this)); 191 } 192 193 void overrideSamplePattern(const SamplePattern& newPattern) override { 194 fSamplePattern = newPattern; 195 } 196 197private: 198 std::unique_ptr<sk_gpu_test::GLTestContext> fTestContext; 199 SamplePattern fSamplePattern; 200}; 201 202DEF_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