xref: /aosp_15_r20/external/skia/include/core/SkDrawable.h (revision c8dee2aa9b3f27cf6c858bd81872bdeb2c07ed17)
1 /*
2  * Copyright 2014 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 SkDrawable_DEFINED
9 #define SkDrawable_DEFINED
10 
11 #include "include/core/SkFlattenable.h"
12 #include "include/core/SkRefCnt.h"
13 #include "include/core/SkScalar.h"
14 #include "include/private/base/SkAPI.h"
15 
16 #include <cstddef>
17 #include <cstdint>
18 #include <memory>
19 
20 class GrBackendDrawableInfo;
21 class SkCanvas;
22 class SkMatrix;
23 class SkPicture;
24 enum class GrBackendApi : unsigned int;
25 struct SkDeserialProcs;
26 struct SkIRect;
27 struct SkImageInfo;
28 struct SkRect;
29 
30 /**
31  *  Base-class for objects that draw into SkCanvas.
32  *
33  *  The object has a generation ID, which is guaranteed to be unique across all drawables. To
34  *  allow for clients of the drawable that may want to cache the results, the drawable must
35  *  change its generation ID whenever its internal state changes such that it will draw differently.
36  */
37 class SK_API SkDrawable : public SkFlattenable {
38 public:
39     /**
40      *  Draws into the specified content. The drawing sequence will be balanced upon return
41      *  (i.e. the saveLevel() on the canvas will match what it was when draw() was called,
42      *  and the current matrix and clip settings will not be changed.
43      */
44     void draw(SkCanvas*, const SkMatrix* = nullptr);
45     void draw(SkCanvas*, SkScalar x, SkScalar y);
46 
47     /**
48      *  When using the GPU backend it is possible for a drawable to execute using the underlying 3D
49      *  API rather than the SkCanvas API. It does so by creating a GpuDrawHandler. The GPU backend
50      *  is deferred so the handler will be given access to the 3D API at the correct point in the
51      *  drawing stream as the GPU backend flushes. Since the drawable may mutate, each time it is
52      *  drawn to a GPU-backed canvas a new handler is snapped, representing the drawable's state at
53      *  the time of the snap.
54      *
55      *  When the GPU backend flushes to the 3D API it will call the draw method on the
56      *  GpuDrawHandler. At this time the drawable may add commands to the stream of GPU commands for
57      *  the unerlying 3D API. The draw function takes a GrBackendDrawableInfo which contains
58      *  information about the current state of 3D API which the caller must respect. See
59      *  GrBackendDrawableInfo for more specific details on what information is sent and the
60      *  requirements for different 3D APIs.
61      *
62      *  Additionaly there may be a slight delay from when the drawable adds its commands to when
63      *  those commands are actually submitted to the GPU. Thus the drawable or GpuDrawHandler is
64      *  required to keep any resources that are used by its added commands alive and valid until
65      *  those commands are submitted to the GPU. The GpuDrawHandler will be kept alive and then
66      *  deleted once the commands are submitted to the GPU. The dtor of the GpuDrawHandler is the
67      *  signal to the drawable that the commands have all been submitted. Different 3D APIs may have
68      *  additional requirements for certain resources which require waiting for the GPU to finish
69      *  all work on those resources before reusing or deleting them. In this case, the drawable can
70      *  use the dtor call of the GpuDrawHandler to add a fence to the GPU to track when the GPU work
71      *  has completed.
72      *
73      *  Currently this is only supported for the GPU Vulkan backend.
74      */
75 
76     class GpuDrawHandler {
77     public:
~GpuDrawHandler()78         virtual ~GpuDrawHandler() {}
79 
draw(const GrBackendDrawableInfo &)80         virtual void draw(const GrBackendDrawableInfo&) {}
81     };
82 
83     /**
84      * Snaps off a GpuDrawHandler to represent the state of the SkDrawable at the time the snap is
85      * called. This is used for executing GPU backend specific draws intermixed with normal Skia GPU
86      * draws. The GPU API, which will be used for the draw, as well as the full matrix, device clip
87      * bounds and imageInfo of the target buffer are passed in as inputs.
88      */
snapGpuDrawHandler(GrBackendApi backendApi,const SkMatrix & matrix,const SkIRect & clipBounds,const SkImageInfo & bufferInfo)89     std::unique_ptr<GpuDrawHandler> snapGpuDrawHandler(GrBackendApi backendApi,
90                                                        const SkMatrix& matrix,
91                                                        const SkIRect& clipBounds,
92                                                        const SkImageInfo& bufferInfo) {
93         return this->onSnapGpuDrawHandler(backendApi, matrix, clipBounds, bufferInfo);
94     }
95 
96     /**
97      * Returns an SkPicture with the contents of this SkDrawable.
98      */
99     sk_sp<SkPicture> makePictureSnapshot();
100 
101     /**
102      *  Return a unique value for this instance. If two calls to this return the same value,
103      *  it is presumed that calling the draw() method will render the same thing as well.
104      *
105      *  Subclasses that change their state should call notifyDrawingChanged() to ensure that
106      *  a new value will be returned the next time it is called.
107      */
108     uint32_t getGenerationID();
109 
110     /**
111      *  Return the (conservative) bounds of what the drawable will draw. If the drawable can
112      *  change what it draws (e.g. animation or in response to some external change), then this
113      *  must return a bounds that is always valid for all possible states.
114      */
115     SkRect getBounds();
116 
117     /**
118      *  Return approximately how many bytes would be freed if this drawable is destroyed.
119      *  The base implementation returns 0 to indicate that this is unknown.
120      */
121     size_t approximateBytesUsed();
122 
123     /**
124      *  Calling this invalidates the previous generation ID, and causes a new one to be computed
125      *  the next time getGenerationID() is called. Typically this is called by the object itself,
126      *  in response to its internal state changing.
127      */
128     void notifyDrawingChanged();
129 
GetFlattenableType()130     static SkFlattenable::Type GetFlattenableType() {
131         return kSkDrawable_Type;
132     }
133 
getFlattenableType()134     SkFlattenable::Type getFlattenableType() const override {
135         return kSkDrawable_Type;
136     }
137 
138     static sk_sp<SkDrawable> Deserialize(const void* data, size_t size,
139                                           const SkDeserialProcs* procs = nullptr) {
140         return sk_sp<SkDrawable>(static_cast<SkDrawable*>(
141                                   SkFlattenable::Deserialize(
142                                   kSkDrawable_Type, data, size, procs).release()));
143     }
144 
getFactory()145     Factory getFactory() const override { return nullptr; }
getTypeName()146     const char* getTypeName() const override { return nullptr; }
147 
148 protected:
149     SkDrawable();
150 
151     virtual SkRect onGetBounds() = 0;
152     virtual size_t onApproximateBytesUsed();
153     virtual void onDraw(SkCanvas*) = 0;
154 
onSnapGpuDrawHandler(GrBackendApi,const SkMatrix &,const SkIRect &,const SkImageInfo &)155     virtual std::unique_ptr<GpuDrawHandler> onSnapGpuDrawHandler(GrBackendApi, const SkMatrix&,
156                                                                  const SkIRect& /*clipBounds*/,
157                                                                  const SkImageInfo&) {
158         return nullptr;
159     }
160 
161     // TODO: Delete this once Android gets updated to take the clipBounds version above.
onSnapGpuDrawHandler(GrBackendApi,const SkMatrix &)162     virtual std::unique_ptr<GpuDrawHandler> onSnapGpuDrawHandler(GrBackendApi, const SkMatrix&) {
163         return nullptr;
164     }
165 
166     /**
167      *  Default implementation calls onDraw() with a canvas that records into a picture. Subclasses
168      *  may override if they have a more efficient way to return a picture for the current state
169      *  of their drawable. Note: this picture must draw the same as what would be drawn from
170      *  onDraw().
171      */
172     virtual sk_sp<SkPicture> onMakePictureSnapshot();
173 
174 private:
175     int32_t fGenerationID;
176 };
177 
178 #endif
179