123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153 |
- /*
- * 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 "tests/Test.h"
- #include "include/core/SkPath.h"
- #include "include/gpu/GrContext.h"
- #include "src/gpu/GrClip.h"
- #include "src/gpu/GrContextPriv.h"
- #include "src/gpu/GrResourceCache.h"
- #include "src/gpu/GrSoftwarePathRenderer.h"
- #include "src/gpu/GrStyle.h"
- #include "src/gpu/effects/GrPorterDuffXferProcessor.h"
- #include "src/gpu/geometry/GrShape.h"
- #include "src/gpu/ops/GrTessellatingPathRenderer.h"
- static SkPath create_concave_path() {
- SkPath path;
- path.moveTo(100, 0);
- path.lineTo(200, 200);
- path.lineTo(100, 150);
- path.lineTo(0, 200);
- path.close();
- return path;
- }
- static void draw_path(GrContext* ctx,
- GrRenderTargetContext* renderTargetContext,
- const SkPath& path,
- GrPathRenderer* pr,
- GrAAType aaType,
- const GrStyle& style) {
- GrPaint paint;
- paint.setXPFactory(GrPorterDuffXPFactory::Get(SkBlendMode::kSrc));
- GrNoClip noClip;
- SkIRect clipConservativeBounds = SkIRect::MakeWH(renderTargetContext->width(),
- renderTargetContext->height());
- GrShape shape(path, style);
- if (shape.style().applies()) {
- shape = shape.applyStyle(GrStyle::Apply::kPathEffectAndStrokeRec, 1.0f);
- }
- SkMatrix matrix = SkMatrix::I();
- GrPathRenderer::DrawPathArgs args{ctx,
- std::move(paint),
- &GrUserStencilSettings::kUnused,
- renderTargetContext,
- &noClip,
- &clipConservativeBounds,
- &matrix,
- &shape,
- aaType,
- false};
- pr->drawPath(args);
- }
- static bool cache_non_scratch_resources_equals(GrResourceCache* cache, int expected) {
- #if GR_CACHE_STATS
- GrResourceCache::Stats stats;
- cache->getStats(&stats);
- return (stats.fTotal - stats.fScratch) == expected;
- #else
- return true;
- #endif
- }
- static void test_path(skiatest::Reporter* reporter,
- std::function<SkPath(void)> createPath,
- std::function<GrPathRenderer*(GrContext*)> createPathRenderer,
- int expected,
- GrAAType aaType = GrAAType::kNone,
- GrStyle style = GrStyle(SkStrokeRec::kFill_InitStyle)) {
- sk_sp<GrContext> ctx = GrContext::MakeMock(nullptr);
- // The cache needs to be big enough that nothing gets flushed, or our expectations can be wrong
- ctx->setResourceCacheLimits(100, 8000000);
- GrResourceCache* cache = ctx->priv().getResourceCache();
- sk_sp<GrRenderTargetContext> rtc(ctx->priv().makeDeferredRenderTargetContext(
- SkBackingFit::kApprox, 800, 800, GrColorType::kRGBA_8888, nullptr, 1, GrMipMapped::kNo,
- kTopLeft_GrSurfaceOrigin));
- if (!rtc) {
- return;
- }
- sk_sp<GrPathRenderer> pathRenderer(createPathRenderer(ctx.get()));
- SkPath path = createPath();
- // Initially, cache only has the render target context
- REPORTER_ASSERT(reporter, cache_non_scratch_resources_equals(cache, 0));
- // Draw the path, check that new resource count matches expectations
- draw_path(ctx.get(), rtc.get(), path, pathRenderer.get(), aaType, style);
- ctx->flush();
- REPORTER_ASSERT(reporter, cache_non_scratch_resources_equals(cache, expected));
- // Nothing should be purgeable yet
- cache->purgeAsNeeded();
- REPORTER_ASSERT(reporter, cache_non_scratch_resources_equals(cache, expected));
- // Reset the path to change the GenID, which should invalidate one resource in the cache.
- // Some path renderers may leave other unique-keyed resources in the cache, though.
- path.reset();
- cache->purgeAsNeeded();
- REPORTER_ASSERT(reporter, cache_non_scratch_resources_equals(cache, expected - 1));
- }
- // Test that deleting the original path invalidates the VBs cached by the tessellating path renderer
- DEF_GPUTEST(TessellatingPathRendererCacheTest, reporter, /* options */) {
- auto createPR = [](GrContext*) {
- return new GrTessellatingPathRenderer();
- };
- // Tessellating path renderer creates a single vertex buffer for non-AA paths. No other
- // resources should be created.
- const int kExpectedResources = 1;
- test_path(reporter, create_concave_path, createPR, kExpectedResources);
- // Test with a style that alters the path geometry. This needs to attach the invalidation logic
- // to the original path, not the modified path produced by the style.
- SkPaint paint;
- paint.setStyle(SkPaint::kStroke_Style);
- paint.setStrokeWidth(1);
- GrStyle style(paint);
- test_path(
- reporter, create_concave_path, createPR, kExpectedResources, GrAAType::kNone, style);
- }
- // Test that deleting the original path invalidates the textures cached by the SW path renderer
- DEF_GPUTEST(SoftwarePathRendererCacheTest, reporter, /* options */) {
- auto createPR = [](GrContext* ctx) {
- return new GrSoftwarePathRenderer(ctx->priv().proxyProvider(), true);
- };
- // Software path renderer creates a mask texture and renders with a non-AA rect, but the flush
- // only contains a single quad so GrFillRectOp doesn't need to use the shared index buffer.
- const int kExpectedResources = 1;
- test_path(reporter, create_concave_path, createPR, kExpectedResources, GrAAType::kCoverage);
- // Test with a style that alters the path geometry. This needs to attach the invalidation logic
- // to the original path, not the modified path produced by the style.
- SkPaint paint;
- paint.setStyle(SkPaint::kStroke_Style);
- paint.setStrokeWidth(1);
- GrStyle style(paint);
- test_path(reporter, create_concave_path, createPR, kExpectedResources, GrAAType::kCoverage,
- style);
- }
|