/* * 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 SkImage_Ganesh_DEFINED #define SkImage_Ganesh_DEFINED #include "include/core/SkRefCnt.h" #include "include/core/SkSamplingOptions.h" #include "include/private/base/SkDebug.h" #include "include/private/base/SkThreadAnnotations.h" #include "src/base/SkSpinlock.h" #include "src/gpu/Swizzle.h" #include "src/gpu/ganesh/GrSurfaceProxyView.h" #include "src/gpu/ganesh/image/SkImage_GaneshBase.h" #include "src/image/SkImage_Base.h" #include #include #include #include class GrBackendFormat; class GrBackendTexture; class GrDirectContext; class GrFragmentProcessor; class GrImageContext; class GrRecordingContext; class GrRenderTask; class GrSurfaceProxy; class SkColorInfo; class SkColorSpace; class SkImage; class SkMatrix; enum class GrColorType; enum class GrImageTexGenPolicy : int; enum class GrSemaphoresSubmitted : bool; enum class SkTileMode; enum GrSurfaceOrigin : int; enum SkColorType : int; enum SkYUVColorSpace : int; struct GrFlushInfo; struct SkIRect; struct SkISize; struct SkImageInfo; struct SkRect; namespace skgpu { enum class Mipmapped : bool; enum class Protected : bool; } class SkImage_Ganesh final : public SkImage_GaneshBase { public: SkImage_Ganesh(sk_sp context, uint32_t uniqueID, GrSurfaceProxyView view, SkColorInfo info); static sk_sp MakeWithVolatileSrc(sk_sp rContext, GrSurfaceProxyView volatileSrc, SkColorInfo colorInfo); ~SkImage_Ganesh() override; // From SkImage.h size_t textureSize() const override; // From SkImage_Base.h SkImage_Base::Type type() const override { return SkImage_Base::Type::kGanesh; } bool onHasMipmaps() const override; bool onIsProtected() const override; using SkImage_GaneshBase::onMakeColorTypeAndColorSpace; sk_sp onMakeColorTypeAndColorSpace(SkColorType, sk_sp, GrDirectContext*) const final; sk_sp onReinterpretColorSpace(sk_sp) const final; void onAsyncRescaleAndReadPixels(const SkImageInfo&, SkIRect srcRect, RescaleGamma, RescaleMode, ReadPixelsCallback, ReadPixelsContext) const override; void onAsyncRescaleAndReadPixelsYUV420(SkYUVColorSpace, bool readAlpha, sk_sp, SkIRect srcRect, SkISize dstSize, RescaleGamma, RescaleMode, ReadPixelsCallback, ReadPixelsContext) const override; void generatingSurfaceIsDeleted() override; // From SkImage_GaneshBase.h GrSemaphoresSubmitted flush(GrDirectContext*, const GrFlushInfo&) const override; std::tuple asView(GrRecordingContext*, skgpu::Mipmapped, GrImageTexGenPolicy) const override; std::unique_ptr asFragmentProcessor(GrRecordingContext*, SkSamplingOptions, const SkTileMode[2], const SkMatrix&, const SkRect*, const SkRect*) const override; // If this is image is a cached SkSurface snapshot then this method is called by the SkSurface // before a write to check if the surface must make a copy to avoid modifying the image's // contents. bool surfaceMustCopyOnWrite(GrSurfaceProxy* surfaceProxy) const; bool getExistingBackendTexture(GrBackendTexture* outTexture, bool flushPendingGrContextIO, GrSurfaceOrigin* origin) const; GrSurfaceOrigin origin() const override { return fOrigin; } private: SkImage_Ganesh(sk_sp, GrSurfaceProxyView volatileSrc, sk_sp stableCopy, sk_sp copyTask, int volatileSrcTargetCount, SkColorInfo); GrSurfaceProxyView makeView(GrRecordingContext*) const; // Thread-safe wrapper around the proxies backing this image. Handles dynamically switching // from a "volatile" proxy that may be overwritten (by an SkSurface that this image was snapped // from) to a "stable" proxy that is a copy of the volatile proxy. It allows the image to cancel // the copy if the stable proxy is never required because the contents of the volatile proxy // were never mutated by the SkSurface during the image lifetime. class ProxyChooser { public: ProxyChooser(sk_sp stableProxy, sk_sp volatileProxy, sk_sp copyTask, int volatileProxyTargetCount); ProxyChooser(sk_sp stableProxy); ~ProxyChooser(); // Checks if there is a volatile proxy that is safe to use. If so returns it, otherwise // returns the stable proxy (and drops the volatile one if it exists). sk_sp chooseProxy(GrRecordingContext* context) SK_EXCLUDES(fLock); // Call when it is known copy is necessary. sk_sp switchToStableProxy() SK_EXCLUDES(fLock); // Call when it is known for sure copy won't be necessary. sk_sp makeVolatileProxyStable() SK_EXCLUDES(fLock); bool surfaceMustCopyOnWrite(GrSurfaceProxy* surfaceProxy) const SK_EXCLUDES(fLock); // Queries that should be independent of which proxy is in use. size_t gpuMemorySize() const SK_EXCLUDES(fLock); skgpu::Mipmapped mipmapped() const SK_EXCLUDES(fLock); skgpu::Protected isProtected() const SK_EXCLUDES(fLock); #ifdef SK_DEBUG const GrBackendFormat& backendFormat() SK_EXCLUDES(fLock); #endif private: mutable SkSpinlock fLock; sk_sp fStableProxy SK_GUARDED_BY(fLock); sk_sp fVolatileProxy SK_GUARDED_BY(fLock); sk_sp fVolatileToStableCopyTask; // The number of GrRenderTasks targeting the volatile proxy at creation time. If the // proxy's target count increases it indicates additional writes and we must switch // to using the stable copy. const int fVolatileProxyTargetCount = 0; }; mutable ProxyChooser fChooser; skgpu::Swizzle fSwizzle; GrSurfaceOrigin fOrigin; using INHERITED = SkImage_GaneshBase; }; #endif