1 /* 2 * Copyright 2016 The Android Open Source Project 3 * 4 * Use of this source code is governed by a BSD-style license that can 5 * be found in the LICENSE file. 6 */ 7 8 #ifndef SkDevice_Compute_DEFINED 9 #define SkDevice_Compute_DEFINED 10 11 // 12 // for now make sure it's defined 13 // 14 15 #if !defined(SK_SUPPORT_GPU_COMPUTE) 16 #define SK_SUPPORT_GPU_COMPUTE 1 17 #endif 18 19 // 20 // 21 // 22 23 #if SK_SUPPORT_GPU_COMPUTE 24 25 // TODO Check whether we can use SkDevice_ComputeLayerGroup at compile time 26 // by checking whether there is only one top device. 27 #define SK_USE_COMPUTE_LAYER_GROUP 28 29 // 30 // C 31 // 32 33 #ifdef __cplusplus 34 extern "C" { 35 #endif 36 37 #include <context.h> 38 39 #ifdef __cplusplus 40 } 41 #endif 42 43 #include "../compute/skc/skc.h" 44 45 // 46 // C++ 47 // 48 49 #include "SkDevice.h" 50 #include "SkClipStackDevice.h" 51 #include "SkContext_Compute.h" 52 #include "SkTArray.h" 53 54 // 55 // 56 // 57 58 #ifdef SK_USE_COMPUTE_LAYER_GROUP 59 class SkDevice_ComputeLayerGroup; 60 #endif 61 62 class SkDevice_Compute : public SkClipStackDevice { 63 public: 64 SkDevice_Compute(sk_sp<SkContext_Compute>, int w, int h); 65 ~SkDevice_Compute() override; 66 67 void drawPaint(const SkPaint& paint) override; 68 void drawPoints(SkCanvas::PointMode, size_t, const SkPoint[], const SkPaint&) override; 69 void drawRect(const SkRect&, const SkPaint&) override; 70 void drawOval(const SkRect&, const SkPaint&) override; 71 void drawRRect(const SkRRect&, const SkPaint&) override; 72 void drawPath(const SkPath&, const SkPaint&, const SkMatrix*, bool) override; 73 void drawText(const void*, size_t, SkScalar, SkScalar, const SkPaint&) override; 74 void drawPosText(const void*, size_t, const SkScalar[], int, const SkPoint&, 75 const SkPaint&) override; 76 77 void onRestore() override { 78 this->SkClipStackDevice::onRestore(); 79 fClipWeakref = SKC_WEAKREF_INVALID; 80 } 81 void onClipRect(const SkRect& rect, SkClipOp op, bool aa) override { 82 this->SkClipStackDevice::onClipRect(rect, op, aa); 83 fClipWeakref = SKC_WEAKREF_INVALID; 84 } 85 void onClipRRect(const SkRRect& rrect, SkClipOp op, bool aa) override { 86 this->SkClipStackDevice::onClipRRect(rrect, op, aa); 87 fClipWeakref = SKC_WEAKREF_INVALID; 88 } 89 void onClipPath(const SkPath& path, SkClipOp op, bool aa) override { 90 this->SkClipStackDevice::onClipPath(path, op, aa); 91 fClipWeakref = SKC_WEAKREF_INVALID; 92 } 93 void onClipRegion(const SkRegion& deviceRgn, SkClipOp op) override { 94 this->SkClipStackDevice::onClipRegion(deviceRgn, op); 95 fClipWeakref = SKC_WEAKREF_INVALID; 96 } 97 void onSetDeviceClipRestriction(SkIRect* clipRestriction) override { 98 this->SkClipStackDevice::onSetDeviceClipRestriction(clipRestriction); 99 fClipWeakref = SKC_WEAKREF_INVALID; 100 } 101 102 ClipType onGetClipType() const override { 103 // TODO Support non-rect clip 104 return kRect_ClipType; 105 } 106 107 void drawBitmap(const SkBitmap&, const SkMatrix&, const SkPaint&) override {} 108 void drawSprite(const SkBitmap&, int, int, const SkPaint&) override {} 109 void drawBitmapRect(const SkBitmap&, const SkRect*, const SkRect&, const SkPaint&, 110 SkCanvas::SrcRectConstraint) override {} 111 void drawDevice(SkBaseDevice*, int, int, const SkPaint&) override; 112 void drawVertices(const SkVertices*, SkBlendMode, const SkPaint&) override {} 113 void flush() override; 114 115 SkBaseDevice* onCreateDevice(const CreateInfo&, const SkPaint*) override; 116 117 void onCtmChanged() override; 118 119 friend class SkDevice_ComputeLayerGroup; 120 121 private: 122 void styling_group_init(); 123 124 void path_add(const SkPaint&, const SkPath&, const SkMatrix* prePathMatrix = nullptr); 125 void circles_add(const SkPaint&, const SkPoint points[], int32_t count, SkScalar radius); 126 void squares_add(const SkPaint&, const SkPoint points[], int32_t count, SkScalar radius); 127 void line_stroked_butt(SkPoint xy0, SkPoint xy1, SkScalar radius); 128 void lines_stroked_add(const SkPaint&, const SkPoint points[], int32_t count, SkScalar radius); 129 void path_rasterize_and_place(const SkPaint&, const skc_path_t path, 130 const SkMatrix* prePathMatrix = nullptr); 131 132 sk_sp<SkContext_Compute> fCompute; 133 134 skc_composition_t fComposition; 135 skc_styling_t fStyling; 136 137 skc_path_builder_t fPB; 138 skc_raster_builder_t fRB; 139 140 skc_group_id fGroupID; 141 skc_group_id fGroupLayerID; 142 143 // When SK_USE_COMPUTE_LAYER_GROUP is set, fTopCTM is the global CTM for the top device. 144 // When SK_USE_COMPUTE_LAYER_GROUP is not set, fTopCTM is equal to this->ctm(). 145 SkMatrix fTopCTM; 146 skc_transform_weakref_t fTransformWeakref; 147 148 skc_raster_clip_weakref_t fClipWeakref; 149 150 #ifdef SK_USE_COMPUTE_LAYER_GROUP 151 SkTArray<skc_group_id> fParents; 152 153 SkDevice_ComputeLayerGroup* createLayerGroup(const CreateInfo&, const SkPaint*); 154 #endif 155 }; 156 157 #ifdef SK_USE_COMPUTE_LAYER_GROUP 158 159 // A group of skc layers that correspond to a saveLayer in the top level (root) SkDevice_Compute. 160 class SkDevice_ComputeLayerGroup : public SkBaseDevice { 161 public: 162 SkDevice_ComputeLayerGroup(SkDevice_Compute* root, const CreateInfo&, const SkPaint*); 163 ~SkDevice_ComputeLayerGroup() override; 164 165 void drawPaint(const SkPaint& paint) override { 166 this->sanityCheck(); 167 fRoot->drawPaint(paint); 168 } 169 170 void 171 drawPoints(SkCanvas::PointMode pm, size_t s, const SkPoint pts[], const SkPaint& p) override { 172 this->sanityCheck(); 173 fRoot->drawPoints(pm, s, pts, p); 174 } 175 176 void drawRect(const SkRect& r, const SkPaint& p) override { 177 this->sanityCheck(); 178 fRoot->drawRect(r, p); 179 } 180 181 void drawOval(const SkRect& r, const SkPaint& p) override { 182 this->sanityCheck(); 183 fRoot->drawOval(r, p); 184 } 185 186 void drawRRect(const SkRRect& rr, const SkPaint& p) override { 187 this->sanityCheck(); 188 fRoot->drawRRect(rr, p); 189 } 190 191 void drawPath(const SkPath& path, const SkPaint& p, const SkMatrix* m, bool b) override { 192 this->sanityCheck(); 193 fRoot->drawPath(path, p, m, b); 194 } 195 196 void drawText(const void* t, size_t l, SkScalar x, SkScalar y, const SkPaint& p) override { 197 this->sanityCheck(); 198 fRoot->drawText(t, l, x, y, p); 199 } 200 201 void drawPosText(const void* t, size_t l, const SkScalar p[], int s, const SkPoint& o, 202 const SkPaint& paint) override { 203 this->sanityCheck(); 204 fRoot->drawPosText(t, l, p, s, o, paint); 205 } 206 207 void onSave() override; 208 void onRestore() override; 209 void onClipRect(const SkRect& rect, SkClipOp, bool aa) override; 210 void onClipRRect(const SkRRect& rrect, SkClipOp, bool aa) override; 211 void onClipPath(const SkPath& path, SkClipOp, bool aa) override; 212 void onClipRegion(const SkRegion& deviceRgn, SkClipOp) override; 213 void onSetDeviceClipRestriction(SkIRect* mutableClipRestriction) override; 214 bool onClipIsAA() const override { 215 return fRoot->onClipIsAA(); 216 } 217 void onAsRgnClip(SkRegion* rgn) const override { 218 return fRoot->onAsRgnClip(rgn); 219 } 220 ClipType onGetClipType() const override { 221 return fRoot->onGetClipType(); 222 } 223 224 void onCtmChanged() override; 225 226 void drawBitmap(const SkBitmap&, const SkMatrix&, const SkPaint&) override {} 227 void drawSprite(const SkBitmap&, int, int, const SkPaint&) override {} 228 void drawBitmapRect(const SkBitmap&, const SkRect*, const SkRect&, const SkPaint&, 229 SkCanvas::SrcRectConstraint) override {} 230 void drawDevice(SkBaseDevice*, int, int, const SkPaint&) override; 231 void drawVertices(const SkVertices*, SkBlendMode, const SkPaint&) override {} 232 void flush() override; 233 234 SkBaseDevice* onCreateDevice(const CreateInfo&, const SkPaint*) override; 235 236 friend class SkDevice_Compute; 237 238 private: 239 SkDevice_Compute* fRoot; 240 241 // Save a copy of the current group id for sanity check. 242 // If the sanity check fails, we're probably in the Android world where 243 // multiple top-level devices can co-exist. In that case, we can no longer use the group syntax 244 // and we have to create a new root-level SkDevice_Compute with an offscreen surface. 245 // According to reed@, we should be able to tell whether this sanity check will fail 246 // at the compile time (e.g., Chrome and Flutter never do this; Android sometimes does this). 247 skc_group_id fGroupID; 248 249 void sanityCheck() { 250 #ifdef SK_DEBUG 251 // We should only change the top level device's CTM. 252 // Otherwise we can't use SkDevice_ComputeLayerGroup. 253 SkASSERT(fGroupID == fRoot->fGroupID); 254 255 // The root SkDevice_Compute must have an origin (0, 0) as saveLayer won't 256 // ever create another SkDevice_Compute 257 SkASSERT(fRoot->getOrigin() == SkIPoint::Make(0, 0)); 258 #endif 259 } 260 }; 261 262 #endif // SK_USE_COMPUTE_LAYER_GROUP 263 264 #endif // SK_SUPPORT_GPU_COMPUTE 265 #endif // SkDevice_Compute_DEFINED 266