Home | History | Annotate | Download | only in tests
      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