1 /* 2 * Copyright 2010 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 skgpu_v1_Device_DEFINED 9 #define skgpu_v1_Device_DEFINED 10 11 #include "include/core/SkCanvas.h" 12 #include "include/core/SkClipOp.h" 13 #include "include/core/SkColor.h" 14 #include "include/core/SkImage.h" 15 #include "include/core/SkImageInfo.h" 16 #include "include/core/SkRect.h" 17 #include "include/core/SkRefCnt.h" 18 #include "include/core/SkSamplingOptions.h" 19 #include "include/core/SkShader.h" 20 #include "include/core/SkSurface.h" 21 #include "include/gpu/GrTypes.h" 22 #include "include/private/base/SkAssert.h" 23 #include "src/core/SkDevice.h" 24 #include "src/core/SkMatrixPriv.h" 25 #include "src/gpu/ganesh/ClipStack.h" 26 #include "src/gpu/ganesh/GrColorInfo.h" 27 #include "src/gpu/ganesh/GrSurfaceProxyView.h" 28 #include "src/text/gpu/SDFTControl.h" 29 30 #include <cstddef> 31 #include <memory> 32 #include <utility> 33 34 class GrBackendSemaphore; 35 class GrClip; 36 class GrRecordingContext; 37 class GrRenderTargetProxy; 38 class GrSurfaceProxy; 39 class SkBitmap; 40 class SkBlender; 41 class SkColorSpace; 42 class SkDrawable; 43 class SkLatticeIter; 44 class SkMatrix; 45 class SkMesh; 46 class SkPaint; 47 class SkPath; 48 class SkPixmap; 49 class SkRRect; 50 class SkRegion; 51 class SkSpecialImage; 52 class SkSurfaceProps; 53 class SkSurface_Ganesh; 54 class SkVertices; 55 enum SkAlphaType : int; 56 enum SkColorType : int; 57 enum class GrAA : bool; 58 enum class GrColorType; 59 enum class SkBackingFit; 60 enum class SkBlendMode; 61 enum class SkTileMode; 62 struct SkArc; 63 struct SkDrawShadowRec; 64 struct SkISize; 65 struct SkPoint; 66 struct SkRSXform; 67 namespace skgpu { 68 enum class Budgeted : bool; 69 enum class Mipmapped : bool; 70 class TiledTextureUtils; 71 } 72 namespace skif { 73 class Backend; 74 } 75 namespace sktext { 76 class GlyphRunList; 77 namespace gpu { 78 class Slug; 79 }} 80 81 82 namespace skgpu::ganesh { 83 84 class SurfaceContext; 85 class SurfaceFillContext; 86 class SurfaceDrawContext; 87 88 /** 89 * Subclass of SkDevice, which directs all drawing to the GrGpu owned by the canvas. 90 */ 91 class Device final : public SkDevice { 92 public: 93 enum class InitContents { 94 kClear, 95 kUninit 96 }; 97 98 GrSurfaceProxyView readSurfaceView(); 99 GrRenderTargetProxy* targetProxy(); 100 recordingContext()101 GrRecordingContext* recordingContext() const override { return fContext.get(); } 102 103 bool wait(int numSemaphores, 104 const GrBackendSemaphore* waitSemaphores, 105 bool deleteSemaphoresAfterWait); 106 107 void discard(); 108 void resolveMSAA(); 109 110 bool replaceBackingProxy(SkSurface::ContentChangeMode, 111 sk_sp<GrRenderTargetProxy>, 112 GrColorType, 113 sk_sp<SkColorSpace>, 114 GrSurfaceOrigin, 115 const SkSurfaceProps&); 116 bool replaceBackingProxy(SkSurface::ContentChangeMode); 117 118 using RescaleGamma = SkImage::RescaleGamma; 119 using RescaleMode = SkImage::RescaleMode; 120 using ReadPixelsCallback = SkImage::ReadPixelsCallback; 121 using ReadPixelsContext = SkImage::ReadPixelsContext; 122 123 void asyncRescaleAndReadPixels(const SkImageInfo& info, 124 const SkIRect& srcRect, 125 RescaleGamma rescaleGamma, 126 RescaleMode rescaleMode, 127 ReadPixelsCallback callback, 128 ReadPixelsContext context); 129 130 void asyncRescaleAndReadPixelsYUV420(SkYUVColorSpace yuvColorSpace, 131 bool readAlpha, 132 sk_sp<SkColorSpace> dstColorSpace, 133 const SkIRect& srcRect, 134 SkISize dstSize, 135 RescaleGamma rescaleGamma, 136 RescaleMode, 137 ReadPixelsCallback callback, 138 ReadPixelsContext context); 139 140 /** 141 * This factory uses the color space, origin, surface properties, and initialization 142 * method along with the provided proxy to create the gpu device. 143 */ 144 static sk_sp<Device> Make(GrRecordingContext*, 145 GrColorType, 146 sk_sp<GrSurfaceProxy>, 147 sk_sp<SkColorSpace>, 148 GrSurfaceOrigin, 149 const SkSurfaceProps&, 150 InitContents); 151 152 /** 153 * This factory uses the budgeted, imageInfo, fit, sampleCount, mipmapped, and isProtected 154 * parameters to create a proxy to back the gpu device. The color space (from the image info), 155 * origin, surface properties, and initialization method are then used (with the created proxy) 156 * to create the device. 157 */ 158 static sk_sp<Device> Make(GrRecordingContext*, 159 skgpu::Budgeted, 160 const SkImageInfo&, 161 SkBackingFit, 162 int sampleCount, 163 skgpu::Mipmapped, 164 GrProtected, 165 GrSurfaceOrigin, 166 const SkSurfaceProps&, 167 InitContents); 168 169 ~Device() override; 170 171 SurfaceDrawContext* surfaceDrawContext(); 172 const SurfaceDrawContext* surfaceDrawContext() const; 173 SurfaceFillContext* surfaceFillContext(); 174 175 SkStrikeDeviceInfo strikeDeviceInfo() const override; 176 177 // set all pixels to 0 178 void clearAll(); 179 180 void drawPaint(const SkPaint& paint) override; 181 void drawPoints(SkCanvas::PointMode mode, size_t count, const SkPoint[], 182 const SkPaint& paint) override; 183 void drawRect(const SkRect& r, const SkPaint& paint) override; 184 void drawRRect(const SkRRect& r, const SkPaint& paint) override; 185 void drawDRRect(const SkRRect& outer, const SkRRect& inner, const SkPaint& paint) override; 186 void drawRegion(const SkRegion& r, const SkPaint& paint) override; 187 void drawOval(const SkRect& oval, const SkPaint& paint) override; 188 void drawArc(const SkArc& arc, const SkPaint& paint) override; 189 void drawPath(const SkPath& path, const SkPaint& paint, bool pathIsMutable) override; 190 191 void drawVertices(const SkVertices*, sk_sp<SkBlender>, const SkPaint&, bool) override; 192 void drawMesh(const SkMesh&, sk_sp<SkBlender>, const SkPaint&) override; 193 #if !defined(SK_ENABLE_OPTIMIZE_SIZE) 194 void drawShadow(const SkPath&, const SkDrawShadowRec&) override; 195 #endif 196 void drawAtlas(const SkRSXform[], const SkRect[], const SkColor[], int count, sk_sp<SkBlender>, 197 const SkPaint&) override; 198 199 void drawImageRect(const SkImage*, const SkRect* src, const SkRect& dst, 200 const SkSamplingOptions&, const SkPaint&, 201 SkCanvas::SrcRectConstraint) override; shouldDrawAsTiledImageRect()202 bool shouldDrawAsTiledImageRect() const override { return true; } 203 bool drawAsTiledImageRect(SkCanvas*, 204 const SkImage*, 205 const SkRect* src, 206 const SkRect& dst, 207 const SkSamplingOptions&, 208 const SkPaint&, 209 SkCanvas::SrcRectConstraint) override; 210 void drawImageLattice(const SkImage*, const SkCanvas::Lattice&, 211 const SkRect& dst, SkFilterMode, const SkPaint&) override; 212 213 void drawDrawable(SkCanvas*, SkDrawable*, const SkMatrix*) override; 214 215 void drawDevice(SkDevice*, const SkSamplingOptions&, const SkPaint&) override; 216 void drawSpecial(SkSpecialImage*, const SkMatrix& localToDevice, const SkSamplingOptions&, 217 const SkPaint&, SkCanvas::SrcRectConstraint) override; 218 219 void drawEdgeAAQuad(const SkRect& rect, const SkPoint clip[4], SkCanvas::QuadAAFlags aaFlags, 220 const SkColor4f& color, SkBlendMode mode) override; 221 void drawEdgeAAImageSet(const SkCanvas::ImageSetEntry[], int count, const SkPoint dstClips[], 222 const SkMatrix preViewMatrices[], const SkSamplingOptions&, 223 const SkPaint&, SkCanvas::SrcRectConstraint) override; 224 225 // Assumes the src and dst rects have already been optimized to fit the proxy. 226 // Only implemented by the gpu devices. 227 // This method is the lowest level draw used for tiled bitmap draws. It doesn't attempt to 228 // modify its parameters (e.g., adjust src & dst) but just draws the image however it can. It 229 // could, almost, be replaced with a drawEdgeAAImageSet call for the tiled bitmap draw use 230 // case but the extra tilemode requirement and the intermediate parameter processing (e.g., 231 // trying to alter the SrcRectConstraint) currently block that. 232 void drawEdgeAAImage(const SkImage*, 233 const SkRect& src, 234 const SkRect& dst, 235 const SkPoint dstClip[4], 236 SkCanvas::QuadAAFlags, 237 const SkMatrix& localToDevice, 238 const SkSamplingOptions&, 239 const SkPaint&, 240 SkCanvas::SrcRectConstraint, 241 const SkMatrix& srcToDst, 242 SkTileMode); 243 244 sk_sp<sktext::gpu::Slug> convertGlyphRunListToSlug(const sktext::GlyphRunList& glyphRunList, 245 const SkPaint& paint) override; 246 247 void drawSlug(SkCanvas*, const sktext::gpu::Slug* slug, const SkPaint& paint) override; 248 249 sk_sp<SkSpecialImage> makeSpecial(const SkBitmap&) override; 250 sk_sp<SkSpecialImage> makeSpecial(const SkImage*) override; 251 sk_sp<SkSpecialImage> snapSpecial(const SkIRect& subset, bool forceCopy = false) override; 252 sk_sp<SkSpecialImage> snapSpecialScaled(const SkIRect& subset, const SkISize& dstDims) override; 253 254 sk_sp<SkDevice> createDevice(const CreateInfo&, const SkPaint*) override; 255 256 sk_sp<SkSurface> makeSurface(const SkImageInfo&, const SkSurfaceProps&) override; 257 asGaneshDevice()258 Device* asGaneshDevice() override { return this; } 259 devClipBounds()260 SkIRect devClipBounds() const override { return fClip.getConservativeBounds(); } 261 pushClipStack()262 void pushClipStack() override { fClip.save(); } popClipStack()263 void popClipStack() override { fClip.restore(); } 264 clipRect(const SkRect & rect,SkClipOp op,bool aa)265 void clipRect(const SkRect& rect, SkClipOp op, bool aa) override { 266 SkASSERT(op == SkClipOp::kIntersect || op == SkClipOp::kDifference); 267 fClip.clipRect(this->localToDevice(), rect, GrAA(aa), op); 268 } clipRRect(const SkRRect & rrect,SkClipOp op,bool aa)269 void clipRRect(const SkRRect& rrect, SkClipOp op, bool aa) override { 270 SkASSERT(op == SkClipOp::kIntersect || op == SkClipOp::kDifference); 271 fClip.clipRRect(this->localToDevice(), rrect, GrAA(aa), op); 272 } 273 void clipPath(const SkPath& path, SkClipOp op, bool aa) override; 274 replaceClip(const SkIRect & rect)275 void replaceClip(const SkIRect& rect) override { 276 // Transform from "global/canvas" coordinates to relative to this device 277 SkRect deviceRect = SkMatrixPriv::MapRect(this->globalToDevice(), SkRect::Make(rect)); 278 fClip.replaceClip(deviceRect.round()); 279 } 280 void clipRegion(const SkRegion& globalRgn, SkClipOp op) override; 281 282 bool isClipAntiAliased() const override; 283 isClipEmpty()284 bool isClipEmpty() const override { 285 return fClip.clipState() == ClipStack::ClipState::kEmpty; 286 } 287 isClipRect()288 bool isClipRect() const override { 289 return fClip.clipState() == ClipStack::ClipState::kDeviceRect || 290 fClip.clipState() == ClipStack::ClipState::kWideOpen; 291 } 292 isClipWideOpen()293 bool isClipWideOpen() const override { 294 return fClip.clipState() == ClipStack::ClipState::kWideOpen; 295 } 296 297 void android_utils_clipAsRgn(SkRegion*) const override; 298 bool android_utils_clipWithStencil() override; 299 300 private: 301 enum class DeviceFlags { 302 kNone = 0, 303 kNeedClear = 1 << 0, //!< Surface requires an initial clear 304 kIsOpaque = 1 << 1, //!< Hint from client that rendering to this device will be 305 // opaque even if the config supports alpha. 306 }; 307 GR_DECL_BITFIELD_CLASS_OPS_FRIENDS(DeviceFlags); 308 309 static SkImageInfo MakeInfo(SurfaceContext*, DeviceFlags); 310 static bool CheckAlphaTypeAndGetFlags(SkAlphaType, InitContents, DeviceFlags*); 311 312 sk_sp<GrRecordingContext> fContext; 313 314 const sktext::gpu::SDFTControl fSDFTControl; 315 316 std::unique_ptr<SurfaceDrawContext> fSurfaceDrawContext; 317 318 ClipStack fClip; 319 320 static sk_sp<Device> Make(std::unique_ptr<SurfaceDrawContext>, 321 SkAlphaType, 322 InitContents); 323 324 Device(std::unique_ptr<SurfaceDrawContext>, DeviceFlags); 325 326 void onDrawGlyphRunList(SkCanvas*, const sktext::GlyphRunList&, const SkPaint& paint) override; 327 328 bool onReadPixels(const SkPixmap&, int, int) override; 329 bool onWritePixels(const SkPixmap&, int, int) override; 330 bool onAccessPixels(SkPixmap*) override; 331 332 sk_sp<skif::Backend> createImageFilteringBackend(const SkSurfaceProps& surfaceProps, 333 SkColorType colorType) const override; 334 onClipShader(sk_sp<SkShader> shader)335 void onClipShader(sk_sp<SkShader> shader) override { 336 fClip.clipShader(std::move(shader)); 337 } 338 clip()339 const GrClip* clip() const { return &fClip; } 340 341 // If not null, dstClip must be contained inside dst and will also respect the edge AA flags. 342 // If 'preViewMatrix' is not null, final CTM will be this->ctm() * preViewMatrix. 343 void drawImageQuadDirect(const SkImage*, 344 const SkRect& src, 345 const SkRect& dst, 346 const SkPoint dstClip[4], 347 SkCanvas::QuadAAFlags, 348 const SkMatrix* preViewMatrix, 349 const SkSamplingOptions&, 350 const SkPaint&, 351 SkCanvas::SrcRectConstraint); 352 353 // FIXME(michaelludwig) - Should be removed in favor of using drawImageQuad with edge flags to 354 // for every element in the SkLatticeIter. 355 void drawViewLattice(GrSurfaceProxyView, 356 const GrColorInfo& colorInfo, 357 std::unique_ptr<SkLatticeIter>, 358 const SkRect& dst, 359 SkFilterMode, 360 const SkPaint&); 361 362 friend class ::SkSurface_Ganesh; // for access to surfaceProps 363 friend class skgpu::TiledTextureUtils; // for access to clip() 364 }; 365 366 GR_MAKE_BITFIELD_CLASS_OPS(Device::DeviceFlags) 367 368 } // namespace skgpu::ganesh 369 370 #endif // skgpu_v1_Device_DEFINED 371