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