From c3bfcb803abb1f45658e9eae9f75b428a4476e75 Mon Sep 17 00:00:00 2001 From: caryclark Date: Tue, 6 Sep 2016 07:09:53 -0700 Subject: [PATCH] Revert of Improve usage of window rectangles (patchset #9 id:160001 of https://codereview.chromium.org/2289363005/ ) Reason for revert: broke build. See https://build.chromium.org/p/client.skia/builders/Perf-Win8-MSVC-ShuttleA-GPU-GTX960-x86_64-Debug/builds/186 Original issue's description: > Improve usage of window rectangles > > * Skips non-AA diff rect elements and replaces them with window > rectangles. > * Places window rectangles in the interiors of antialiased diff rects. > * Arranges two overlapping window rectangles in a plus shape inside of > diff rounded rects. > * Enables window rectangles when clearing and generating clip masks. > > GTX 960 perf result (with vs. without window rectangles): > > glinst4 msaa16 gpu > keymobi_pinterest.skp 0.48 -> 0.17 [ 35%] 2.77 -> 1.49 [ 54%] 0.22 -> 0.16 [ 70%] > keymobi_digg_com.skp 0.42 -> 0.23 [ 55%] 2.34 -> 1.08 [ 46%] 0.25 -> 0.21 [ 83%] > desk_jsfiddlebigcar.skp 0.28 -> 0.16 [ 59%] 1.70 -> 0.96 [ 57%] 0.19 -> 0.14 [ 70%] > top25desk_wordpress.skp 0.45 -> 0.18 [ 40%] 2.78 -> 1.53 [ 55%] 0.21 -> 0.19 [ 94%] > top25desk_weather_com.skp 2.01 -> 1.93 [ 96%] 23.5 -> 2.54 [ 11%] 1.90 -> 1.68 [ 88%] > keymobi_blogger.skp 0.57 -> 0.37 [ 65%] 2.87 -> 1.54 [ 54%] 0.43 -> 0.33 [ 77%] > keymobi_linkedin.skp 0.32 -> 0.17 [ 51%] 1.93 -> 1.04 [ 54%] 0.17 -> 0.15 [ 91%] > keymobi_bing_com_search_... 0.29 -> 0.25 [ 83%] 1.85 -> 1.23 [ 66%] 0.50 -> 0.24 [ 48%] > keymobi_theverge_com_201... 1.00 -> 0.67 [ 68%] 9.46 -> 3.84 [ 41%] 0.72 -> 0.65 [ 90%] > keymobi_sfgate_com_.skp 1.56 -> 1.13 [ 72%] 4.49 -> 2.86 [ 64%] 1.54 -> 1.11 [ 72%] > keymobi_ftw_usatoday_com... 0.59 -> 0.34 [ 57%] 2.80 -> 1.54 [ 55%] 1.21 -> 1.20 [ 99%] > keymobi_shop_mobileweb_e... 0.46 -> 0.32 [ 70%] 2.60 -> 1.26 [ 48%] 0.35 -> 0.34 [ 97%] > keymobi_cnn_com.skp 0.68 -> 0.42 [ 63%] 3.40 -> 2.10 [ 62%] 0.49 -> 0.45 [ 93%] > keymobi_plus_google_com_... 0.77 -> 0.46 [ 60%] 4.83 -> 3.56 [ 74%] 0.52 -> 0.46 [ 89%] > keymobi_wordpress.skp 0.50 -> 0.40 [ 81%] 2.60 -> 1.31 [ 50%] 0.40 -> 0.37 [ 91%] > keymobi_androidpolice_co... 0.84 -> 0.73 [ 87%] 4.15 -> 2.05 [ 49%] 0.77 -> 0.67 [ 87%] > keymobi_online_wsj_com_h... 0.55 -> 0.43 [ 78%] 2.91 -> 1.66 [ 57%] 0.45 -> 0.41 [ 90%] > keymobi_iphone_capitolvo... 1.18 -> 0.96 [ 81%] 6.26 -> 4.96 [ 79%] 0.95 -> 0.92 [ 97%] > keymobi_wikipedia__1_tab... 0.46 -> 0.41 [ 89%] 2.51 -> 1.24 [ 49%] 0.40 -> 0.38 [ 95%] > keymobi_wikipedia__1_tab... 0.46 -> 0.42 [ 90%] 2.52 -> 1.25 [ 50%] 0.40 -> 0.38 [ 96%] > keymobi_boingboing_net.skp 0.62 -> 0.56 [ 90%] 3.15 -> 1.80 [ 57%] 0.61 -> 0.56 [ 92%] > keymobi_cnn_com_2012_10_... 0.86 -> 0.82 [ 95%] 2.81 -> 1.50 [ 53%] 0.91 -> 0.83 [ 91%] > top25desk_techcrunch_com... 0.61 -> 0.56 [ 92%] 3.03 -> 1.76 [ 58%] 0.62 -> 0.56 [ 91%] > top25desk_ebay_com.skp 1.18 -> 1.08 [ 92%] 2.23 -> 1.24 [ 56%] 1.14 -> 1.09 [ 96%] > desk_css3gradients.skp 0.64 -> 0.61 [ 95%] 2.99 -> 1.54 [ 52%] 0.62 -> 0.61 [ 99%] > top25desk_blogger.skp 0.61 -> 0.59 [ 96%] 2.50 -> 1.37 [ 55%] 0.60 -> 0.57 [ 95%] > keymobi_nytimes_com_.skp 0.65 -> 0.64 [ 98%] 2.69 -> 1.42 [ 53%] 0.62 -> 0.59 [ 96%] > keymobi_wowwiki_com_worl... 0.99 -> 0.92 [ 92%] 3.46 -> 2.06 [ 60%] 0.98 -> 0.95 [ 96%] > keymobi_cuteoverload_com... 1.37 -> 1.26 [ 92%] 3.24 -> 2.45 [ 76%] 1.38 -> 1.35 [ 98%] > keymobi_mobile_news_sand... 0.88 -> 0.81 [ 93%] 3.50 -> 2.07 [ 59%] 0.82 -> 0.81 [100%] > top25desk_linkedin.skp 0.87 -> 0.87 [100%] 2.92 -> 1.73 [ 59%] 0.94 -> 0.86 [ 91%] > top25desk_docs___1_open_... 1.43 -> 1.36 [ 95%] 1.87 -> 1.42 [ 76%] 0.73 -> 0.66 [ 91%] > keymobi_reddit_com_r_pro... 0.68 -> 0.66 [ 96%] 2.49 -> 1.23 [ 49%] 0.65 -> 0.66 [102%] > ... > > BUG=skia: > GOLD_TRYBOT_URL= https://gold.skia.org/search?issue=2289363005 > > Committed: https://skia.googlesource.com/skia/+/db42be9a326c747ff92ed1da8c3536c5b3e8e22b TBR=bsalomon@google.com,egdaniel@google.com,robertphillips@google.com,csmartdalton@google.com # Not skipping CQ checks because original CL landed more than 1 days ago. BUG=skia: Review-Url: https://codereview.chromium.org/2312173002 --- gm/windowrectangles.cpp | 305 ------------------------------------ gyp/gpu.gypi | 2 - include/gpu/GrTypesPriv.h | 27 ++++ include/private/GrSurfaceProxy.h | 1 - src/gpu/GrAppliedClip.h | 23 ++- src/gpu/GrClipStackClip.cpp | 32 ++-- src/gpu/GrDrawContext.cpp | 9 +- src/gpu/GrDrawTarget.cpp | 2 +- src/gpu/GrFixedClip.cpp | 44 ++---- src/gpu/GrFixedClip.h | 39 +++-- src/gpu/GrPipeline.cpp | 4 +- src/gpu/GrPipeline.h | 10 +- src/gpu/GrReducedClip.cpp | 116 +------------- src/gpu/GrReducedClip.h | 32 ++-- src/gpu/GrRenderTarget.cpp | 5 - src/gpu/GrRenderTargetPriv.h | 2 +- src/gpu/GrScissorState.h | 40 ----- src/gpu/GrWindowRectangles.h | 21 ++- src/gpu/GrWindowRectsState.h | 60 ------- src/gpu/batches/GrClearBatch.h | 3 - src/gpu/gl/GrGLGpu.cpp | 37 ++--- src/gpu/gl/GrGLGpu.h | 42 ++--- src/gpu/vk/GrVkGpuCommandBuffer.cpp | 2 - tests/ProxyTest.cpp | 8 +- tests/WindowRectanglesTest.cpp | 16 ++ 25 files changed, 192 insertions(+), 690 deletions(-) delete mode 100644 gm/windowrectangles.cpp delete mode 100644 src/gpu/GrScissorState.h delete mode 100644 src/gpu/GrWindowRectsState.h diff --git a/gm/windowrectangles.cpp b/gm/windowrectangles.cpp deleted file mode 100644 index 96c4ea6..0000000 --- a/gm/windowrectangles.cpp +++ /dev/null @@ -1,305 +0,0 @@ -/* - * Copyright 2016 Google Inc. - * - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - */ - -#include "gm.h" -#include "SkClipStack.h" -#include "SkRRect.h" - -#if SK_SUPPORT_GPU -# include "GrAppliedClip.h" -# include "GrDrawContext.h" -# include "GrDrawContextPriv.h" -# include "GrFixedClip.h" -# include "GrReducedClip.h" -# include "GrRenderTargetPriv.h" -# include "GrResourceProvider.h" -# include "effects/GrTextureDomain.h" -#endif - -constexpr static SkIRect kDeviceRect = {0, 0, 600, 600}; -constexpr static SkIRect kLayerRect = {25, 25, 575, 575}; -constexpr static SkIRect kCoverRect = {50, 50, 550, 550}; - -namespace skiagm { - -//////////////////////////////////////////////////////////////////////////////////////////////////// - -class WindowRectanglesBaseGM : public GM { -protected: - virtual void onCoverClipStack(const SkClipStack&, SkCanvas*) = 0; - -private: - SkISize onISize() override { return SkISize::Make(kDeviceRect.width(), kDeviceRect.height()); } - void onDraw(SkCanvas*) final; -}; - -void WindowRectanglesBaseGM::onDraw(SkCanvas* canvas) { - sk_tool_utils::draw_checkerboard(canvas, 0xffffffff, 0xffc6c3c6, 25); - canvas->saveLayer(SkRect::Make(kLayerRect), nullptr); - - SkClipStack stack; - stack.clipDevRect(SkRect::MakeXYWH(370.75, 80.25, 149, 100), SkRegion::kDifference_Op, false); - stack.clipDevRect(SkRect::MakeXYWH(80.25, 420.75, 150, 100), SkRegion::kDifference_Op, true); - stack.clipDevRRect(SkRRect::MakeRectXY(SkRect::MakeXYWH(200, 200, 200, 200), 60, 45), - SkRegion::kDifference_Op, true); - - SkRRect nine; - nine.setNinePatch(SkRect::MakeXYWH(550 - 30.25 - 100, 370.75, 100, 150), 12, 35, 23, 20); - stack.clipDevRRect(nine, SkRegion::kDifference_Op, true); - - SkRRect complx; - SkVector complxRadii[4] = {{6, 4}, {8, 12}, {16, 24}, {48, 32}}; - complx.setRectRadii(SkRect::MakeXYWH(80.25, 80.75, 100, 149), complxRadii); - stack.clipDevRRect(complx, SkRegion::kDifference_Op, false); - - this->onCoverClipStack(stack, canvas); - - canvas->restore(); -} - -//////////////////////////////////////////////////////////////////////////////////////////////////// - -/** - * Draws a clip that will exercise window rectangles if they are supported. - */ -class WindowRectanglesGM : public WindowRectanglesBaseGM { -private: - SkString onShortName() final { return SkString("windowrectangles"); } - void onCoverClipStack(const SkClipStack&, SkCanvas*) final; -}; - -/** - * This is a simple helper class for resetting a canvas's clip to our test’s SkClipStack. - */ -class ReplayClipStackVisitor final : public SkCanvasClipVisitor { -public: - typedef SkRegion::Op Op; - ReplayClipStackVisitor(SkCanvas* canvas) : fCanvas(canvas) {} - void clipRect(const SkRect& r, Op op, bool aa) override { fCanvas->clipRect(r, op, aa); } - void clipRRect(const SkRRect& rr, Op op, bool aa) override { fCanvas->clipRRect(rr, op, aa); } - void clipPath(const SkPath&, Op, bool) override { SkFAIL("Not implemented"); } -private: - SkCanvas* const fCanvas; -}; - -void WindowRectanglesGM::onCoverClipStack(const SkClipStack& stack, SkCanvas* canvas) { - SkPaint paint; - paint.setColor(0xff00aa80); - - // Set up the canvas's clip to match our SkClipStack. - ReplayClipStackVisitor visitor(canvas); - SkClipStack::Iter iter(stack, SkClipStack::Iter::kBottom_IterStart); - for (const SkClipStack::Element* element = iter.next(); element; element = iter.next()) { - element->replay(&visitor); - } - - canvas->drawRect(SkRect::Make(kCoverRect), paint); -} - -DEF_GM( return new WindowRectanglesGM(); ) - -//////////////////////////////////////////////////////////////////////////////////////////////////// - -#if SK_SUPPORT_GPU - -constexpr static int kNumWindows = 8; - -/** - * Visualizes the mask (alpha or stencil) for a clip with several window rectangles. The purpose of - * this test is to verify that window rectangles are being used during clip mask generation, and to - * visualize where the window rectangles are placed. - * - * We use window rectangles when generating the clip mask because there is no need to invest time - * defining those regions where window rectangles will be in effect during the actual draw anyway. - * - * This test works by filling the entire clip mask with a small checkerboard pattern before drawing - * it, and then covering the mask with a solid color once it has been generated. The regions inside - * window rectangles or outside the scissor should still have the initial checkerboard intact. - */ -class WindowRectanglesMaskGM : public WindowRectanglesBaseGM { -private: - constexpr static int kMaskCheckerSize = 5; - SkString onShortName() final { return SkString("windowrectangles_mask"); } - void onCoverClipStack(const SkClipStack&, SkCanvas*) final; - void visualizeAlphaMask(GrContext*, GrDrawContext*, const GrReducedClip&, const GrPaint&); - void visualizeStencilMask(GrContext*, GrDrawContext*, const GrReducedClip&, const GrPaint&); - void stencilCheckerboard(GrDrawContext*, bool flip); - void fail(SkCanvas*); -}; - -/** - * Base class for GrClips that visualize a clip mask. - */ -class MaskOnlyClipBase : public GrClip { -private: - bool quickContains(const SkRect&) const final { return false; } - bool isRRect(const SkRect& rtBounds, SkRRect* rr, bool* aa) const final { return false; } - void getConservativeBounds(int width, int height, SkIRect* rect, bool* iior) const final { - rect->set(0, 0, width, height); - if (iior) { - *iior = false; - } - } -}; - -/** - * This class clips a cover by an alpha mask. We use it to visualize the alpha clip mask. - */ -class AlphaOnlyClip final : public MaskOnlyClipBase { -public: - AlphaOnlyClip(GrTexture* mask, int x, int y) { - int w = mask->width(), h = mask->height(); - SkMatrix mat = SkMatrix::MakeScale(1.f / SkIntToScalar(w), 1.f / SkIntToScalar(h)); - mat.preTranslate(SkIntToScalar(-x), SkIntToScalar(-y)); - fFP = GrTextureDomainEffect::Make( - mask, nullptr, mat, - GrTextureDomain::MakeTexelDomain(mask, SkIRect::MakeWH(w, h)), - GrTextureDomain::kDecal_Mode, GrTextureParams::kNone_FilterMode, - kDevice_GrCoordSet); - - } -private: - bool apply(GrContext*, GrDrawContext*, bool, bool, GrAppliedClip* out) const override { - out->addCoverageFP(fFP); - return true; - } - sk_sp fFP; -}; - -/** - * This class clips a cover by the stencil clip bit. We use it to visualize the stencil mask. - */ -class StencilOnlyClip final : public MaskOnlyClipBase { -private: - bool apply(GrContext*, GrDrawContext*, bool, bool, GrAppliedClip* out) const override { - out->addStencilClip(); - return true; - } -}; - -void WindowRectanglesMaskGM::onCoverClipStack(const SkClipStack& stack, SkCanvas* canvas) { - GrContext* ctx = canvas->getGrContext(); - GrDrawContext* dc = canvas->internal_private_accessTopLayerDrawContext(); - - if (!ctx || !dc || - dc->accessRenderTarget()->renderTargetPriv().maxWindowRectangles() < kNumWindows) { - this->fail(canvas); - return; - } - - const GrReducedClip reducedClip(stack, SkRect::Make(kCoverRect), kNumWindows); - - GrPaint paint; - paint.setAntiAlias(true); - if (!dc->isStencilBufferMultisampled()) { - paint.setColor4f(GrColor4f(0, 0.25f, 1, 1)); - this->visualizeAlphaMask(ctx, dc, reducedClip, paint); - } else { - paint.setColor4f(GrColor4f(1, 0.25f, 0.25f, 1)); - this->visualizeStencilMask(ctx, dc, reducedClip, paint); - } -} - -void WindowRectanglesMaskGM::visualizeAlphaMask(GrContext* ctx, GrDrawContext* dc, - const GrReducedClip& reducedClip, - const GrPaint& paint) { - GrPixelConfig config = kRGBA_8888_GrPixelConfig; - if (ctx->caps()->isConfigRenderable(kAlpha_8_GrPixelConfig, false)) { - config = kAlpha_8_GrPixelConfig; - } - - sk_sp maskDC(ctx->makeDrawContext(SkBackingFit::kExact, kLayerRect.width(), - kLayerRect.height(), config, nullptr)); - if (!maskDC || - !ctx->resourceProvider()->attachStencilAttachment(maskDC->accessRenderTarget())) { - return; - } - - // Draw a checker pattern into the alpha mask so we can visualize the regions left untouched by - // the clip mask generation. - this->stencilCheckerboard(maskDC.get(), true); - maskDC->clear(nullptr, GrColorPackA4(0xff), true); - maskDC->drawContextPriv().drawAndStencilRect(StencilOnlyClip(), &GrUserStencilSettings::kUnused, - SkRegion::kDifference_Op, false, false, - SkMatrix::I(), - SkRect::MakeIWH(maskDC->width(), maskDC->height())); - reducedClip.drawAlphaClipMask(maskDC.get()); - sk_sp mask(maskDC->asTexture()); - - int x = kCoverRect.x() - kLayerRect.x(), - y = kCoverRect.y() - kLayerRect.y(); - - // Now visualize the alpha mask by drawing a rect over the area where it is defined. The regions - // inside window rectangles or outside the scissor should still have the initial checkerboard - // intact. (This verifies we didn't spend any time modifying those pixels in the mask.) - AlphaOnlyClip clip(mask.get(), x, y); - dc->drawRect(clip, paint, SkMatrix::I(), - SkRect::Make(SkIRect::MakeXYWH(x, y, mask->width(), mask->height()))); -} - -void WindowRectanglesMaskGM::visualizeStencilMask(GrContext* ctx, GrDrawContext* dc, - const GrReducedClip& reducedClip, - const GrPaint& paint) { - if (!ctx->resourceProvider()->attachStencilAttachment(dc->accessRenderTarget())) { - return; - } - - // Draw a checker pattern into the stencil buffer so we can visualize the regions left untouched - // by the clip mask generation. - this->stencilCheckerboard(dc, false); - reducedClip.drawStencilClipMask(ctx, dc, {kLayerRect.x(), kLayerRect.y()}); - - // Now visualize the stencil mask by covering the entire render target. The regions inside - // window rectangless or outside the scissor should still have the initial checkerboard intact. - // (This verifies we didn't spend any time modifying those pixels in the mask.) - dc->drawPaint(StencilOnlyClip(), paint, SkMatrix::I()); -} - -void WindowRectanglesMaskGM::stencilCheckerboard(GrDrawContext* dc, bool flip) { - constexpr static GrUserStencilSettings kSetClip( - GrUserStencilSettings::StaticInit< - 0, - GrUserStencilTest::kAlways, - 0, - GrUserStencilOp::kSetClipBit, - GrUserStencilOp::kKeep, - 0>() - ); - - dc->drawContextPriv().clearStencilClip(GrFixedClip::Disabled(), false); - - for (int y = 0; y < kLayerRect.height(); y += kMaskCheckerSize) { - for (int x = (y & 1) == flip ? 0 : kMaskCheckerSize; - x < kLayerRect.width(); x += 2 * kMaskCheckerSize) { - SkIRect checker = SkIRect::MakeXYWH(x, y, kMaskCheckerSize, kMaskCheckerSize); - dc->drawContextPriv().stencilRect(GrNoClip(), &kSetClip, false, SkMatrix::I(), - SkRect::Make(checker)); - } - } -} - -void WindowRectanglesMaskGM::fail(SkCanvas* canvas) { - SkPaint paint; - paint.setAntiAlias(true); - paint.setTextAlign(SkPaint::kCenter_Align); - paint.setTextSize(20); - sk_tool_utils::set_portable_typeface(&paint); - - SkString errorMsg; - errorMsg.printf("Requires GPU with %i window rectangles", kNumWindows); - - canvas->clipRect(SkRect::Make(kCoverRect)); - canvas->clear(SK_ColorWHITE); - canvas->drawText(errorMsg.c_str(), errorMsg.size(), SkIntToScalar(kCoverRect.centerX()), - SkIntToScalar(kCoverRect.centerY() - 10), paint); -} - -DEF_GM( return new WindowRectanglesMaskGM(); ) - -#endif - -} diff --git a/gyp/gpu.gypi b/gyp/gpu.gypi index 33142f2..d1a6952 100644 --- a/gyp/gpu.gypi +++ b/gyp/gpu.gypi @@ -170,7 +170,6 @@ '<(skia_src_path)/gpu/GrResourceHandle.h', '<(skia_src_path)/gpu/GrResourceProvider.cpp', '<(skia_src_path)/gpu/GrResourceProvider.h', - '<(skia_src_path)/gpu/GrScissorState.h', '<(skia_src_path)/gpu/GrShape.cpp', '<(skia_src_path)/gpu/GrShape.h', '<(skia_src_path)/gpu/GrStencilAttachment.cpp', @@ -205,7 +204,6 @@ '<(skia_src_path)/gpu/GrTRecorder.h', '<(skia_src_path)/gpu/GrUserStencilSettings.h', '<(skia_src_path)/gpu/GrWindowRectangles.h', - '<(skia_src_path)/gpu/GrWindowRectsState.h', '<(skia_src_path)/gpu/GrXferProcessor.cpp', '<(skia_src_path)/gpu/GrYUVProvider.cpp', '<(skia_src_path)/gpu/GrYUVProvider.h', diff --git a/include/gpu/GrTypesPriv.h b/include/gpu/GrTypesPriv.h index d60fab1..8c42d64 100644 --- a/include/gpu/GrTypesPriv.h +++ b/include/gpu/GrTypesPriv.h @@ -9,6 +9,7 @@ #define GrTypesPriv_DEFINED #include "GrTypes.h" +#include "SkRect.h" #include "SkRefCnt.h" /** @@ -419,6 +420,32 @@ enum GrIOType { kRW_GrIOType }; +struct GrScissorState { + GrScissorState() : fEnabled(false) {} + GrScissorState(const SkIRect& rect) : fEnabled(true), fRect(rect) {} + void setDisabled() { fEnabled = false; } + void set(const SkIRect& rect) { fRect = rect; fEnabled = true; } + bool SK_WARN_UNUSED_RESULT intersect(const SkIRect& rect) { + if (!fEnabled) { + this->set(rect); + return true; + } + return fRect.intersect(rect); + } + bool operator==(const GrScissorState& other) const { + return fEnabled == other.fEnabled && + (false == fEnabled || fRect == other.fRect); + } + bool operator!=(const GrScissorState& other) const { return !(*this == other); } + + bool enabled() const { return fEnabled; } + const SkIRect& rect() const { return fRect; } + +private: + bool fEnabled; + SkIRect fRect; +}; + /** * Indicates the type of data that a GPU buffer will be used for. */ diff --git a/include/private/GrSurfaceProxy.h b/include/private/GrSurfaceProxy.h index 69656fe..98979ac 100644 --- a/include/private/GrSurfaceProxy.h +++ b/include/private/GrSurfaceProxy.h @@ -9,7 +9,6 @@ #define GrSurfaceProxy_DEFINED #include "GrGpuResource.h" -#include "SkRect.h" class GrTextureProxy; class GrRenderTargetProxy; diff --git a/src/gpu/GrAppliedClip.h b/src/gpu/GrAppliedClip.h index 3e98c6c..c02e9d0 100644 --- a/src/gpu/GrAppliedClip.h +++ b/src/gpu/GrAppliedClip.h @@ -8,8 +8,8 @@ #ifndef GrAppliedClip_DEFINED #define GrAppliedClip_DEFINED -#include "GrScissorState.h" -#include "GrWindowRectsState.h" +#include "GrTypesPriv.h" +#include "GrWindowRectangles.h" class GrFragmentProcessor; @@ -25,7 +25,7 @@ public: } const GrScissorState& scissorState() const { return fScissorState; } - const GrWindowRectsState& windowRectsState() const { return fWindowRectsState; } + const GrWindowRectangles& windowRects() const { return fWindowRects; } GrFragmentProcessor* clipCoverageFragmentProcessor() const { return fClipCoverageFP.get(); } bool hasStencilClip() const { return fHasStencilClip; } @@ -36,15 +36,12 @@ public: return fScissorState.intersect(irect) && fClippedDrawBounds.intersect(SkRect::Make(irect)); } - void addWindowRectangles(const GrWindowRectsState& windowState) { - SkASSERT(!fWindowRectsState.enabled()); - fWindowRectsState = windowState; - } - - void addWindowRectangles(const GrWindowRectangles& windows, const SkIPoint& origin, - GrWindowRectsState::Mode mode) { - SkASSERT(!fWindowRectsState.enabled()); - fWindowRectsState.set(windows, origin, mode); + /** + * Adds an exclusive window rectangle to the clip. It is not currently supported to switch the + * windows to inclusive mode. + */ + void addWindowRectangle(const SkIRect& window) { + fWindowRects.addWindow(window); } void addCoverageFP(sk_sp fp) { @@ -65,7 +62,7 @@ public: private: GrScissorState fScissorState; - GrWindowRectsState fWindowRectsState; + GrWindowRectangles fWindowRects; sk_sp fClipCoverageFP; bool fHasStencilClip; SkRect fClippedDrawBounds; diff --git a/src/gpu/GrClipStackClip.cpp b/src/gpu/GrClipStackClip.cpp index d6ad1d9..4572db5 100644 --- a/src/gpu/GrClipStackClip.cpp +++ b/src/gpu/GrClipStackClip.cpp @@ -287,14 +287,11 @@ bool GrClipStackClip::apply(GrContext* context, GrDrawContext* drawContext, bool return false; } - GrRenderTarget* rt = drawContext->accessRenderTarget(); - const SkScalar clipX = SkIntToScalar(fOrigin.x()), clipY = SkIntToScalar(fOrigin.y()); SkRect clipSpaceDevBounds = devBounds.makeOffset(clipX, clipY); - const GrReducedClip reducedClip(*fStack, clipSpaceDevBounds, - rt->renderTargetPriv().maxWindowRectangles()); + const GrReducedClip reducedClip(*fStack, clipSpaceDevBounds); if (reducedClip.hasIBounds() && !GrClip::IsInsideClip(reducedClip.ibounds(), clipSpaceDevBounds)) { @@ -303,17 +300,29 @@ bool GrClipStackClip::apply(GrContext* context, GrDrawContext* drawContext, bool out->addScissor(scissorSpaceIBounds); } - if (!reducedClip.windowRectangles().empty()) { - out->addWindowRectangles(reducedClip.windowRectangles(), fOrigin, - GrWindowRectsState::Mode::kExclusive); - } - if (reducedClip.elements().isEmpty()) { return InitialState::kAllIn == reducedClip.initialState(); } SkASSERT(reducedClip.hasIBounds()); + // Attempt to implement difference clip rects with window rectangles. This will eventually + // become more comprehensive. + if (drawContext->accessRenderTarget()->renderTargetPriv().supportsWindowRectangles() && + 1 == reducedClip.elements().count() && !reducedClip.requiresAA() && + InitialState::kAllIn == reducedClip.initialState()) { + const Element* element = reducedClip.elements().head(); + SkRegion::Op op = element->getOp(); + if (Element::kRect_Type == element->getType() && + (SkRegion::kDifference_Op == op || SkRegion::kXOR_Op == op)) { + SkIRect window; + element->getRect().round(&window); + window.offset(-fOrigin); + out->addWindowRectangle(window); + return true; + } + } + // An element count of 4 was chosen because of the common pattern in Blink of: // isect RR // diff RR @@ -368,15 +377,12 @@ bool GrClipStackClip::apply(GrContext* context, GrDrawContext* drawContext, bool // use the stencil clip if we can't represent the clip as a rectangle. // TODO: these need to be swapped over to using a StencilAttachmentProxy GrStencilAttachment* stencilAttachment = - context->resourceProvider()->attachStencilAttachment(rt); + context->resourceProvider()->attachStencilAttachment(drawContext->accessRenderTarget()); if (nullptr == stencilAttachment) { SkDebugf("WARNING: failed to attach stencil buffer for clip mask. Clip will be ignored.\n"); return true; } - // This relies on the property that a reduced sub-rect of the last clip will contain all the - // relevant window rectangles that were in the last clip. This subtle requirement will go away - // after clipping is overhauled. if (stencilAttachment->mustRenderClip(reducedClip.elementsGenID(), reducedClip.ibounds(), fOrigin)) { reducedClip.drawStencilClipMask(context, drawContext, fOrigin); diff --git a/src/gpu/GrDrawContext.cpp b/src/gpu/GrDrawContext.cpp index 87252f3..1fd113d 100644 --- a/src/gpu/GrDrawContext.cpp +++ b/src/gpu/GrDrawContext.cpp @@ -215,12 +215,9 @@ void GrDrawContextPriv::clear(const GrFixedClip& clip, void GrDrawContext::internalClear(const GrFixedClip& clip, const GrColor color, bool canIgnoreClip) { - bool isFull = false; - if (!clip.hasWindowRectangles()) { - isFull = !clip.scissorEnabled() || - (canIgnoreClip && fContext->caps()->fullClearIsFree()) || - clip.scissorRect().contains(SkIRect::MakeWH(this->width(), this->height())); - } + bool isFull = !clip.scissorEnabled() || + (canIgnoreClip && fContext->caps()->fullClearIsFree()) || + clip.scissorRect().contains(SkIRect::MakeWH(this->width(), this->height())); if (fContext->caps()->useDrawInsteadOfClear()) { // This works around a driver bug with clear by drawing a rect instead. diff --git a/src/gpu/GrDrawTarget.cpp b/src/gpu/GrDrawTarget.cpp index 0117d0e..3b9f1ec 100644 --- a/src/gpu/GrDrawTarget.cpp +++ b/src/gpu/GrDrawTarget.cpp @@ -381,7 +381,7 @@ void GrDrawTarget::drawBatch(const GrPipelineBuilder& pipelineBuilder, sk_sp_address_as_pointer_address(pipelineBuilder.fCoverageFragmentProcessors.begin()), pipelineBuilder.numCoverageFragmentProcessors()); args.fScissor = &appliedClip.scissorState(); - args.fWindowRectsState = &appliedClip.windowRectsState(); + args.fWindowRects = &appliedClip.windowRects(); args.fHasStencilClip = appliedClip.hasStencilClip(); if (!this->setupDstReadIfNecessary(pipelineBuilder, drawContext->accessRenderTarget(), clip, args.fOpts, diff --git a/src/gpu/GrFixedClip.cpp b/src/gpu/GrFixedClip.cpp index 7385028..ebdd49b 100644 --- a/src/gpu/GrFixedClip.cpp +++ b/src/gpu/GrFixedClip.cpp @@ -10,45 +10,25 @@ #include "GrAppliedClip.h" #include "GrDrawContext.h" -bool GrFixedClip::quickContains(const SkRect& rect) const { - if (fWindowRectsState.enabled()) { - return false; - } - return !fScissorState.enabled() || GrClip::IsInsideClip(fScissorState.rect(), rect); -} - -void GrFixedClip::getConservativeBounds(int w, int h, SkIRect* devResult, bool* iior) const { - devResult->setXYWH(0, 0, w, h); +void GrFixedClip::getConservativeBounds(int width, int height, SkIRect* devResult, + bool* isIntersectionOfRects) const { + devResult->setXYWH(0, 0, width, height); if (fScissorState.enabled()) { if (!devResult->intersect(fScissorState.rect())) { devResult->setEmpty(); } } - if (iior) { - *iior = true; + if (isIntersectionOfRects) { + *isIntersectionOfRects = true; } } -bool GrFixedClip::isRRect(const SkRect& rtBounds, SkRRect* rr, bool* aa) const { - if (fWindowRectsState.enabled()) { - return false; - } +bool GrFixedClip::apply(GrContext*, GrDrawContext* drawContext, bool isHWAntiAlias, + bool hasUserStencilSettings, GrAppliedClip* out) const { if (fScissorState.enabled()) { - SkRect rect = SkRect::Make(fScissorState.rect()); - if (!rect.intersects(rtBounds)) { - return false; - } - rr->setRect(rect); - *aa = false; - return true; - } - return false; -}; - -bool GrFixedClip::apply(GrContext*, GrDrawContext* dc, bool, bool, GrAppliedClip* out) const { - if (fScissorState.enabled()) { - SkIRect tightScissor = SkIRect::MakeWH(dc->width(), dc->height()); - if (!tightScissor.intersect(fScissorState.rect())) { + SkIRect tightScissor; + if (!tightScissor.intersect(fScissorState.rect(), + SkIRect::MakeWH(drawContext->width(), drawContext->height()))) { return false; } if (IsOutsideClip(tightScissor, out->clippedDrawBounds())) { @@ -59,10 +39,6 @@ bool GrFixedClip::apply(GrContext*, GrDrawContext* dc, bool, bool, GrAppliedClip } } - if (fWindowRectsState.enabled()) { - out->addWindowRectangles(fWindowRectsState); - } - return true; } diff --git a/src/gpu/GrFixedClip.h b/src/gpu/GrFixedClip.h index 6fb7d23..8b3a9c1 100644 --- a/src/gpu/GrFixedClip.h +++ b/src/gpu/GrFixedClip.h @@ -9,8 +9,7 @@ #define GrFixedClip_DEFINED #include "GrClip.h" -#include "GrScissorState.h" -#include "GrWindowRectsState.h" +#include "GrTypesPriv.h" /** * GrFixedClip is a clip that gets implemented by fixed-function hardware. @@ -30,26 +29,32 @@ public: return fScissorState.intersect(irect); } - const GrWindowRectsState& windowRectsState() const { return fWindowRectsState; } - bool hasWindowRectangles() const { return fWindowRectsState.enabled(); } - - void disableWindowRectangles() { fWindowRectsState.setDisabled(); } - - void setWindowRectangles(const GrWindowRectangles& windows, const SkIPoint& origin, - GrWindowRectsState::Mode mode) { - fWindowRectsState.set(windows, origin, mode); + bool quickContains(const SkRect& rect) const final { + return !fScissorState.enabled() || GrClip::IsInsideClip(fScissorState.rect(), rect); } - - bool quickContains(const SkRect&) const override; - void getConservativeBounds(int w, int h, SkIRect* devResult, bool* iior) const override; - bool isRRect(const SkRect& rtBounds, SkRRect* rr, bool* aa) const override; - bool apply(GrContext*, GrDrawContext*, bool, bool, GrAppliedClip* out) const override; + void getConservativeBounds(int width, int height, SkIRect* devResult, + bool* isIntersectionOfRects) const final; + + bool isRRect(const SkRect& rtBounds, SkRRect* rr, bool* aa) const override { + if (fScissorState.enabled()) { + SkRect rect = SkRect::Make(fScissorState.rect()); + if (!rect.intersects(rtBounds)) { + return false; + } + rr->setRect(rect); + *aa = false; + return true; + } + return false; + }; + + bool apply(GrContext*, GrDrawContext*, bool useHWAA, bool hasUserStencilSettings, + GrAppliedClip* out) const final; static const GrFixedClip& Disabled(); private: - GrScissorState fScissorState; - GrWindowRectsState fWindowRectsState; + GrScissorState fScissorState; }; #endif diff --git a/src/gpu/GrPipeline.cpp b/src/gpu/GrPipeline.cpp index 892bccd..8fe321d 100644 --- a/src/gpu/GrPipeline.cpp +++ b/src/gpu/GrPipeline.cpp @@ -27,7 +27,7 @@ GrPipeline* GrPipeline::CreateAt(void* memory, const CreateArgs& args, pipeline->fRenderTarget.reset(rt); SkASSERT(pipeline->fRenderTarget); pipeline->fScissorState = *args.fScissor; - pipeline->fWindowRectsState = *args.fWindowRectsState; + pipeline->fWindowRects = *args.fWindowRects; if (builder.hasUserStencilSettings() || args.fHasStencilClip) { const GrRenderTargetPriv& rtPriv = rt->renderTargetPriv(); pipeline->fStencilSettings.reset(*builder.getUserStencil(), args.fHasStencilClip, @@ -230,7 +230,7 @@ bool GrPipeline::AreEqual(const GrPipeline& a, const GrPipeline& b, a.fFragmentProcessors.count() != b.fFragmentProcessors.count() || a.fNumColorProcessors != b.fNumColorProcessors || a.fScissorState != b.fScissorState || - !a.fWindowRectsState.cheapEqualTo(b.fWindowRectsState) || + a.fWindowRects != b.fWindowRects || a.fFlags != b.fFlags || a.fStencilSettings != b.fStencilSettings || a.fDrawFace != b.fDrawFace || diff --git a/src/gpu/GrPipeline.h b/src/gpu/GrPipeline.h index 8c2f538..18f1a2a 100644 --- a/src/gpu/GrPipeline.h +++ b/src/gpu/GrPipeline.h @@ -16,9 +16,9 @@ #include "GrPrimitiveProcessor.h" #include "GrProcOptInfo.h" #include "GrProgramDesc.h" -#include "GrScissorState.h" #include "GrStencilSettings.h" -#include "GrWindowRectsState.h" +#include "GrTypesPriv.h" +#include "GrWindowRectangles.h" #include "SkMatrix.h" #include "SkRefCnt.h" @@ -60,7 +60,7 @@ public: const GrCaps* fCaps; GrPipelineOptimizations fOpts; const GrScissorState* fScissor; - const GrWindowRectsState* fWindowRectsState; + const GrWindowRectangles* fWindowRects; bool fHasStencilClip; GrXferProcessor::DstTexture fDstTexture; }; @@ -154,7 +154,7 @@ public: const GrScissorState& getScissorState() const { return fScissorState; } - const GrWindowRectsState& getWindowRectsState() const { return fWindowRectsState; } + const GrWindowRectangles& getWindowRectangles() const { return fWindowRects; } bool isHWAntialiasState() const { return SkToBool(fFlags & kHWAA_Flag); } bool snapVerticesToPixelCenters() const { return SkToBool(fFlags & kSnapVertices_Flag); } @@ -223,7 +223,7 @@ private: typedef GrPendingProgramElement ProgramXferProcessor; RenderTarget fRenderTarget; GrScissorState fScissorState; - GrWindowRectsState fWindowRectsState; + GrWindowRectangles fWindowRects; GrStencilSettings fStencilSettings; GrDrawFace fDrawFace; uint32_t fFlags; diff --git a/src/gpu/GrReducedClip.cpp b/src/gpu/GrReducedClip.cpp index 948f7e9..dfc0a26 100644 --- a/src/gpu/GrReducedClip.cpp +++ b/src/gpu/GrReducedClip.cpp @@ -28,8 +28,7 @@ typedef SkClipStack::Element Element; * based on later intersect operations, and perhaps remove intersect-rects. We could optionally * take a rect in case the caller knows a bound on what is to be drawn through this clip. */ -GrReducedClip::GrReducedClip(const SkClipStack& stack, const SkRect& queryBounds, - int maxWindowRectangles) { +GrReducedClip::GrReducedClip(const SkClipStack& stack, const SkRect& queryBounds) { SkASSERT(!queryBounds.isEmpty()); fHasIBounds = false; @@ -95,15 +94,10 @@ GrReducedClip::GrReducedClip(const SkClipStack& stack, const SkRect& queryBounds // Now that we have determined the bounds to use and filtered out the trivial cases, call the // helper that actually walks the stack. - this->walkStack(stack, tighterQuery, maxWindowRectangles); - - if (fWindowRects.count() < maxWindowRectangles) { - this->addInteriorWindowRectangles(maxWindowRectangles); - } + this->walkStack(stack, tighterQuery); } -void GrReducedClip::walkStack(const SkClipStack& stack, const SkRect& queryBounds, - int maxWindowRectangles) { +void GrReducedClip::walkStack(const SkClipStack& stack, const SkRect& queryBounds) { // walk backwards until we get to: // a) the beginning // b) an operation that is known to make the bounds all inside/outside @@ -162,10 +156,6 @@ void GrReducedClip::walkStack(const SkClipStack& stack, const SkRect& queryBound skippable = true; } else if (GrClip::IsOutsideClip(element->getBounds(), queryBounds)) { skippable = true; - } else if (fWindowRects.count() < maxWindowRectangles && !embiggens && - !element->isAA() && Element::kRect_Type == element->getType()) { - this->addWindowRectangle(element->getRect(), false); - skippable = true; } } if (!skippable) { @@ -430,85 +420,10 @@ void GrReducedClip::walkStack(const SkClipStack& stack, const SkRect& queryBound fInitialState = static_cast(initialTriState); } -static bool element_is_pure_subtract(SkRegion::Op op) { - SkASSERT(op >= 0); - return op <= SkRegion::kIntersect_Op; - - GR_STATIC_ASSERT(0 == SkRegion::kDifference_Op); - GR_STATIC_ASSERT(1 == SkRegion::kIntersect_Op); -} - -void GrReducedClip::addInteriorWindowRectangles(int maxWindowRectangles) { - SkASSERT(fWindowRects.count() < maxWindowRectangles); - // Walk backwards through the element list and add window rectangles to the interiors of - // "difference" elements. Quit if we encounter an element that may grow the clip. - ElementList::Iter iter(fElements, ElementList::Iter::kTail_IterStart); - for (; iter.get() && element_is_pure_subtract(iter.get()->getOp()); iter.prev()) { - const Element* element = iter.get(); - if (SkRegion::kDifference_Op != element->getOp()) { - continue; - } - - if (Element::kRect_Type == element->getType()) { - SkASSERT(element->isAA()); - this->addWindowRectangle(element->getRect(), true); - if (fWindowRects.count() >= maxWindowRectangles) { - return; - } - continue; - } - - if (Element::kRRect_Type == element->getType()) { - // For round rects we add two overlapping windows in the shape of a plus. - const SkRRect& clipRRect = element->getRRect(); - SkVector insetTL = clipRRect.radii(SkRRect::kUpperLeft_Corner); - SkVector insetBR = clipRRect.radii(SkRRect::kLowerRight_Corner); - if (SkRRect::kComplex_Type == clipRRect.getType()) { - const SkVector& insetTR = clipRRect.radii(SkRRect::kUpperRight_Corner); - const SkVector& insetBL = clipRRect.radii(SkRRect::kLowerLeft_Corner); - insetTL.fX = SkTMax(insetTL.x(), insetBL.x()); - insetTL.fY = SkTMax(insetTL.y(), insetTR.y()); - insetBR.fX = SkTMax(insetBR.x(), insetTR.x()); - insetBR.fY = SkTMax(insetBR.y(), insetBL.y()); - } - const SkRect& bounds = clipRRect.getBounds(); - if (insetTL.x() + insetBR.x() >= bounds.width() || - insetTL.y() + insetBR.y() >= bounds.height()) { - continue; // The interior "plus" is empty. - } - - SkRect horzRect = SkRect::MakeLTRB(bounds.left(), bounds.top() + insetTL.y(), - bounds.right(), bounds.bottom() - insetBR.y()); - this->addWindowRectangle(horzRect, element->isAA()); - if (fWindowRects.count() >= maxWindowRectangles) { - return; - } - - SkRect vertRect = SkRect::MakeLTRB(bounds.left() + insetTL.x(), bounds.top(), - bounds.right() - insetBR.x(), bounds.bottom()); - this->addWindowRectangle(vertRect, element->isAA()); - if (fWindowRects.count() >= maxWindowRectangles) { - return; - } - continue; - } - } -} - -inline void GrReducedClip::addWindowRectangle(const SkRect& elementInteriorRect, bool elementIsAA) { - SkIRect* window = &fWindowRects.addWindow(); - if (!elementIsAA) { - elementInteriorRect.round(window); - } else { - elementInteriorRect.roundIn(window); - } -} - inline bool GrReducedClip::intersectIBounds(const SkIRect& irect) { SkASSERT(fHasIBounds); if (!fIBounds.intersect(irect)) { fHasIBounds = false; - fWindowRects.reset(); fElements.reset(); fRequiresAA = false; fInitialState = InitialState::kAllOut; @@ -588,11 +503,6 @@ bool GrReducedClip::drawAlphaClipMask(GrDrawContext* dc) const { // we populate with a rasterization of the clip. GrFixedClip clip(SkIRect::MakeWH(fIBounds.width(), fIBounds.height())); - if (!fWindowRects.empty()) { - clip.setWindowRectangles(fWindowRects, {fIBounds.left(), fIBounds.top()}, - GrWindowRectsState::Mode::kExclusive); - } - // The scratch texture that we are drawing into can be substantially larger than the mask. Only // clear the part that we care about. GrColor initialCoverage = InitialState::kAllIn == this->initialState() ? -1 : 0; @@ -660,23 +570,18 @@ public: StencilClip(const SkIRect& scissorRect) : fFixedClip(scissorRect) {} const GrFixedClip& fixedClip() const { return fFixedClip; } - void setWindowRectangles(const GrWindowRectangles& windows, const SkIPoint& origin, - GrWindowRectsState::Mode mode) { - fFixedClip.setWindowRectangles(windows, origin, mode); - } - private: - bool quickContains(const SkRect&) const override { + bool quickContains(const SkRect&) const final { return false; } - void getConservativeBounds(int width, int height, SkIRect* bounds, bool* iior) const override { - fFixedClip.getConservativeBounds(width, height, bounds, iior); + void getConservativeBounds(int width, int height, SkIRect* devResult, bool* iior) const final { + fFixedClip.getConservativeBounds(width, height, devResult, iior); } - bool isRRect(const SkRect& rtBounds, SkRRect* rr, bool* aa) const override { + bool isRRect(const SkRect& rtBounds, SkRRect* rr, bool* aa) const final { return false; } bool apply(GrContext* context, GrDrawContext* drawContext, bool useHWAA, - bool hasUserStencilSettings, GrAppliedClip* out) const override { + bool hasUserStencilSettings, GrAppliedClip* out) const final { if (!fFixedClip.apply(context, drawContext, useHWAA, hasUserStencilSettings, out)) { return false; } @@ -695,11 +600,6 @@ bool GrReducedClip::drawStencilClipMask(GrContext* context, // We set the current clip to the bounds so that our recursive draws are scissored to them. StencilClip stencilClip(fIBounds.makeOffset(-clipOrigin.x(), -clipOrigin.y())); - if (!fWindowRects.empty()) { - stencilClip.setWindowRectangles(fWindowRects, clipOrigin, - GrWindowRectsState::Mode::kExclusive); - } - bool initialState = InitialState::kAllIn == this->initialState(); drawContext->drawContextPriv().clearStencilClip(stencilClip.fixedClip(), initialState); diff --git a/src/gpu/GrReducedClip.h b/src/gpu/GrReducedClip.h index b8413e6..731d58f 100644 --- a/src/gpu/GrReducedClip.h +++ b/src/gpu/GrReducedClip.h @@ -8,7 +8,6 @@ #ifndef GrReducedClip_DEFINED #define GrReducedClip_DEFINED -#include "GrWindowRectangles.h" #include "SkClipStack.h" #include "SkTLList.h" @@ -21,11 +20,11 @@ class GrDrawContext; */ class SK_API GrReducedClip { public: - GrReducedClip(const SkClipStack&, const SkRect& queryBounds, int maxWindowRectangles = 0); + GrReducedClip(const SkClipStack& stack, const SkRect& queryBounds); /** - * If hasIBounds() is true, this is the bounding box within which the clip elements are valid. - * The caller must not modify any pixels outside this box. Undefined if hasIBounds() is false. + * If hasIBounds() is true, this is the bounding box within which the reduced clip is valid, and + * the caller must not modify any pixels outside this box. Undefined if hasIBounds() is false. */ const SkIRect& ibounds() const { SkASSERT(fHasIBounds); return fIBounds; } int left() const { return this->ibounds().left(); } @@ -39,16 +38,10 @@ public: */ bool hasIBounds() const { return fHasIBounds; } - /** - * If nonempty, this is a set of "exclusive" windows within which the clip elements are NOT - * valid. The caller must not modify any pixels inside these windows. - */ - const GrWindowRectangles& windowRectangles() const { return fWindowRects; } - typedef SkTLList ElementList; /** - * Populated with a minimal list of elements required to fully implement the clip. + * Populated with a minimal list of elements that implement the clip. */ const ElementList& elements() const { return fElements; } @@ -74,18 +67,15 @@ public: bool drawStencilClipMask(GrContext*, GrDrawContext*, const SkIPoint& clipOrigin) const; private: - void walkStack(const SkClipStack&, const SkRect& queryBounds, int maxWindowRectangles); - void addInteriorWindowRectangles(int maxWindowRectangles); - void addWindowRectangle(const SkRect& elementInteriorRect, bool elementIsAA); + void walkStack(const SkClipStack&, const SkRect& queryBounds); bool intersectIBounds(const SkIRect&); - SkIRect fIBounds; - bool fHasIBounds; - GrWindowRectangles fWindowRects; - ElementList fElements; - int32_t fElementsGenID; - bool fRequiresAA; - InitialState fInitialState; + SkIRect fIBounds; + bool fHasIBounds; + ElementList fElements; + int32_t fElementsGenID; + bool fRequiresAA; + InitialState fInitialState; }; #endif diff --git a/src/gpu/GrRenderTarget.cpp b/src/gpu/GrRenderTarget.cpp index 2053a16..90f94b3 100644 --- a/src/gpu/GrRenderTarget.cpp +++ b/src/gpu/GrRenderTarget.cpp @@ -127,8 +127,3 @@ const GrGpu::MultisampleSpecs& GrRenderTargetPriv::getMultisampleSpecs(const GrStencilSettings& stencil) const { return fRenderTarget->getGpu()->getMultisampleSpecs(fRenderTarget, stencil); } - -int GrRenderTargetPriv::maxWindowRectangles() const { - return (this->flags() & Flags::kWindowRectsSupport) ? - fRenderTarget->getGpu()->caps()->maxWindowRectangles() : 0; -} diff --git a/src/gpu/GrRenderTargetPriv.h b/src/gpu/GrRenderTargetPriv.h index 698288e..2c828ec 100644 --- a/src/gpu/GrRenderTargetPriv.h +++ b/src/gpu/GrRenderTargetPriv.h @@ -38,7 +38,7 @@ public: typedef GrRenderTarget::Flags Flags; Flags flags() const { return fRenderTarget->fFlags; } - int maxWindowRectangles() const; + bool supportsWindowRectangles() const { return this->flags() & Flags::kWindowRectsSupport; } private: explicit GrRenderTargetPriv(GrRenderTarget* renderTarget) : fRenderTarget(renderTarget) {} diff --git a/src/gpu/GrScissorState.h b/src/gpu/GrScissorState.h deleted file mode 100644 index 59ea088..0000000 --- a/src/gpu/GrScissorState.h +++ /dev/null @@ -1,40 +0,0 @@ -/* - * Copyright 2016 Google Inc. - * - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - */ - -#ifndef GrScissorState_DEFINED -#define GrScissorState_DEFINED - -#include "SkRect.h" - -class GrScissorState { -public: - GrScissorState() : fEnabled(false) {} - GrScissorState(const SkIRect& rect) : fEnabled(true), fRect(rect) {} - void setDisabled() { fEnabled = false; } - void set(const SkIRect& rect) { fRect = rect; fEnabled = true; } - bool SK_WARN_UNUSED_RESULT intersect(const SkIRect& rect) { - if (!fEnabled) { - this->set(rect); - return true; - } - return fRect.intersect(rect); - } - bool operator==(const GrScissorState& other) const { - return fEnabled == other.fEnabled && - (false == fEnabled || fRect == other.fRect); - } - bool operator!=(const GrScissorState& other) const { return !(*this == other); } - - bool enabled() const { return fEnabled; } - const SkIRect& rect() const { return fRect; } - -private: - bool fEnabled; - SkIRect fRect; -}; - -#endif diff --git a/src/gpu/GrWindowRectangles.h b/src/gpu/GrWindowRectangles.h index 076c40d..b2f6e1a 100644 --- a/src/gpu/GrWindowRectangles.h +++ b/src/gpu/GrWindowRectangles.h @@ -15,15 +15,21 @@ class GrWindowRectangles { public: constexpr static int kMaxWindows = 8; - GrWindowRectangles() : fCount(0) {} + enum class Mode : bool { + kExclusive, + kInclusive + }; + + GrWindowRectangles(Mode mode = Mode::kExclusive) : fMode(mode), fCount(0) {} GrWindowRectangles(const GrWindowRectangles& that) : fCount(0) { *this = that; } ~GrWindowRectangles() { SkSafeUnref(this->rec()); } - bool empty() const { return !fCount; } + Mode mode() const { return fMode; } int count() const { return fCount; } + bool disabled() const { return Mode::kExclusive == fMode && !fCount; } const SkIRect* data() const; - void reset(); + void reset(Mode = Mode::kExclusive); GrWindowRectangles& operator=(const GrWindowRectangles&); SkIRect& addWindow(const SkIRect& window) { return this->addWindow() = window; } @@ -38,7 +44,8 @@ private: const Rec* rec() const { return fCount <= kNumLocalWindows ? nullptr : fRec; } - int fCount; + Mode fMode; + uint8_t fCount; union { SkIRect fLocalWindows[kNumLocalWindows]; // If fCount <= kNumLocalWindows. Rec* fRec; // If fCount > kNumLocalWindows. @@ -58,13 +65,15 @@ inline const SkIRect* GrWindowRectangles::data() const { return fCount <= kNumLocalWindows ? fLocalWindows : fRec->fData; } -inline void GrWindowRectangles::reset() { +inline void GrWindowRectangles::reset(Mode mode) { SkSafeUnref(this->rec()); + fMode = mode; fCount = 0; } inline GrWindowRectangles& GrWindowRectangles::operator=(const GrWindowRectangles& that) { SkSafeUnref(this->rec()); + fMode = that.fMode; fCount = that.fCount; if (fCount <= kNumLocalWindows) { memcpy(fLocalWindows, that.fLocalWindows, fCount * sizeof(SkIRect)); @@ -89,7 +98,7 @@ inline SkIRect& GrWindowRectangles::addWindow() { } inline bool GrWindowRectangles::operator==(const GrWindowRectangles& that) const { - if (fCount != that.fCount) { + if (fMode != that.fMode || fCount != that.fCount) { return false; } if (fCount > kNumLocalWindows && fRec == that.fRec) { diff --git a/src/gpu/GrWindowRectsState.h b/src/gpu/GrWindowRectsState.h deleted file mode 100644 index 9d3b61b..0000000 --- a/src/gpu/GrWindowRectsState.h +++ /dev/null @@ -1,60 +0,0 @@ -/* - * Copyright 2016 Google Inc. - * - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - */ - -#ifndef GrWindowRectsState_DEFINED -#define GrWindowRectsState_DEFINED - -#include "GrWindowRectangles.h" - -class GrWindowRectsState { -public: - enum class Mode : bool { - kExclusive, - kInclusive - }; - - GrWindowRectsState() : fMode(Mode::kExclusive) {} - GrWindowRectsState(const GrWindowRectangles& windows, const SkIPoint& origin, Mode mode) - : fMode(mode) - , fOrigin(origin) - , fWindows(windows) { - } - - bool enabled() const { return Mode::kInclusive == fMode || !fWindows.empty(); } - Mode mode() const { return fMode; } - const SkIPoint& origin() const { return fOrigin; } - const GrWindowRectangles& windows() const { return fWindows; } - int numWindows() const { return fWindows.count(); } - - void setDisabled() { - fMode = Mode::kExclusive; - fWindows.reset(); - } - - void set(const GrWindowRectangles& windows, const SkIPoint& origin, Mode mode) { - fMode = mode; - fOrigin = origin; - fWindows = windows; - } - - bool cheapEqualTo(const GrWindowRectsState& that) const { - if (fMode != that.fMode) { - return false; - } - if (!fWindows.empty() && fOrigin != that.fOrigin) { - return false; - } - return fWindows == that.fWindows; - } - -private: - Mode fMode; - SkIPoint fOrigin; - GrWindowRectangles fWindows; -}; - -#endif diff --git a/src/gpu/batches/GrClearBatch.h b/src/gpu/batches/GrClearBatch.h index 16f1ddd..27e19fa 100644 --- a/src/gpu/batches/GrClearBatch.h +++ b/src/gpu/batches/GrClearBatch.h @@ -71,9 +71,6 @@ private: // same color. GrClearBatch* cb = t->cast(); SkASSERT(cb->fRenderTarget == fRenderTarget); - if (!fClip.windowRectsState().cheapEqualTo(cb->fClip.windowRectsState())) { - return false; - } if (cb->contains(this)) { fClip = cb->fClip; this->replaceBounds(*t); diff --git a/src/gpu/gl/GrGLGpu.cpp b/src/gpu/gl/GrGLGpu.cpp index e002d51..466af6c 100644 --- a/src/gpu/gl/GrGLGpu.cpp +++ b/src/gpu/gl/GrGLGpu.cpp @@ -564,7 +564,7 @@ void GrGLGpu::onResetContext(uint32_t resetBits) { if (resetBits & kView_GrGLBackendState) { fHWScissorSettings.invalidate(); - fHWWindowRectsState.invalidate(); + fHWWindowRects.invalidate(); fHWViewport.invalidate(); } @@ -1997,42 +1997,39 @@ void GrGLGpu::flushScissor(const GrScissorState& scissorState, this->disableScissor(); } -void GrGLGpu::flushWindowRectangles(const GrWindowRectsState& windowState, - const GrGLRenderTarget* rt) { - typedef GrWindowRectsState::Mode Mode; - SkASSERT(!windowState.enabled() || rt->renderFBOID()); // Window rects can't be used on-screen. - SkASSERT(windowState.numWindows() <= this->caps()->maxWindowRectangles()); +void GrGLGpu::flushWindowRectangles(const GrWindowRectangles& windows, const GrGLRenderTarget* rt) { + typedef GrWindowRectangles::Mode Mode; + SkASSERT(windows.count() <= this->caps()->maxWindowRectangles()); + SkASSERT(windows.disabled() || rt->renderFBOID()); // Window rectangles can't be used on-screen. if (!this->caps()->maxWindowRectangles() || - fHWWindowRectsState.knownEqualTo(rt->origin(), rt->getViewport(), windowState)) { + fHWWindowRects.equal(rt->origin(), rt->getViewport(), windows)) { return; } // This is purely a workaround for a spurious warning generated by gcc. Otherwise the above // assert would be sufficient. https://gcc.gnu.org/bugzilla/show_bug.cgi?id=5912 - int numWindows = SkTMin(windowState.numWindows(), int(GrWindowRectangles::kMaxWindows)); - SkASSERT(windowState.numWindows() == numWindows); + int numWindows = SkTMin(windows.count(), int(GrWindowRectangles::kMaxWindows)); + SkASSERT(windows.count() == numWindows); GrGLIRect glwindows[GrWindowRectangles::kMaxWindows]; - const SkIRect* skwindows = windowState.windows().data(); - int dx = -windowState.origin().x(), dy = -windowState.origin().y(); + const SkIRect* skwindows = windows.data(); for (int i = 0; i < numWindows; ++i) { - const SkIRect& skwindow = skwindows[i].makeOffset(dx, dy); - glwindows[i].setRelativeTo(rt->getViewport(), skwindow, rt->origin()); + glwindows[i].setRelativeTo(rt->getViewport(), skwindows[i], rt->origin()); } - GrGLenum glmode = (Mode::kExclusive == windowState.mode()) ? GR_GL_EXCLUSIVE : GR_GL_INCLUSIVE; + GrGLenum glmode = (Mode::kExclusive == windows.mode()) ? GR_GL_EXCLUSIVE : GR_GL_INCLUSIVE; GL_CALL(WindowRectangles(glmode, numWindows, glwindows->asInts())); - fHWWindowRectsState.set(rt->origin(), rt->getViewport(), windowState); + fHWWindowRects.set(rt->origin(), rt->getViewport(), windows); } void GrGLGpu::disableWindowRectangles() { - if (!this->caps()->maxWindowRectangles() || fHWWindowRectsState.knownDisabled()) { + if (!this->caps()->maxWindowRectangles() || fHWWindowRects.disabled()) { return; } GL_CALL(WindowRectangles(GR_GL_EXCLUSIVE, 0, nullptr)); - fHWWindowRectsState.setDisabled(); + fHWWindowRects.setDisabled(); } void GrGLGpu::flushMinSampleShading(float minSampleShading) { @@ -2082,7 +2079,7 @@ bool GrGLGpu::flushGLState(const GrPipeline& pipeline, const GrPrimitiveProcesso GrGLRenderTarget* glRT = static_cast(pipeline.getRenderTarget()); this->flushStencil(pipeline.getStencil()); this->flushScissor(pipeline.getScissorState(), glRT->getViewport(), glRT->origin()); - this->flushWindowRectangles(pipeline.getWindowRectsState(), glRT); + this->flushWindowRectangles(pipeline.getWindowRectangles(), glRT); this->flushHWAAState(glRT, pipeline.isHWAntialiasState(), !pipeline.getStencil().isDisabled()); // This must come after textures are flushed because a texture may need @@ -2210,7 +2207,7 @@ void GrGLGpu::clear(const GrFixedClip& clip, GrColor color, GrRenderTarget* targ this->flushRenderTarget(glRT, clip.scissorEnabled() ? &clip.scissorRect() : nullptr); this->flushScissor(clip.scissorState(), glRT->getViewport(), glRT->origin()); - this->flushWindowRectangles(clip.windowRectsState(), glRT); + this->disableWindowRectangles(); GrGLfloat r, g, b, a; static const GrGLfloat scale255 = 1.f / 255.f; @@ -2274,7 +2271,7 @@ void GrGLGpu::clearStencilClip(const GrFixedClip& clip, this->flushRenderTarget(glRT, &SkIRect::EmptyIRect()); this->flushScissor(clip.scissorState(), glRT->getViewport(), glRT->origin()); - this->flushWindowRectangles(clip.windowRectsState(), glRT); + this->disableWindowRectangles(); GL_CALL(StencilMask((uint32_t) clipStencilMask)); GL_CALL(ClearStencil(value)); diff --git a/src/gpu/gl/GrGLGpu.h b/src/gpu/gl/GrGLGpu.h index 62803ee..3fe4204 100644 --- a/src/gpu/gl/GrGLGpu.h +++ b/src/gpu/gl/GrGLGpu.h @@ -18,7 +18,6 @@ #include "GrGLVertexArray.h" #include "GrGpu.h" #include "GrTypes.h" -#include "GrWindowRectsState.h" #include "GrXferProcessor.h" #include "SkTArray.h" #include "SkTypes.h" @@ -315,7 +314,7 @@ private: // disables the scissor void disableScissor(); - void flushWindowRectangles(const GrWindowRectsState&, const GrGLRenderTarget*); + void flushWindowRectangles(const GrWindowRectangles&, const GrGLRenderTarget*); void disableWindowRectangles(); void initFSAASupport(); @@ -425,36 +424,39 @@ private: class { public: - bool valid() const { return kInvalidSurfaceOrigin != fRTOrigin; } - void invalidate() { fRTOrigin = kInvalidSurfaceOrigin; } - bool knownDisabled() const { return this->valid() && !fWindowState.enabled(); } - void setDisabled() { fRTOrigin = kDefault_GrSurfaceOrigin, fWindowState.setDisabled(); } - - void set(GrSurfaceOrigin rtOrigin, const GrGLIRect& viewport, - const GrWindowRectsState& windowState) { - fRTOrigin = rtOrigin; - fViewport = viewport; - fWindowState = windowState; + bool valid() const { return kInvalidOrigin != fOrigin; } + void invalidate() { fOrigin = kInvalidOrigin; } + + bool disabled() const { + return this->valid() && Mode::kExclusive == fWindows.mode() && !fWindows.count(); } + void setDisabled() { fOrigin = kDefault_GrSurfaceOrigin, fWindows.reset(); } - bool knownEqualTo(GrSurfaceOrigin rtOrigin, const GrGLIRect& viewport, - const GrWindowRectsState& windowState) const { + bool equal(GrSurfaceOrigin org, const GrGLIRect& viewp, + const GrWindowRectangles& windows) const { if (!this->valid()) { return false; } - if (fWindowState.numWindows() && (fRTOrigin != rtOrigin || fViewport != viewport)) { + if (fWindows.count() && (fOrigin != org || fViewport != viewp)) { return false; } - return fWindowState.cheapEqualTo(windowState); + return fWindows == windows; + } + + void set(GrSurfaceOrigin org, const GrGLIRect& viewp, const GrWindowRectangles& windows) { + fOrigin = org; + fViewport = viewp; + fWindows = windows; } private: - enum { kInvalidSurfaceOrigin = -1 }; + typedef GrWindowRectangles::Mode Mode; + enum { kInvalidOrigin = -1 }; - int fRTOrigin; + int fOrigin; GrGLIRect fViewport; - GrWindowRectsState fWindowState; - } fHWWindowRectsState; + GrWindowRectangles fWindows; + } fHWWindowRects; GrGLIRect fHWViewport; diff --git a/src/gpu/vk/GrVkGpuCommandBuffer.cpp b/src/gpu/vk/GrVkGpuCommandBuffer.cpp index e3c7cb7..6144cf9 100644 --- a/src/gpu/vk/GrVkGpuCommandBuffer.cpp +++ b/src/gpu/vk/GrVkGpuCommandBuffer.cpp @@ -162,7 +162,6 @@ void GrVkGpuCommandBuffer::onClearStencilClip(GrRenderTarget* target, const GrFixedClip& clip, bool insideStencilMask) { SkASSERT(target); - SkASSERT(!clip.hasWindowRectangles()); GrVkRenderTarget* vkRT = static_cast(target); GrStencilAttachment* sb = target->renderTargetPriv().getStencilAttachment(); @@ -216,7 +215,6 @@ void GrVkGpuCommandBuffer::onClearStencilClip(GrRenderTarget* target, void GrVkGpuCommandBuffer::onClear(GrRenderTarget* target, const GrFixedClip& clip, GrColor color) { // parent class should never let us get here with no RT SkASSERT(target); - SkASSERT(!clip.hasWindowRectangles()); VkClearColorValue vkColor; GrColorToRGBAFloat(color, vkColor.float32); diff --git a/tests/ProxyTest.cpp b/tests/ProxyTest.cpp index 367dee4..016ce5e 100644 --- a/tests/ProxyTest.cpp +++ b/tests/ProxyTest.cpp @@ -162,8 +162,7 @@ DEF_GPUTEST_FOR_RENDERING_CONTEXTS(WrappedProxyTest, reporter, ctxInfo) { GrGpu* gpu = ctxInfo.grContext()->getGpu(); sk_sp defaultFBO( gpu->wrapBackendRenderTarget(backendDesc, kBorrow_GrWrapOwnership)); - REPORTER_ASSERT(reporter, - !defaultFBO->renderTargetPriv().maxWindowRectangles()); + SkASSERT(!defaultFBO->renderTargetPriv().supportsWindowRectangles()); sk_sp rtProxy( GrRenderTargetProxy::Make(caps, defaultFBO)); @@ -179,9 +178,8 @@ DEF_GPUTEST_FOR_RENDERING_CONTEXTS(WrappedProxyTest, reporter, ctxInfo) { desc.fFlags = kRenderTarget_GrSurfaceFlag; tex.reset(provider->createTexture(desc, budgeted)); sk_sp rt(sk_ref_sp(tex->asRenderTarget())); - REPORTER_ASSERT(reporter, - caps.maxWindowRectangles() == - rt->renderTargetPriv().maxWindowRectangles()); + SkASSERT(caps.maxWindowRectangles() <= 0 || + rt->renderTargetPriv().supportsWindowRectangles()); sk_sp rtProxy(GrRenderTargetProxy::Make(caps, rt)); check_surface(reporter, rtProxy.get(), origin, diff --git a/tests/WindowRectanglesTest.cpp b/tests/WindowRectanglesTest.cpp index e954565..d569f1d 100644 --- a/tests/WindowRectanglesTest.cpp +++ b/tests/WindowRectanglesTest.cpp @@ -31,6 +31,7 @@ DEF_TEST(WindowRectangles, reporter) { GrWindowRectangles wr2(wr); REPORTER_ASSERT(reporter, wr2 == wr); + REPORTER_ASSERT(reporter, wr2.mode() == wr.mode()); REPORTER_ASSERT(reporter, wr2.count() == wr.count()); REPORTER_ASSERT(reporter, !memcmp(wr2.data(), wr.data(), i * sizeof(SkIRect))); @@ -71,6 +72,21 @@ DEF_TEST(WindowRectangles, reporter) { REPORTER_ASSERT(reporter, !memcmp(A.data(), windowData, GrWindowRectangles::kMaxWindows * sizeof(SkIRect))); } + + GrWindowRectangles wrI(GrWindowRectangles::Mode::kInclusive); + for (int i = 0; i < wr.count(); ++i) { + wrI.addWindow(windowData[i]); + } + REPORTER_ASSERT(reporter, wrI != wr); + REPORTER_ASSERT(reporter, wrI.mode() != wr.mode()); + REPORTER_ASSERT(reporter, wrI.count() == wr.count()); + REPORTER_ASSERT(reporter, !memcmp(wrI.data(), wr.data(), wr.count() * sizeof(SkIRect))); + + wr.reset(GrWindowRectangles::Mode::kInclusive); + for (int i = 0; i < wrI.count(); ++i) { + wr.addWindow(windowData[i]); + } + REPORTER_ASSERT(reporter, wrI == wr); } #endif -- 2.7.4