/* * Copyright 2010 Google Inc. * * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ #ifndef skgpu_v1_Device_DEFINED #define skgpu_v1_Device_DEFINED #include "include/core/SkCanvas.h" #include "include/core/SkClipOp.h" #include "include/core/SkColor.h" #include "include/core/SkImage.h" #include "include/core/SkImageInfo.h" #include "include/core/SkRect.h" #include "include/core/SkRefCnt.h" #include "include/core/SkSamplingOptions.h" #include "include/core/SkShader.h" #include "include/core/SkSurface.h" #include "include/gpu/ganesh/GrTypes.h" #include "include/private/base/SkAssert.h" #include "include/private/base/SkMacros.h" #include "src/core/SkDevice.h" #include "src/core/SkMatrixPriv.h" #include "src/gpu/ganesh/ClipStack.h" #include "src/gpu/ganesh/GrColorInfo.h" #include "src/gpu/ganesh/GrSurfaceProxyView.h" #include "src/text/gpu/SubRunControl.h" #include #include #include class GrBackendSemaphore; class GrClip; class GrRecordingContext; class GrRenderTargetProxy; class GrSurfaceProxy; class SkBitmap; class SkBlender; class SkColorSpace; class SkDrawable; class SkLatticeIter; class SkMatrix; class SkMesh; class SkPaint; class SkPath; class SkPixmap; class SkRRect; class SkRegion; class SkSpecialImage; class SkSurfaceProps; class SkSurface_Ganesh; class SkVertices; enum SkAlphaType : int; enum SkColorType : int; enum class GrAA : bool; enum class GrColorType; enum class SkBackingFit; enum class SkBlendMode; enum class SkTileMode; struct SkArc; struct SkDrawShadowRec; struct SkISize; struct SkPoint; struct SkRSXform; namespace skgpu { enum class Budgeted : bool; enum class Mipmapped : bool; class TiledTextureUtils; } namespace skif { class Backend; } namespace sktext { class GlyphRunList; namespace gpu { class Slug; }} namespace skgpu::ganesh { class SurfaceContext; class SurfaceFillContext; class SurfaceDrawContext; /** * Subclass of SkDevice, which directs all drawing to the GrGpu owned by the canvas. */ class Device final : public SkDevice { public: enum class InitContents { kClear, kUninit }; GrSurfaceProxyView readSurfaceView(); GrRenderTargetProxy* targetProxy(); GrRecordingContext* recordingContext() const override { return fContext.get(); } bool wait(int numSemaphores, const GrBackendSemaphore* waitSemaphores, bool deleteSemaphoresAfterWait); void discard(); void resolveMSAA(); bool replaceBackingProxy(SkSurface::ContentChangeMode, sk_sp, GrColorType, sk_sp, GrSurfaceOrigin, const SkSurfaceProps&); bool replaceBackingProxy(SkSurface::ContentChangeMode); using RescaleGamma = SkImage::RescaleGamma; using RescaleMode = SkImage::RescaleMode; using ReadPixelsCallback = SkImage::ReadPixelsCallback; using ReadPixelsContext = SkImage::ReadPixelsContext; void asyncRescaleAndReadPixels(const SkImageInfo& info, const SkIRect& srcRect, RescaleGamma rescaleGamma, RescaleMode rescaleMode, ReadPixelsCallback callback, ReadPixelsContext context); void asyncRescaleAndReadPixelsYUV420(SkYUVColorSpace yuvColorSpace, bool readAlpha, sk_sp dstColorSpace, const SkIRect& srcRect, SkISize dstSize, RescaleGamma rescaleGamma, RescaleMode, ReadPixelsCallback callback, ReadPixelsContext context); /** * This factory uses the color space, origin, surface properties, and initialization * method along with the provided proxy to create the gpu device. */ static sk_sp Make(GrRecordingContext*, GrColorType, sk_sp, sk_sp, GrSurfaceOrigin, const SkSurfaceProps&, InitContents); /** * This factory uses the budgeted, imageInfo, fit, sampleCount, mipmapped, and isProtected * parameters to create a proxy to back the gpu device. The color space (from the image info), * origin, surface properties, and initialization method are then used (with the created proxy) * to create the device. */ static sk_sp Make(GrRecordingContext*, skgpu::Budgeted, const SkImageInfo&, SkBackingFit, int sampleCount, skgpu::Mipmapped, GrProtected, GrSurfaceOrigin, const SkSurfaceProps&, InitContents); ~Device() override; SurfaceDrawContext* surfaceDrawContext(); const SurfaceDrawContext* surfaceDrawContext() const; SurfaceFillContext* surfaceFillContext(); SkStrikeDeviceInfo strikeDeviceInfo() const override; // set all pixels to 0 void clearAll(); void drawPaint(const SkPaint& paint) override; void drawPoints(SkCanvas::PointMode mode, size_t count, const SkPoint[], const SkPaint& paint) override; void drawRect(const SkRect& r, const SkPaint& paint) override; void drawRRect(const SkRRect& r, const SkPaint& paint) override; void drawDRRect(const SkRRect& outer, const SkRRect& inner, const SkPaint& paint) override; void drawRegion(const SkRegion& r, const SkPaint& paint) override; void drawOval(const SkRect& oval, const SkPaint& paint) override; void drawArc(const SkArc& arc, const SkPaint& paint) override; void drawPath(const SkPath& path, const SkPaint& paint, bool pathIsMutable) override; void drawVertices(const SkVertices*, sk_sp, const SkPaint&, bool) override; void drawMesh(const SkMesh&, sk_sp, const SkPaint&) override; #if !defined(SK_ENABLE_OPTIMIZE_SIZE) void drawShadow(const SkPath&, const SkDrawShadowRec&) override; #endif void drawAtlas(const SkRSXform[], const SkRect[], const SkColor[], int count, sk_sp, const SkPaint&) override; void drawImageRect(const SkImage*, const SkRect* src, const SkRect& dst, const SkSamplingOptions&, const SkPaint&, SkCanvas::SrcRectConstraint) override; bool shouldDrawAsTiledImageRect() const override { return true; } bool drawAsTiledImageRect(SkCanvas*, const SkImage*, const SkRect* src, const SkRect& dst, const SkSamplingOptions&, const SkPaint&, SkCanvas::SrcRectConstraint) override; void drawImageLattice(const SkImage*, const SkCanvas::Lattice&, const SkRect& dst, SkFilterMode, const SkPaint&) override; void drawDrawable(SkCanvas*, SkDrawable*, const SkMatrix*) override; void drawDevice(SkDevice*, const SkSamplingOptions&, const SkPaint&) override; void drawSpecial(SkSpecialImage*, const SkMatrix& localToDevice, const SkSamplingOptions&, const SkPaint&, SkCanvas::SrcRectConstraint) override; void drawEdgeAAQuad(const SkRect& rect, const SkPoint clip[4], SkCanvas::QuadAAFlags aaFlags, const SkColor4f& color, SkBlendMode mode) override; void drawEdgeAAImageSet(const SkCanvas::ImageSetEntry[], int count, const SkPoint dstClips[], const SkMatrix preViewMatrices[], const SkSamplingOptions&, const SkPaint&, SkCanvas::SrcRectConstraint) override; // Assumes the src and dst rects have already been optimized to fit the proxy. // Only implemented by the gpu devices. // This method is the lowest level draw used for tiled bitmap draws. It doesn't attempt to // modify its parameters (e.g., adjust src & dst) but just draws the image however it can. It // could, almost, be replaced with a drawEdgeAAImageSet call for the tiled bitmap draw use // case but the extra tilemode requirement and the intermediate parameter processing (e.g., // trying to alter the SrcRectConstraint) currently block that. void drawEdgeAAImage(const SkImage*, const SkRect& src, const SkRect& dst, const SkPoint dstClip[4], SkCanvas::QuadAAFlags, const SkMatrix& localToDevice, const SkSamplingOptions&, const SkPaint&, SkCanvas::SrcRectConstraint, const SkMatrix& srcToDst, SkTileMode); sk_sp convertGlyphRunListToSlug(const sktext::GlyphRunList& glyphRunList, const SkPaint& paint) override; void drawSlug(SkCanvas*, const sktext::gpu::Slug* slug, const SkPaint& paint) override; sk_sp makeSpecial(const SkBitmap&) override; sk_sp makeSpecial(const SkImage*) override; sk_sp snapSpecial(const SkIRect& subset, bool forceCopy = false) override; sk_sp snapSpecialScaled(const SkIRect& subset, const SkISize& dstDims) override; sk_sp createDevice(const CreateInfo&, const SkPaint*) override; sk_sp makeSurface(const SkImageInfo&, const SkSurfaceProps&) override; Device* asGaneshDevice() override { return this; } SkIRect devClipBounds() const override { return fClip.getConservativeBounds(); } void pushClipStack() override { fClip.save(); } void popClipStack() override { fClip.restore(); } void clipRect(const SkRect& rect, SkClipOp op, bool aa) override { SkASSERT(op == SkClipOp::kIntersect || op == SkClipOp::kDifference); fClip.clipRect(this->localToDevice(), rect, GrAA(aa), op); } void clipRRect(const SkRRect& rrect, SkClipOp op, bool aa) override { SkASSERT(op == SkClipOp::kIntersect || op == SkClipOp::kDifference); fClip.clipRRect(this->localToDevice(), rrect, GrAA(aa), op); } void clipPath(const SkPath& path, SkClipOp op, bool aa) override; void replaceClip(const SkIRect& rect) override { // Transform from "global/canvas" coordinates to relative to this device SkRect deviceRect = SkMatrixPriv::MapRect(this->globalToDevice(), SkRect::Make(rect)); fClip.replaceClip(deviceRect.round()); } void clipRegion(const SkRegion& globalRgn, SkClipOp op) override; bool isClipAntiAliased() const override; bool isClipEmpty() const override { return fClip.clipState() == ClipStack::ClipState::kEmpty; } bool isClipRect() const override { return fClip.clipState() == ClipStack::ClipState::kDeviceRect || fClip.clipState() == ClipStack::ClipState::kWideOpen; } bool isClipWideOpen() const override { return fClip.clipState() == ClipStack::ClipState::kWideOpen; } void android_utils_clipAsRgn(SkRegion*) const override; bool android_utils_clipWithStencil() override; private: enum class DeviceFlags { kNone = 0, kNeedClear = 1 << 0, //!< Surface requires an initial clear kIsOpaque = 1 << 1, //!< Hint from client that rendering to this device will be // opaque even if the config supports alpha. }; SK_DECL_BITFIELD_CLASS_OPS_FRIENDS(DeviceFlags); static SkImageInfo MakeInfo(SurfaceContext*, DeviceFlags); static bool CheckAlphaTypeAndGetFlags(SkAlphaType, InitContents, DeviceFlags*); sk_sp fContext; const sktext::gpu::SubRunControl fSubRunControl; std::unique_ptr fSurfaceDrawContext; ClipStack fClip; static sk_sp Make(std::unique_ptr, SkAlphaType, InitContents); Device(std::unique_ptr, DeviceFlags); void onDrawGlyphRunList(SkCanvas*, const sktext::GlyphRunList&, const SkPaint& paint) override; bool onReadPixels(const SkPixmap&, int, int) override; bool onWritePixels(const SkPixmap&, int, int) override; bool onAccessPixels(SkPixmap*) override; sk_sp createImageFilteringBackend(const SkSurfaceProps& surfaceProps, SkColorType colorType) const override; void onClipShader(sk_sp shader) override { fClip.clipShader(std::move(shader)); } const GrClip* clip() const { return &fClip; } // If not null, dstClip must be contained inside dst and will also respect the edge AA flags. // If 'preViewMatrix' is not null, final CTM will be this->ctm() * preViewMatrix. void drawImageQuadDirect(const SkImage*, const SkRect& src, const SkRect& dst, const SkPoint dstClip[4], SkCanvas::QuadAAFlags, const SkMatrix* preViewMatrix, const SkSamplingOptions&, const SkPaint&, SkCanvas::SrcRectConstraint); // FIXME(michaelludwig) - Should be removed in favor of using drawImageQuad with edge flags to // for every element in the SkLatticeIter. void drawViewLattice(GrSurfaceProxyView, const GrColorInfo& colorInfo, std::unique_ptr, const SkRect& dst, SkFilterMode, const SkPaint&); friend class ::SkSurface_Ganesh; // for access to surfaceProps friend class skgpu::TiledTextureUtils; // for access to clip() }; SK_MAKE_BITFIELD_CLASS_OPS(Device::DeviceFlags) } // namespace skgpu::ganesh #endif // skgpu_v1_Device_DEFINED