• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
onRestore()77     void onRestore() override {
78         this->SkClipStackDevice::onRestore();
79         fClipWeakref = SKC_WEAKREF_INVALID;
80     }
onClipRect(const SkRect & rect,SkClipOp op,bool aa)81     void onClipRect(const SkRect& rect, SkClipOp op, bool aa) override {
82         this->SkClipStackDevice::onClipRect(rect, op, aa);
83         fClipWeakref = SKC_WEAKREF_INVALID;
84     }
onClipRRect(const SkRRect & rrect,SkClipOp op,bool aa)85     void onClipRRect(const SkRRect& rrect, SkClipOp op, bool aa) override {
86         this->SkClipStackDevice::onClipRRect(rrect, op, aa);
87         fClipWeakref = SKC_WEAKREF_INVALID;
88     }
onClipPath(const SkPath & path,SkClipOp op,bool aa)89     void onClipPath(const SkPath& path, SkClipOp op, bool aa) override {
90         this->SkClipStackDevice::onClipPath(path, op, aa);
91         fClipWeakref = SKC_WEAKREF_INVALID;
92     }
onClipRegion(const SkRegion & deviceRgn,SkClipOp op)93     void onClipRegion(const SkRegion& deviceRgn, SkClipOp op) override {
94         this->SkClipStackDevice::onClipRegion(deviceRgn, op);
95         fClipWeakref = SKC_WEAKREF_INVALID;
96     }
onSetDeviceClipRestriction(SkIRect * clipRestriction)97     void onSetDeviceClipRestriction(SkIRect* clipRestriction) override {
98         this->SkClipStackDevice::onSetDeviceClipRestriction(clipRestriction);
99         fClipWeakref = SKC_WEAKREF_INVALID;
100     }
101 
onGetClipType()102     ClipType onGetClipType() const override {
103         // TODO Support non-rect clip
104         return kRect_ClipType;
105     }
106 
drawBitmap(const SkBitmap &,const SkMatrix &,const SkPaint &)107     void drawBitmap(const SkBitmap&, const SkMatrix&, const SkPaint&) override {}
drawSprite(const SkBitmap &,int,int,const SkPaint &)108     void drawSprite(const SkBitmap&, int, int, const SkPaint&) override {}
drawBitmapRect(const SkBitmap &,const SkRect *,const SkRect &,const SkPaint &,SkCanvas::SrcRectConstraint)109     void drawBitmapRect(const SkBitmap&, const SkRect*, const SkRect&, const SkPaint&,
110                         SkCanvas::SrcRectConstraint) override {}
111     void drawDevice(SkBaseDevice*, int, int, const SkPaint&) override;
drawVertices(const SkVertices *,SkBlendMode,const SkPaint &)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 
drawPaint(const SkPaint & paint)165     void drawPaint(const SkPaint& paint) override {
166         this->sanityCheck();
167         fRoot->drawPaint(paint);
168     }
169 
170     void
drawPoints(SkCanvas::PointMode pm,size_t s,const SkPoint pts[],const SkPaint & p)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 
drawRect(const SkRect & r,const SkPaint & p)176     void drawRect(const SkRect& r, const SkPaint& p) override {
177         this->sanityCheck();
178         fRoot->drawRect(r, p);
179     }
180 
drawOval(const SkRect & r,const SkPaint & p)181     void drawOval(const SkRect& r, const SkPaint& p) override {
182         this->sanityCheck();
183         fRoot->drawOval(r, p);
184     }
185 
drawRRect(const SkRRect & rr,const SkPaint & p)186     void drawRRect(const SkRRect& rr, const SkPaint& p) override {
187         this->sanityCheck();
188         fRoot->drawRRect(rr, p);
189     }
190 
drawPath(const SkPath & path,const SkPaint & p,const SkMatrix * m,bool b)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 
drawText(const void * t,size_t l,SkScalar x,SkScalar y,const SkPaint & p)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 
drawPosText(const void * t,size_t l,const SkScalar p[],int s,const SkPoint & o,const SkPaint & paint)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;
onClipIsAA()214     bool onClipIsAA() const override {
215         return fRoot->onClipIsAA();
216     }
onAsRgnClip(SkRegion * rgn)217     void onAsRgnClip(SkRegion* rgn) const override {
218         return fRoot->onAsRgnClip(rgn);
219     }
onGetClipType()220     ClipType onGetClipType() const override {
221         return fRoot->onGetClipType();
222     }
223 
224     void onCtmChanged() override;
225 
drawBitmap(const SkBitmap &,const SkMatrix &,const SkPaint &)226     void drawBitmap(const SkBitmap&, const SkMatrix&, const SkPaint&) override {}
drawSprite(const SkBitmap &,int,int,const SkPaint &)227     void drawSprite(const SkBitmap&, int, int, const SkPaint&) override {}
drawBitmapRect(const SkBitmap &,const SkRect *,const SkRect &,const SkPaint &,SkCanvas::SrcRectConstraint)228     void drawBitmapRect(const SkBitmap&, const SkRect*, const SkRect&, const SkPaint&,
229                         SkCanvas::SrcRectConstraint) override {}
230     void drawDevice(SkBaseDevice*, int, int, const SkPaint&) override;
drawVertices(const SkVertices *,SkBlendMode,const SkPaint &)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 
sanityCheck()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