| /* | |
| * Copyright 2021 Google LLC | |
| * | |
| * Use of this source code is governed by a BSD-style license that can be | |
| * found in the LICENSE file. | |
| */ | |
| #ifndef skgpu_graphite_Surface_Graphite_DEFINED | |
| #define skgpu_graphite_Surface_Graphite_DEFINED | |
| #include "include/core/SkRecorder.h" | |
| #include "src/image/SkSurface_Base.h" | |
| #include "include/gpu/GpuTypes.h" | |
| #include "src/gpu/SkBackingFit.h" | |
| #include "src/gpu/graphite/ResourceTypes.h" | |
| #include "src/gpu/graphite/TextureProxyView.h" | |
| namespace skgpu::graphite { | |
| class Context; | |
| class Device; | |
| class DrawContext; | |
| class Image; | |
| class Recorder; | |
| class TextureProxy; | |
| class Surface final : public SkSurface_Base { | |
| public: | |
| // Convenience factory to create a Device, instantiate its target proxy and return as a Surface. | |
| static sk_sp<Surface> Make(Recorder* recorder, | |
| const SkImageInfo& info, | |
| std::string_view label, | |
| Budgeted budgeted, | |
| Mipmapped mipmapped = Mipmapped::kNo, | |
| SkBackingFit backingFit = SkBackingFit::kExact, | |
| const SkSurfaceProps* props = nullptr) { | |
| return Make(recorder, info, label, budgeted, mipmapped, backingFit, props, | |
| LoadOp::kClear, /*registerWithRecorder=*/true, /*allowUnpremul=*/false); | |
| } | |
| // Make a surface that is not registered with the provided recorder. This surface should be | |
| // short-lived and it must be flushed manually for its draw commands to be recorded. Most | |
| // scratch surfaces will be budgeted, but if the underlying texture is being returned as a | |
| // client-owned image, that may not be the case. | |
| // | |
| // allowUnpremul=true should only be used if the surface is only going to be rendered | |
| // into with src-blending with calls to drawPaint or pixel-aligned drawRect calls to | |
| // avoid anti-aliasing. | |
| static sk_sp<Surface> MakeScratch(Recorder* recorder, | |
| const SkImageInfo& info, | |
| std::string_view label, | |
| Budgeted budgeted = Budgeted::kYes, | |
| Mipmapped mipmapped = Mipmapped::kNo, | |
| SkBackingFit backingFit = SkBackingFit::kApprox, | |
| bool allowUnpremul = false) { | |
| return Make(recorder, info, label, budgeted, mipmapped, backingFit, | |
| /*props=*/nullptr, LoadOp::kDiscard, /*registerWithRecorder=*/false, | |
| allowUnpremul); | |
| } | |
| Surface(sk_sp<Device>); | |
| ~Surface() override; | |
| // From SkSurface.h | |
| SkImageInfo imageInfo() const override; | |
| // From SkSurface_Base.h | |
| SkSurface_Base::Type type() const override { return SkSurface_Base::Type::kGraphite; } | |
| Recorder* onGetRecorder() const override; | |
| SkRecorder* onGetBaseRecorder() const override; | |
| SkCanvas* onNewCanvas() override; | |
| sk_sp<SkSurface> onNewSurface(const SkImageInfo&) override; | |
| sk_sp<SkImage> onNewImageSnapshot(const SkIRect* subset) override; | |
| sk_sp<SkImage> onMakeTemporaryImage() override; | |
| void onWritePixels(const SkPixmap&, int x, int y) override; | |
| void onAsyncRescaleAndReadPixels(const SkImageInfo& info, | |
| SkIRect srcRect, | |
| RescaleGamma rescaleGamma, | |
| RescaleMode rescaleMode, | |
| ReadPixelsCallback callback, | |
| ReadPixelsContext context) override; | |
| void onAsyncRescaleAndReadPixelsYUV420(SkYUVColorSpace yuvColorSpace, | |
| bool readAlpha, | |
| sk_sp<SkColorSpace> dstColorSpace, | |
| SkIRect srcRect, | |
| SkISize dstSize, | |
| RescaleGamma rescaleGamma, | |
| RescaleMode, | |
| ReadPixelsCallback callback, | |
| ReadPixelsContext context) override; | |
| bool onCopyOnWrite(ContentChangeMode) override; | |
| sk_sp<const SkCapabilities> onCapabilities() override; | |
| // May not be texturable, but includes the swizzle required when sampling or reading to CPU | |
| const TextureProxyView& target() const; | |
| TextureProxyView readSurfaceView() const; | |
| // Will be null if the target is not texturable. | |
| sk_sp<Image> asImage() const; | |
| // Shares the texture but returns an Image with adjusted SkColorInfo to reflect the compatible | |
| // `otherCT` and `otherAT`. | |
| sk_sp<Image> asImage(SkColorType otherCT, SkAlphaType otherAT) const; | |
| sk_sp<Image> makeImageCopy(const SkIRect* subset, Mipmapped) const; | |
| void flushToDrawContext(DrawContext*); | |
| private: | |
| // Regular and scratch surfaces differ by initial clear and if they are registered or not, | |
| // otherwise are constructed the same. | |
| // | |
| // allowUnpremul=true should only be used if the surface is only going to be rendered | |
| // into with src-blending with calls to drawPaint or pixel-aligned drawRect calls to | |
| // avoid anti-aliasing. | |
| static sk_sp<Surface> Make(Recorder* recorder, | |
| const SkImageInfo&, | |
| std::string_view label, | |
| Budgeted, | |
| Mipmapped, | |
| SkBackingFit, | |
| const SkSurfaceProps* props, | |
| LoadOp initialLoadOp, | |
| bool registerWithRecorder, | |
| bool allowUnpremul); | |
| sk_sp<Device> fDevice; | |
| sk_sp<Image> fImageView; // the image object returned by asImage() | |
| friend void Flush(SkSurface*); | |
| }; | |
| // TODO: The long-term for the public API around surfaces and flushing/submitting will likely | |
| // be replaced with explicit control over Recorders and submitting Recordings to the Context | |
| // directly. For now, internal tools often rely on surface/canvas flushing to control what's | |
| // being timed (nanobench or viewer's stats layer), so we flush any pending draws to a DrawPass. | |
| // While this won't measure actual conversion of the task list to backend command buffers, that | |
| // should be fairly negligible since most of the work is handled in DrawPass::Make(). | |
| // Additionally flushing pending work here ensures we don't batch across or clear prior recorded | |
| // work when looping in a benchmark, as the controlling code expects. | |
| void Flush(sk_sp<SkSurface> surface); | |
| void Flush(SkSurface* surface); | |
| } // namespace skgpu::graphite | |
| #endif // skgpu_graphite_Surface_Graphite_DEFINED |