| /* |
| * Copyright 2017 Google Inc. |
| * |
| * Use of this source code is governed by a BSD-style license that can be |
| * found in the LICENSE file. |
| */ |
| |
| #include "SkTypes.h" |
| |
| #if SK_SUPPORT_GPU |
| |
| #include "SkCanvas.h" |
| #include "SkDeferredDisplayListRecorder.h" |
| #include "SkGpuDevice.h" |
| #include "SkSurface.h" |
| #include "SkSurface_Gpu.h" |
| #include "SkSurfaceCharacterization.h" |
| #include "SkSurfaceProps.h" |
| #include "Test.h" |
| |
| class SurfaceParameters { |
| public: |
| static const int kNumParams = 8; |
| static const int kSampleCount = 5; |
| |
| SurfaceParameters() |
| : fWidth(64) |
| , fHeight(64) |
| , fOrigin(kTopLeft_GrSurfaceOrigin) |
| , fColorType(kRGBA_8888_SkColorType) |
| , fColorSpace(SkColorSpace::MakeSRGB()) |
| , fSampleCount(0) |
| , fSurfaceProps(0x0, kUnknown_SkPixelGeometry) { |
| } |
| |
| int sampleCount() const { return fSampleCount; } |
| |
| // Modify the SurfaceParameters in just one way |
| void modify(int i) { |
| switch (i) { |
| case 0: |
| fWidth = 63; |
| break; |
| case 1: |
| fHeight = 63; |
| break; |
| case 2: |
| fOrigin = kBottomLeft_GrSurfaceOrigin; |
| break; |
| case 3: |
| fColorType = kRGBA_F16_SkColorType; |
| break; |
| case 4: |
| fColorSpace = SkColorSpace::MakeSRGBLinear(); |
| break; |
| case kSampleCount: |
| fSampleCount = 4; |
| break; |
| case 6: |
| fSurfaceProps = SkSurfaceProps(0x0, kRGB_H_SkPixelGeometry); |
| break; |
| case 7: |
| fSurfaceProps = SkSurfaceProps(SkSurfaceProps::kUseDeviceIndependentFonts_Flag, |
| kUnknown_SkPixelGeometry); |
| break; |
| } |
| } |
| |
| // Create the surface with the current set of parameters |
| sk_sp<SkSurface> make(GrContext* context) const { |
| // Note that Ganesh doesn't make use of the SkImageInfo's alphaType |
| SkImageInfo ii = SkImageInfo::Make(fWidth, fHeight, fColorType, |
| kPremul_SkAlphaType, fColorSpace); |
| |
| return SkSurface::MakeRenderTarget(context, SkBudgeted::kYes, ii, fSampleCount, |
| fOrigin, &fSurfaceProps); |
| } |
| |
| private: |
| int fWidth; |
| int fHeight; |
| GrSurfaceOrigin fOrigin; |
| SkColorType fColorType; |
| sk_sp<SkColorSpace> fColorSpace; |
| int fSampleCount; |
| SkSurfaceProps fSurfaceProps; |
| }; |
| |
| // This tests SkSurfaceCharacterization/SkSurface compatibility |
| DEF_GPUTEST_FOR_ALL_CONTEXTS(SkSurfaceCharacterization, reporter, ctxInfo) { |
| GrContext* context = ctxInfo.grContext(); |
| |
| std::unique_ptr<SkDeferredDisplayList> ddl; |
| |
| // First, create a DDL using the stock SkSurface parameters |
| { |
| SurfaceParameters params; |
| |
| sk_sp<SkSurface> s = params.make(context); |
| if (!s) { |
| return; |
| } |
| |
| SkSurfaceCharacterization c; |
| SkAssertResult(s->characterize(&c)); |
| |
| SkDeferredDisplayListRecorder r(c); |
| SkCanvas* canvas = r.getCanvas(); |
| if (!canvas) { |
| return; |
| } |
| |
| canvas->drawRect(SkRect::MakeXYWH(10, 10, 10, 10), SkPaint()); |
| ddl = r.detach(); |
| |
| REPORTER_ASSERT(reporter, s->draw(ddl.get())); |
| } |
| |
| // Then, alter each parameter in turn and check that the DDL & surface are incompatible |
| for (int i = 0; i < SurfaceParameters::kNumParams; ++i) { |
| SurfaceParameters params; |
| params.modify(i); |
| |
| sk_sp<SkSurface> s = params.make(context); |
| if (!s) { |
| continue; |
| } |
| |
| if (SurfaceParameters::kSampleCount == i) { |
| SkSurface_Gpu* gpuSurf = static_cast<SkSurface_Gpu*>(s.get()); |
| |
| int supportedSampleCount = context->caps()->getSampleCount( |
| params.sampleCount(), |
| gpuSurf->getDevice()->accessRenderTargetContext()->asRenderTargetProxy()->config()); |
| if (0 == supportedSampleCount) { |
| // If changing the sample count won't result in a different |
| // surface characterization, skip this step |
| continue; |
| } |
| } |
| |
| REPORTER_ASSERT(reporter, !s->draw(ddl.get())); |
| } |
| |
| // Next test the compatibility of resource cache parameters |
| { |
| const SurfaceParameters params; |
| sk_sp<SkSurface> s = params.make(context); |
| |
| int maxResourceCount; |
| size_t maxResourceBytes; |
| context->getResourceCacheLimits(&maxResourceCount, &maxResourceBytes); |
| |
| context->setResourceCacheLimits(maxResourceCount/2, maxResourceBytes); |
| REPORTER_ASSERT(reporter, !s->draw(ddl.get())); |
| |
| context->setResourceCacheLimits(maxResourceCount, maxResourceBytes/2); |
| REPORTER_ASSERT(reporter, !s->draw(ddl.get())); |
| |
| // resource limits >= those at characterization time are accepted |
| context->setResourceCacheLimits(2*maxResourceCount, maxResourceBytes); |
| REPORTER_ASSERT(reporter, s->draw(ddl.get())); |
| |
| context->setResourceCacheLimits(maxResourceCount, 2*maxResourceBytes); |
| REPORTER_ASSERT(reporter, s->draw(ddl.get())); |
| |
| context->setResourceCacheLimits(maxResourceCount, maxResourceBytes); |
| REPORTER_ASSERT(reporter, s->draw(ddl.get())); |
| } |
| |
| // Make sure non-GPU-backed surfaces fail characterization |
| { |
| SkImageInfo ii = SkImageInfo::MakeN32(64, 64, kOpaque_SkAlphaType); |
| |
| sk_sp<SkSurface> rasterSurface = SkSurface::MakeRaster(ii); |
| SkSurfaceCharacterization c; |
| REPORTER_ASSERT(reporter, !rasterSurface->characterize(&c)); |
| } |
| } |
| |
| #endif |