text: /*
   * Copyright 2015 Google Inc.
   *
   * Use of this source code is governed by a BSD-style license that can be
   * found in the LICENSE file.
   */
  
  #ifndef GrSurfaceDrawContext_DEFINED
  #define GrSurfaceDrawContext_DEFINED
  
  #include "include/core/SkCanvas.h"
  #include "include/core/SkDrawable.h"
  #include "include/core/SkRefCnt.h"
  #include "include/core/SkSurface.h"
  #include "include/core/SkSurfaceProps.h"
  #include "include/private/GrTypesPriv.h"
  #include "src/core/SkGlyphRunPainter.h"
  #include "src/gpu/GrOpsTask.h"
  #include "src/gpu/GrPaint.h"
  #include "src/gpu/GrRenderTargetProxy.h"
  #include "src/gpu/GrSurfaceFillContext.h"
  #include "src/gpu/GrSurfaceProxyView.h"
  #include "src/gpu/GrXferProcessor.h"
  #include "src/gpu/geometry/GrQuad.h"
  
  class GrBackendSemaphore;
  class GrClip;
  class GrColorSpaceXform;
  class GrCoverageCountingPathRenderer;
  class GrDrawOp;
  class GrOp;
  class GrRenderTarget;
  class GrStyledShape;
  class GrStyle;
  class GrTextureProxy;
  struct GrUserStencilSettings;
  struct SkDrawShadowRec;
  class SkGlyphRunList;
  struct SkIPoint;
  struct SkIRect;
  class SkLatticeIter;
  class SkMatrixProvider;
  class SkMatrix;
  class SkPaint;
  class SkPath;
  struct SkPoint;
  struct SkRect;
  class SkRegion;
  class SkRRect;
  struct SkRSXform;
  class SkRuntimeEffect;
  class SkTextBlob;
  class SkVertices;
  
  /**
   * A helper object to orchestrate commands (draws, etc...) for GrSurfaces that are GrRenderTargets.
   */
  class GrSurfaceDrawContext : public GrSurfaceFillContext {
  public:
      static std::unique_ptr<GrSurfaceDrawContext> Make(GrRecordingContext*,
                                                        GrColorType,
                                                        sk_sp<GrSurfaceProxy>,
                                                        sk_sp<SkColorSpace>,
                                                        GrSurfaceOrigin,
                                                        const SkSurfaceProps&,
                                                        bool flushTimeOpsTask = false);
  
      /* Uses the default texture format for the color type */
      static std::unique_ptr<GrSurfaceDrawContext> Make(GrRecordingContext*,
                                                        GrColorType,
                                                        sk_sp<SkColorSpace>,
                                                        SkBackingFit,
                                                        SkISize dimensions,
                                                        const SkSurfaceProps&,
                                                        int sampleCnt = 1,
                                                        GrMipmapped = GrMipmapped::kNo,
                                                        GrProtected = GrProtected::kNo,
                                                        GrSurfaceOrigin = kBottomLeft_GrSurfaceOrigin,
                                                        SkBudgeted = SkBudgeted::kYes);
  
      /**
       * Takes custom swizzles rather than determining swizzles from color type and format.
       * It will have color type kUnknown.
       */
      static std::unique_ptr<GrSurfaceDrawContext> Make(GrRecordingContext*,
                                                        sk_sp<SkColorSpace>,
                                                        SkBackingFit,
                                                        SkISize dimensions,
                                                        const GrBackendFormat&,
                                                        int sampleCnt,
                                                        GrMipmapped,
                                                        GrProtected,
                                                        GrSwizzle readSwizzle,
                                                        GrSwizzle writeSwizzle,
                                                        GrSurfaceOrigin,
                                                        SkBudgeted,
                                                        const SkSurfaceProps&);
  
      // Same as previous factory but will try to use fallback GrColorTypes if the one passed in
      // fails. The fallback GrColorType will have at least the number of channels and precision per
      // channel as the passed in GrColorType. It may also swizzle the changes (e.g., BGRA -> RGBA).
      // SRGB-ness will be preserved.
      static std::unique_ptr<GrSurfaceDrawContext> MakeWithFallback(
              GrRecordingContext*,
              GrColorType,
              sk_sp<SkColorSpace>,
              SkBackingFit,
              SkISize dimensions,
              const SkSurfaceProps&,
              int sampleCnt = 1,
              GrMipmapped = GrMipmapped::kNo,
              GrProtected = GrProtected::kNo,
              GrSurfaceOrigin = kBottomLeft_GrSurfaceOrigin,
              SkBudgeted = SkBudgeted::kYes);
  
      // These match the definitions in SkSurface & GrSurface.h, for whence they came
      typedef void* ReleaseContext;
      typedef void (*ReleaseProc)(ReleaseContext);
  
      // Creates a GrSurfaceDrawContext that wraps the passed in GrBackendTexture.
      static std::unique_ptr<GrSurfaceDrawContext> MakeFromBackendTexture(
              GrRecordingContext*, GrColorType, sk_sp<SkColorSpace>, const GrBackendTexture&,
              int sampleCnt, GrSurfaceOrigin, const SkSurfaceProps&,
              sk_sp<GrRefCntedCallback> releaseHelper);
  
      GrSurfaceDrawContext(GrRecordingContext*,
                           GrSurfaceProxyView readView,
                           GrSurfaceProxyView writeView,
                           GrColorType,
                           sk_sp<SkColorSpace>,
                           const SkSurfaceProps&,
                           bool flushTimeOpsTask = false);
  
      ~GrSurfaceDrawContext() override;
  
      /**
       *  Draw everywhere (respecting the clip) with the paint.
       */
      void drawPaint(const GrClip*, GrPaint&&, const SkMatrix& viewMatrix);
  
      /**
       * Draw the rect using a paint.
       * @param paint        describes how to color pixels.
       * @param GrAA         Controls whether rect is antialiased
       * @param viewMatrix   transformation matrix
       * @param style        The style to apply. Null means fill. Currently path effects are not
       *                     allowed.
       * The rects coords are used to access the paint (through texture matrix)
       */
      void drawRect(const GrClip*,
                    GrPaint&& paint,
                    GrAA,
                    const SkMatrix& viewMatrix,
                    const SkRect&,
                    const GrStyle* style = nullptr);
  
      /**
       * Maps a rectangle of shader coordinates to a rectangle and fills that rectangle.
       *
       * @param GrPaint      describes how to color pixels.
       * @param GrAA         Controls whether rect is antialiased
       * @param SkMatrix     transformation matrix which applies to rectToDraw
       * @param rectToDraw   the rectangle to draw
       * @param localRect    the rectangle of shader coordinates applied to rectToDraw
       */
      void fillRectToRect(const GrClip*,
                          GrPaint&&,
                          GrAA,
                          const SkMatrix&,
                          const SkRect& rectToDraw,
                          const SkRect& localRect);
  
      /**
       * Fills a block of pixels with a paint and a localMatrix, respecting the clip.
       */
      void fillPixelsWithLocalMatrix(const GrClip* clip,
                                     GrPaint&& paint,
                                     const SkIRect& bounds,
                                     const SkMatrix& localMatrix) {
          SkRect rect = SkRect::Make(bounds);
          DrawQuad quad{GrQuad::MakeFromRect(rect, SkMatrix::I()),
                        GrQuad::MakeFromRect(rect, localMatrix), GrQuadAAFlags::kNone};
          this->drawFilledQuad(clip, std::move(paint), GrAA::kNo, &quad);
      }
  
      /**
       * Creates an op that draws a fill rect with per-edge control over anti-aliasing.
       *
       * This is a specialized version of fillQuadWithEdgeAA, but is kept separate since knowing
       * the geometry is a rectangle affords more optimizations.
       */
      void fillRectWithEdgeAA(const GrClip* clip, GrPaint&& paint, GrAA aa, GrQuadAAFlags edgeAA,
                              const SkMatrix& viewMatrix, const SkRect& rect,
                              const SkRect* optionalLocalRect = nullptr) {
          if (edgeAA == GrQuadAAFlags::kAll) {
              this->fillRectToRect(clip, std::move(paint), aa, viewMatrix, rect,
                                   (optionalLocalRect) ? *optionalLocalRect : rect);
              return;
          }
          const SkRect& localRect = optionalLocalRect ? *optionalLocalRect : rect;
          DrawQuad quad{GrQuad::MakeFromRect(rect, viewMatrix), GrQuad(localRect), edgeAA};
          this->drawFilledQuad(clip, std::move(paint), aa, &quad);
      }
  
      /**
       * Similar to fillRectWithEdgeAA but draws an arbitrary 2D convex quadrilateral transformed
       * by 'viewMatrix', with per-edge control over anti-aliasing. The quad should follow the
       * ordering used by SkRect::toQuad(), which determines how the edge AA is applied:
       *  - "top" = points [0] and [1]
       *  - "right" = points[1] and [2]
       *  - "bottom" = points[2] and [3]
       *  - "left" = points[3] and [0]
       *
       * The last argument, 'optionalLocalQuad', can be null if no separate local coordinates are
       * necessary.
       */
      void fillQuadWithEdgeAA(const GrClip* clip, GrPaint&& paint, GrAA aa, GrQuadAAFlags edgeAA,
                              const SkMatrix& viewMatrix, const SkPoint points[4],
                              const SkPoint optionalLocalPoints[4]) {
          const SkPoint* localPoints = optionalLocalPoints ? optionalLocalPoints : points;
          DrawQuad quad{GrQuad::MakeFromSkQuad(points, viewMatrix),
                        GrQuad::MakeFromSkQuad(localPoints, SkMatrix::I()), edgeAA};
          this->drawFilledQuad(clip, std::move(paint), aa, &quad);
      }
  
      /** Used with drawQuadSet */
      struct QuadSetEntry {
          SkRect fRect;
          SkPMColor4f fColor; // Overrides any color on the GrPaint
          SkMatrix fLocalMatrix;
          GrQuadAAFlags fAAFlags;
      };
  
      // TODO(michaelludwig) - remove if the bulk API is not useful for SkiaRenderer
      void drawQuadSet(const GrClip* clip, GrPaint&& paint, GrAA aa, const SkMatrix& viewMatrix,
                       const QuadSetEntry[], int cnt);
  
      /**
       * Creates an op that draws a subrectangle of a texture. The passed color is modulated by the
       * texture's color. 'srcRect' specifies the rectangle of the texture to draw. 'dstRect'
       * specifies the rectangle to draw in local coords which will be transformed by 'viewMatrix' to
       * device space.
       */
      void drawTexture(const GrClip*,
                       GrSurfaceProxyView,
                       SkAlphaType,
                       GrSamplerState::Filter,
                       GrSamplerState::MipmapMode,
                       SkBlendMode,
                       const SkPMColor4f&,
                       const SkRect& srcRect,
                       const SkRect& dstRect,
                       GrAA,
                       GrQuadAAFlags,
                       SkCanvas::SrcRectConstraint,
                       const SkMatrix&,
                       sk_sp<GrColorSpaceXform>);
  
      /**
       * Variant of drawTexture that instead draws the texture applied to 'dstQuad' transformed by
       * 'viewMatrix', using the 'srcQuad' texture coordinates clamped to the optional 'subset'. If
       * 'subset' is null, it's equivalent to using the fast src rect constraint. If 'subset' is
       * provided, the strict src rect constraint is applied using 'subset'.
       */
      void drawTextureQuad(const GrClip* clip,
                           GrSurfaceProxyView view,
                           GrColorType srcColorType,
                           SkAlphaType srcAlphaType,
                           GrSamplerState::Filter filter,
                           GrSamplerState::MipmapMode mm,
                           SkBlendMode mode,
                           const SkPMColor4f& color,
                           const SkPoint srcQuad[4],
                           const SkPoint dstQuad[4],
                           GrAA aa,
                           GrQuadAAFlags edgeAA,
                           const SkRect* subset,
                           const SkMatrix& viewMatrix,
                           sk_sp<GrColorSpaceXform> texXform) {
          DrawQuad quad{GrQuad::MakeFromSkQuad(dstQuad, viewMatrix),
                        GrQuad::MakeFromSkQuad(srcQuad, SkMatrix::I()), edgeAA};
          this->drawTexturedQuad(clip, std::move(view), srcAlphaType, std::move(texXform), filter, mm,
                                 color, mode, aa, &quad, subset);
      }
  
      /** Used with drawTextureSet */
      struct TextureSetEntry {
          GrSurfaceProxyView fProxyView;
          SkAlphaType fSrcAlphaType;
          SkRect fSrcRect;
          SkRect fDstRect;
          const SkPoint* fDstClipQuad; // Must be null, or point to an array of 4 points
          const SkMatrix* fPreViewMatrix; // If not null, entry's CTM is 'viewMatrix' * fPreViewMatrix
          SkPMColor4f   fColor; // {a,a,a,a} for rgb textures, {r,g,b,a} for alpha-only textures
          GrQuadAAFlags fAAFlags;
      };
      /**
       * Draws a set of textures with a shared filter, color, view matrix, color xform, and
       * texture color xform. The textures must all have the same GrTextureType and GrConfig.
       *
       * If any entries provide a non-null fDstClip array, it will be read from immediately based on
       * fDstClipCount, so the pointer can become invalid after this returns.
       *
       * 'proxRunCnt' is the number of proxy changes encountered in the entry array. Technically this
       * can be inferred from the array within this function, but the information is already known
       * by SkGpuDevice, so no need to incur another iteration over the array.
       */
      void drawTextureSet(const GrClip*,
                          TextureSetEntry[],
                          int cnt,
                          int proxyRunCnt,
                          GrSamplerState::Filter,
                          GrSamplerState::MipmapMode,
                          SkBlendMode mode,
                          GrAA aa,
                          SkCanvas::SrcRectConstraint,
                          const SkMatrix& viewMatrix,
                          sk_sp<GrColorSpaceXform> texXform);
  
      /**
       * Draw a roundrect using a paint.
       *
       * @param paint       describes how to color pixels.
       * @param GrAA        Controls whether rrect is antialiased.
       * @param viewMatrix  transformation matrix
       * @param rrect       the roundrect to draw
       * @param style       style to apply to the rrect. Currently path effects are not allowed.
       */
      void drawRRect(const GrClip*,
                     GrPaint&&,
                     GrAA,
                     const SkMatrix& viewMatrix,
                     const SkRRect& rrect,
                     const GrStyle& style);
  
      /**
       * Use a fast method to render the ambient and spot shadows for a path.
       * Will return false if not possible for the given path.
       *
       * @param viewMatrix   transformation matrix
       * @param path         the path to shadow
       * @param rec          parameters for shadow rendering
       */
      bool drawFastShadow(const GrClip*,
                          const SkMatrix& viewMatrix,
                          const SkPath& path,
                          const SkDrawShadowRec& rec);
  
      /**
       * Draws a path.
       *
       * @param paint         describes how to color pixels.
       * @param GrAA          Controls whether the path is antialiased.
       * @param viewMatrix    transformation matrix
       * @param path          the path to draw
       * @param style         style to apply to the path.
       */
      void drawPath(const GrClip*,
                    GrPaint&&,
                    GrAA,
                    const SkMatrix& viewMatrix,
                    const SkPath&,
                    const GrStyle&);
  
      /**
       * Draws a shape.
       *
       * @param paint         describes how to color pixels.
       * @param GrAA          Controls whether the path is antialiased.
       * @param viewMatrix    transformation matrix
       * @param shape         the shape to draw
       */
      void drawShape(const GrClip*,
                     GrPaint&&,
                     GrAA,
                     const SkMatrix& viewMatrix,
                     GrStyledShape&&);
  
  
      /**
       * Draws vertices with a paint.
       *
       * @param   paint            describes how to color pixels.
       * @param   viewMatrix       transformation matrix
       * @param   vertices         specifies the mesh to draw.
       * @param   overridePrimType primitive type to draw. If NULL, derive prim type from vertices.
       * @param   effect           runtime effect that will handle custom vertex attributes.
       */
      void drawVertices(const GrClip*,
                        GrPaint&& paint,
                        const SkMatrixProvider& matrixProvider,
                        sk_sp<SkVertices> vertices,
                        GrPrimitiveType* overridePrimType = nullptr,
                        const SkRuntimeEffect* effect = nullptr);
  
      /**
       * Draws textured sprites from an atlas with a paint. This currently does not support AA for the
       * sprite rectangle edges.
       *
       * @param   paint           describes how to color pixels.
       * @param   viewMatrix      transformation matrix
       * @param   spriteCount     number of sprites.
       * @param   xform           array of compressed transformation data, required.
       * @param   texRect         array of texture rectangles used to access the paint.
       * @param   colors          optional array of per-sprite colors, supercedes
       *                          the paint's color field.
       */
      void drawAtlas(const GrClip*,
                     GrPaint&& paint,
                     const SkMatrix& viewMatrix,
                     int spriteCount,
                     const SkRSXform xform[],
                     const SkRect texRect[],
                     const SkColor colors[]);
  
      /**
       * Draws a region.
       *
       * @param paint         describes how to color pixels
       * @param viewMatrix    transformation matrix
       * @param aa            should the rects of the region be antialiased.
       * @param region        the region to be drawn
       * @param style         style to apply to the region
       */
      void drawRegion(const GrClip*,
                      GrPaint&& paint,
                      GrAA aa,
                      const SkMatrix& viewMatrix,
                      const SkRegion& region,
                      const GrStyle& style,
                      const GrUserStencilSettings* ss = nullptr);
  
      /**
       * Draws an oval.
       *
       * @param paint         describes how to color pixels.
       * @param GrAA          Controls whether the oval is antialiased.
       * @param viewMatrix    transformation matrix
       * @param oval          the bounding rect of the oval.
       * @param style         style to apply to the oval. Currently path effects are not allowed.
       */
      void drawOval(const GrClip*,
                    GrPaint&& paint,
                    GrAA,
                    const SkMatrix& viewMatrix,
                    const SkRect& oval,
                    const GrStyle& style);
  
      /**
       * Draws a partial arc of an oval.
       *
       * @param paint         describes how to color pixels.
       * @param GrGrAA        Controls whether the arc is antialiased.
       * @param viewMatrix    transformation matrix.
       * @param oval          the bounding rect of the oval.
       * @param startAngle    starting angle in degrees.
       * @param sweepAngle    angle to sweep in degrees. Must be in (-360, 360)
       * @param useCenter     true means that the implied path begins at the oval center, connects as
       *                      a line to the point indicated by the start contains the arc indicated by
       *                      the sweep angle. If false the line beginning at the center point is
       *                      omitted.
       * @param style         style to apply to the oval.
       */
      void drawArc(const GrClip*,
                   GrPaint&& paint,
                   GrAA,
                   const SkMatrix& viewMatrix,
                   const SkRect& oval,
                   SkScalar startAngle,
                   SkScalar sweepAngle,
                   bool useCenter,
                   const GrStyle& style);
  
      /**
       * Draw the image as a set of rects, specified by |iter|.
       */
      void drawImageLattice(const GrClip*,
                            GrPaint&&,
                            const SkMatrix& viewMatrix,
                            GrSurfaceProxyView,
                            SkAlphaType alphaType,
                            sk_sp<GrColorSpaceXform>,
                            GrSamplerState::Filter,
                            std::unique_ptr<SkLatticeIter>,
                            const SkRect& dst);
  
      /**
       * Draw the text specified by the SkGlyphRunList.
       *
       * @param viewMatrix      transformationMatrix
       * @param glyphRunList    text, text positions, and paint.
       */
      void drawGlyphRunList(const GrClip*,
                            const SkMatrixProvider& viewMatrix,
                            const SkGlyphRunList& glyphRunList,
                            const SkPaint& paint);
  
      /**
       * Draw the text specified by the SkGlyphRunList.
       *
       * @param viewMatrix      transformationMatrix
       * @param glyphRunList    text, text positions, and paint.
       */
      void drawGlyphRunListWithCache(const GrClip*,
                                     const SkMatrixProvider& viewMatrix,
                                     const SkGlyphRunList& glyphRunList,
                                     const SkPaint& paint);
  
      /**
       * Draw the text specified by the SkGlyphRunList.
       *
       * @param viewMatrix      transformationMatrix
       * @param glyphRunList    text, text positions, and paint.
       */
      void drawGlyphRunListNoCache(const GrClip*,
                                   const SkMatrixProvider& viewMatrix,
                                   const SkGlyphRunList& glyphRunList,
                                   const SkPaint& paint);
  
      /**
       * Adds the necessary signal and wait semaphores and adds the passed in SkDrawable to the
       * command stream.
       */
      void drawDrawable(std::unique_ptr<SkDrawable::GpuDrawHandler>, const SkRect& bounds);
  
      // called to note the last clip drawn to the stencil buffer.
      // TODO: remove after clipping overhaul.
      void setLastClip(uint32_t clipStackGenID,
                       const SkIRect& devClipBounds,
                       int numClipAnalyticElements) {
          GrOpsTask* opsTask = this->getOpsTask();
          opsTask->fLastClipStackGenID = clipStackGenID;
          opsTask->fLastDevClipBounds = devClipBounds;
          opsTask->fLastClipNumAnalyticElements = numClipAnalyticElements;
      }
  
      // called to determine if we have to render the clip into SB.
      // TODO: remove after clipping overhaul.
      bool mustRenderClip(uint32_t clipStackGenID,
                          const SkIRect& devClipBounds,
                          int numClipAnalyticElements) {
          GrOpsTask* opsTask = this->getOpsTask();
          return opsTask->fLastClipStackGenID != clipStackGenID ||
                 !opsTask->fLastDevClipBounds.contains(devClipBounds) ||
                 opsTask->fLastClipNumAnalyticElements != numClipAnalyticElements;
      }
  
      void clearStencilClip(const SkIRect& scissor, bool insideStencilMask) {
          this->internalStencilClear(&scissor, insideStencilMask);
      }
  
      // While this can take a general clip, since GrReducedClip relies on this function, it must take
      // care to only provide hard clips or we could get stuck in a loop. The general clip is needed
      // so that path renderers can use this function.
      void stencilRect(const GrClip* clip,
                       const GrUserStencilSettings* ss,
                       GrPaint&& paint,
                       GrAA doStencilMSAA,
                       const SkMatrix& viewMatrix,
                       const SkRect& rect,
                       const SkMatrix* localMatrix = nullptr) {
          // Since this provides stencil settings to drawFilledQuad, it performs a different AA type
          // resolution compared to regular rect draws, which is the main reason it remains separate.
          DrawQuad quad{GrQuad::MakeFromRect(rect, viewMatrix),
                        localMatrix ? GrQuad::MakeFromRect(rect, *localMatrix) : GrQuad(rect),
                        doStencilMSAA == GrAA::kYes ? GrQuadAAFlags::kAll : GrQuadAAFlags::kNone};
          this->drawFilledQuad(clip, std::move(paint), doStencilMSAA, &quad, ss);
      }
  
      // Fills the user stencil bits with a non-zero value at every sample inside the path. This will
      // likely be implemented with a Redbook algorithm, but it is not guaranteed. The samples being
      // rendered to must be zero initially.
      bool stencilPath(const GrHardClip*,
                       GrAA doStencilMSAA,
                       const SkMatrix& viewMatrix,
                       const SkPath&);
  
      /**
       * Draws a path, either AA or not, and touches the stencil buffer with the user stencil settings
       * for each color sample written.
       */
      bool drawAndStencilPath(const GrHardClip*,
                              const GrUserStencilSettings*,
                              SkRegion::Op op,
                              bool invert,
                              GrAA doStencilMSAA,
                              const SkMatrix& viewMatrix,
                              const SkPath&);
  
      SkBudgeted isBudgeted() const;
  
      int maxWindowRectangles() const;
  
      SkGlyphRunListPainter* glyphRunPainter() { return &fGlyphPainter; }
  
      /*
       * This unique ID will not change for a given RenderTargetContext. However, it is _NOT_
       * guaranteed to match the uniqueID of the underlying GrRenderTarget - beware!
       */
      GrSurfaceProxy::UniqueID uniqueID() const { return this->asSurfaceProxy()->uniqueID(); }
  
      // Allows caller of addDrawOp to know which op list an op will be added to.
      using WillAddOpFn = void(GrOp*, uint32_t opsTaskID);
      // These perform processing specific to GrDrawOp-derived ops before recording them into an
      // op list. Before adding the op to an op list the WillAddOpFn is called. Note that it
      // will not be called in the event that the op is discarded. Moreover, the op may merge into
      // another op after the function is called (either before addDrawOp returns or some time later).
      //
      // If the clip pointer is null, no clipping will be performed.
      void addDrawOp(const GrClip*,
                     GrOp::Owner,
                     const std::function<WillAddOpFn>& = std::function<WillAddOpFn>());
      void addDrawOp(GrOp::Owner op) { this->addDrawOp(nullptr, std::move(op)); }
  
      bool refsWrappedObjects() const { return this->asRenderTargetProxy()->refsWrappedObjects(); }
  
      /**
       *  The next time this GrSurfaceDrawContext is flushed, the gpu will wait on the passed in
       *  semaphores before executing any commands.
       */
      bool waitOnSemaphores(int numSemaphores, const GrBackendSemaphore waitSemaphores[],
                            bool deleteSemaphoresAfterWait);
  
      int numSamples() const { return this->asRenderTargetProxy()->numSamples(); }
      const SkSurfaceProps& surfaceProps() const { return fSurfaceProps; }
      bool canUseDynamicMSAA() const { return fCanUseDynamicMSAA; }
      bool wrapsVkSecondaryCB() const { return this->asRenderTargetProxy()->wrapsVkSecondaryCB(); }
      GrMipmapped mipmapped() const;
  
      bool alwaysAntialias() const {
          return fSurfaceProps.flags() & kDMSAA_SkSurfacePropsPrivateFlag;
      }
  
      GrAA chooseAA(const SkPaint& paint) {
          return GrAA(paint.isAntiAlias() || this->alwaysAntialias());
      }
  
      // This entry point should only be called if the backing GPU object is known to be
      // instantiated.
      GrRenderTarget* accessRenderTarget() { return this->asSurfaceProxy()->peekRenderTarget(); }
  
      GrSurfaceDrawContext* asRenderTargetContext() override { return this; }
  
  #if GR_TEST_UTILS
      void testingOnly_SetPreserveOpsOnFullClear() { fPreserveOpsOnFullClear_TestingOnly = true; }
  #endif
  
  private:
      enum class QuadOptimization;
  
      void willReplaceOpsTask(GrOpsTask* prevTask, GrOpsTask* nextTask) override;
  
      GrAAType chooseAAType(GrAA);
  
      GrOpsTask::CanDiscardPreviousOps canDiscardPreviousOpsOnFullClear() const override;
      void setNeedsStencil();
  
      void internalStencilClear(const SkIRect* scissor, bool insideStencilMask);
  
      // 'stencilSettings' are provided merely for decision making purposes; When non-null,
      // optimization strategies that submit special ops are avoided.
      //
      // 'aa' and 'quad' should be the original draw request on input, and will be updated as
      // appropriate depending on the returned optimization level.
      //
      // If kSubmitted is returned, the provided paint was consumed. Otherwise it is left unchanged.
      QuadOptimization attemptQuadOptimization(const GrClip* clip,
                                               const GrUserStencilSettings* stencilSettings,
                                               GrAA* aa,
                                               DrawQuad* quad,
                                               GrPaint* paint);
  
      // If stencil settings, 'ss', are non-null, AA controls MSAA or no AA. If they are null, then AA
      // can choose between coverage, MSAA as per chooseAAType(). This will always attempt to apply
      // quad optimizations, so all quad/rect public APIs should rely on this function for consistent
      // clipping behavior. 'quad' will be modified in place to reflect final rendered geometry.
      void drawFilledQuad(const GrClip* clip,
                          GrPaint&& paint,
                          GrAA aa,
                          DrawQuad* quad,
                          const GrUserStencilSettings* ss = nullptr);
  
      // Like drawFilledQuad but does not require using a GrPaint or FP for texturing.
      // 'quad' may be modified in place to reflect final geometry.
      void drawTexturedQuad(const GrClip* clip,
                            GrSurfaceProxyView proxyView,
                            SkAlphaType alphaType,
                            sk_sp<GrColorSpaceXform> textureXform,
                            GrSamplerState::Filter filter,
                            GrSamplerState::MipmapMode,
                            const SkPMColor4f& color,
                            SkBlendMode blendMode,
                            GrAA aa,
                            DrawQuad* quad,
                            const SkRect* subset = nullptr);
  
      void drawStrokedLine(const GrClip*, GrPaint&&, GrAA, const SkMatrix&, const SkPoint[2],
                           const SkStrokeRec&);
  
      // Tries to detect if the given shape is a simple, and draws it without path rendering if
      // we know how.
      bool drawSimpleShape(const GrClip*, GrPaint*, GrAA, const SkMatrix&, const GrStyledShape&);
  
      // If 'attemptDrawSimple' is true, of if the original shape is marked as having been simplfied,
      // this will attempt to re-route through drawSimpleShape() to see if we can avoid path rendering
      // one more time.
      void drawShapeUsingPathRenderer(const GrClip*, GrPaint&&, GrAA, const SkMatrix&,
                                      GrStyledShape&&, bool attemptDrawSimple = false);
  
      // Makes a copy of the proxy if it is necessary for the draw and places the texture that should
      // be used by GrXferProcessor to access the destination color in 'result'. If the return
      // value is false then a texture copy could not be made.
      //
      // The op should have already had setClippedBounds called on it.
      bool SK_WARN_UNUSED_RESULT setupDstProxyView(const GrOp& op,
                                                   GrXferProcessor::DstProxyView* result);
  
      SkGlyphRunListPainter* glyphPainter() { return &fGlyphPainter; }
  
      const SkSurfaceProps fSurfaceProps;
      const bool fCanUseDynamicMSAA;
  
      bool fNeedsStencil = false;
  
      GrDstSampleType fDstSampleType = GrDstSampleType::kNone;
  
  #if GR_TEST_UTILS
      bool fPreserveOpsOnFullClear_TestingOnly = false;
  #endif
      SkGlyphRunListPainter fGlyphPainter;
      using INHERITED = GrSurfaceFillContext;
  };
  
  #endif
  