1 /* 2 * Copyright 2015 Google Inc. 3 * 4 * Use of this source code is governed by a BSD-style license that can be 5 * found in the LICENSE file. 6 */ 7 8 #ifndef SkImage_Ganesh_DEFINED 9 #define SkImage_Ganesh_DEFINED 10 11 #include "include/core/SkRefCnt.h" 12 #include "include/core/SkSamplingOptions.h" 13 #include "include/private/base/SkDebug.h" 14 #include "include/private/base/SkThreadAnnotations.h" 15 #include "src/base/SkSpinlock.h" 16 #include "src/gpu/Swizzle.h" 17 #include "src/gpu/ganesh/GrSurfaceProxyView.h" 18 #include "src/gpu/ganesh/image/SkImage_GaneshBase.h" 19 #include "src/image/SkImage_Base.h" 20 21 #include <cstddef> 22 #include <cstdint> 23 #include <memory> 24 #include <tuple> 25 26 class GrBackendFormat; 27 class GrBackendTexture; 28 class GrDirectContext; 29 class GrFragmentProcessor; 30 class GrImageContext; 31 class GrRecordingContext; 32 class GrRenderTask; 33 class GrSurfaceProxy; 34 class SkColorInfo; 35 class SkColorSpace; 36 class SkImage; 37 class SkMatrix; 38 enum class GrColorType; 39 enum class GrImageTexGenPolicy : int; 40 enum class GrSemaphoresSubmitted : bool; 41 enum class SkTileMode; 42 enum GrSurfaceOrigin : int; 43 enum SkColorType : int; 44 enum SkYUVColorSpace : int; 45 struct GrFlushInfo; 46 struct SkIRect; 47 struct SkISize; 48 struct SkImageInfo; 49 struct SkRect; 50 51 namespace skgpu { 52 enum class Mipmapped : bool; 53 enum class Protected : bool; 54 } 55 56 class SkImage_Ganesh final : public SkImage_GaneshBase { 57 public: 58 SkImage_Ganesh(sk_sp<GrImageContext> context, 59 uint32_t uniqueID, 60 GrSurfaceProxyView view, 61 SkColorInfo info); 62 63 static sk_sp<SkImage> MakeWithVolatileSrc(sk_sp<GrRecordingContext> rContext, 64 GrSurfaceProxyView volatileSrc, 65 SkColorInfo colorInfo); 66 67 ~SkImage_Ganesh() override; 68 69 // From SkImage.h 70 size_t textureSize() const override; 71 72 // From SkImage_Base.h type()73 SkImage_Base::Type type() const override { return SkImage_Base::Type::kGanesh; } 74 75 bool onHasMipmaps() const override; 76 bool onIsProtected() const override; 77 78 using SkImage_GaneshBase::onMakeColorTypeAndColorSpace; 79 sk_sp<SkImage> onMakeColorTypeAndColorSpace(SkColorType, 80 sk_sp<SkColorSpace>, 81 GrDirectContext*) const final; 82 83 sk_sp<SkImage> onReinterpretColorSpace(sk_sp<SkColorSpace>) const final; 84 85 void onAsyncRescaleAndReadPixels(const SkImageInfo&, 86 SkIRect srcRect, 87 RescaleGamma, 88 RescaleMode, 89 ReadPixelsCallback, 90 ReadPixelsContext) const override; 91 92 void onAsyncRescaleAndReadPixelsYUV420(SkYUVColorSpace, 93 bool readAlpha, 94 sk_sp<SkColorSpace>, 95 SkIRect srcRect, 96 SkISize dstSize, 97 RescaleGamma, 98 RescaleMode, 99 ReadPixelsCallback, 100 ReadPixelsContext) const override; 101 102 void generatingSurfaceIsDeleted() override; 103 104 // From SkImage_GaneshBase.h 105 GrSemaphoresSubmitted flush(GrDirectContext*, const GrFlushInfo&) const override; 106 107 std::tuple<GrSurfaceProxyView, GrColorType> asView(GrRecordingContext*, 108 skgpu::Mipmapped, 109 GrImageTexGenPolicy) const override; 110 111 std::unique_ptr<GrFragmentProcessor> asFragmentProcessor(GrRecordingContext*, 112 SkSamplingOptions, 113 const SkTileMode[2], 114 const SkMatrix&, 115 const SkRect*, 116 const SkRect*) const override; 117 118 // If this is image is a cached SkSurface snapshot then this method is called by the SkSurface 119 // before a write to check if the surface must make a copy to avoid modifying the image's 120 // contents. 121 bool surfaceMustCopyOnWrite(GrSurfaceProxy* surfaceProxy) const; 122 123 bool getExistingBackendTexture(GrBackendTexture* outTexture, 124 bool flushPendingGrContextIO, 125 GrSurfaceOrigin* origin) const; 126 origin()127 GrSurfaceOrigin origin() const override { return fOrigin; } 128 129 private: 130 SkImage_Ganesh(sk_sp<GrDirectContext>, 131 GrSurfaceProxyView volatileSrc, 132 sk_sp<GrSurfaceProxy> stableCopy, 133 sk_sp<GrRenderTask> copyTask, 134 int volatileSrcTargetCount, 135 SkColorInfo); 136 137 GrSurfaceProxyView makeView(GrRecordingContext*) const; 138 139 // Thread-safe wrapper around the proxies backing this image. Handles dynamically switching 140 // from a "volatile" proxy that may be overwritten (by an SkSurface that this image was snapped 141 // from) to a "stable" proxy that is a copy of the volatile proxy. It allows the image to cancel 142 // the copy if the stable proxy is never required because the contents of the volatile proxy 143 // were never mutated by the SkSurface during the image lifetime. 144 class ProxyChooser { 145 public: 146 ProxyChooser(sk_sp<GrSurfaceProxy> stableProxy, 147 sk_sp<GrSurfaceProxy> volatileProxy, 148 sk_sp<GrRenderTask> copyTask, 149 int volatileProxyTargetCount); 150 151 ProxyChooser(sk_sp<GrSurfaceProxy> stableProxy); 152 153 ~ProxyChooser(); 154 155 // Checks if there is a volatile proxy that is safe to use. If so returns it, otherwise 156 // returns the stable proxy (and drops the volatile one if it exists). 157 sk_sp<GrSurfaceProxy> chooseProxy(GrRecordingContext* context) SK_EXCLUDES(fLock); 158 // Call when it is known copy is necessary. 159 sk_sp<GrSurfaceProxy> switchToStableProxy() SK_EXCLUDES(fLock); 160 // Call when it is known for sure copy won't be necessary. 161 sk_sp<GrSurfaceProxy> makeVolatileProxyStable() SK_EXCLUDES(fLock); 162 163 bool surfaceMustCopyOnWrite(GrSurfaceProxy* surfaceProxy) const SK_EXCLUDES(fLock); 164 165 // Queries that should be independent of which proxy is in use. 166 size_t gpuMemorySize() const SK_EXCLUDES(fLock); 167 skgpu::Mipmapped mipmapped() const SK_EXCLUDES(fLock); 168 skgpu::Protected isProtected() const SK_EXCLUDES(fLock); 169 #ifdef SK_DEBUG 170 const GrBackendFormat& backendFormat() SK_EXCLUDES(fLock); 171 #endif 172 173 private: 174 mutable SkSpinlock fLock; 175 sk_sp<GrSurfaceProxy> fStableProxy SK_GUARDED_BY(fLock); 176 sk_sp<GrSurfaceProxy> fVolatileProxy SK_GUARDED_BY(fLock); 177 sk_sp<GrRenderTask> fVolatileToStableCopyTask; 178 // The number of GrRenderTasks targeting the volatile proxy at creation time. If the 179 // proxy's target count increases it indicates additional writes and we must switch 180 // to using the stable copy. 181 const int fVolatileProxyTargetCount = 0; 182 }; 183 184 mutable ProxyChooser fChooser; 185 skgpu::Swizzle fSwizzle; 186 GrSurfaceOrigin fOrigin; 187 188 using INHERITED = SkImage_GaneshBase; 189 }; 190 191 #endif 192