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 void hintCacheGpuResource() override; 105 // From SkImage_GaneshBase.h 106 GrSemaphoresSubmitted flush(GrDirectContext*, const GrFlushInfo&) const override; 107 108 std::tuple<GrSurfaceProxyView, GrColorType> asView(GrRecordingContext*, 109 skgpu::Mipmapped, 110 GrImageTexGenPolicy) const override; 111 112 std::unique_ptr<GrFragmentProcessor> asFragmentProcessor(GrRecordingContext*, 113 SkSamplingOptions, 114 const SkTileMode[2], 115 const SkMatrix&, 116 const SkRect*, 117 const SkRect*) const override; 118 119 // If this is image is a cached SkSurface snapshot then this method is called by the SkSurface 120 // before a write to check if the surface must make a copy to avoid modifying the image's 121 // contents. 122 bool surfaceMustCopyOnWrite(GrSurfaceProxy* surfaceProxy) const; 123 124 bool getExistingBackendTexture(GrBackendTexture* outTexture, 125 bool flushPendingGrContextIO, 126 GrSurfaceOrigin* origin) const; 127 origin()128 GrSurfaceOrigin origin() const override { return fOrigin; } 129 130 private: 131 SkImage_Ganesh(sk_sp<GrDirectContext>, 132 GrSurfaceProxyView volatileSrc, 133 sk_sp<GrSurfaceProxy> stableCopy, 134 sk_sp<GrRenderTask> copyTask, 135 int volatileSrcTargetCount, 136 SkColorInfo); 137 138 GrSurfaceProxyView makeView(GrRecordingContext*) const; 139 140 // Thread-safe wrapper around the proxies backing this image. Handles dynamically switching 141 // from a "volatile" proxy that may be overwritten (by an SkSurface that this image was snapped 142 // from) to a "stable" proxy that is a copy of the volatile proxy. It allows the image to cancel 143 // the copy if the stable proxy is never required because the contents of the volatile proxy 144 // were never mutated by the SkSurface during the image lifetime. 145 class ProxyChooser { 146 public: 147 ProxyChooser(sk_sp<GrSurfaceProxy> stableProxy, 148 sk_sp<GrSurfaceProxy> volatileProxy, 149 sk_sp<GrRenderTask> copyTask, 150 int volatileProxyTargetCount); 151 152 ProxyChooser(sk_sp<GrSurfaceProxy> stableProxy); 153 154 ~ProxyChooser(); 155 156 // Checks if there is a volatile proxy that is safe to use. If so returns it, otherwise 157 // returns the stable proxy (and drops the volatile one if it exists). 158 sk_sp<GrSurfaceProxy> chooseProxy(GrRecordingContext* context) SK_EXCLUDES(fLock); 159 // Call when it is known copy is necessary. 160 sk_sp<GrSurfaceProxy> switchToStableProxy() SK_EXCLUDES(fLock); 161 // Call when it is known for sure copy won't be necessary. 162 sk_sp<GrSurfaceProxy> makeVolatileProxyStable() SK_EXCLUDES(fLock); 163 164 bool surfaceMustCopyOnWrite(GrSurfaceProxy* surfaceProxy) const SK_EXCLUDES(fLock); 165 166 // Queries that should be independent of which proxy is in use. 167 size_t gpuMemorySize() const SK_EXCLUDES(fLock); 168 skgpu::Mipmapped mipmapped() const SK_EXCLUDES(fLock); 169 skgpu::Protected isProtected() const SK_EXCLUDES(fLock); 170 #ifdef SK_DEBUG 171 const GrBackendFormat& backendFormat() SK_EXCLUDES(fLock); 172 #endif 173 174 private: 175 mutable SkSpinlock fLock; 176 sk_sp<GrSurfaceProxy> fStableProxy SK_GUARDED_BY(fLock); 177 sk_sp<GrSurfaceProxy> fVolatileProxy SK_GUARDED_BY(fLock); 178 sk_sp<GrRenderTask> fVolatileToStableCopyTask; 179 // The number of GrRenderTasks targeting the volatile proxy at creation time. If the 180 // proxy's target count increases it indicates additional writes and we must switch 181 // to using the stable copy. 182 const int fVolatileProxyTargetCount = 0; 183 }; 184 185 mutable ProxyChooser fChooser; 186 skgpu::Swizzle fSwizzle; 187 GrSurfaceOrigin fOrigin; 188 189 using INHERITED = SkImage_GaneshBase; 190 }; 191 192 #endif 193