Home | History | Annotate | Download | only in sk
      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