• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright 2021 Google LLC
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_graphite_Recorder_DEFINED
9 #define skgpu_graphite_Recorder_DEFINED
10 
11 #include "include/core/SkRefCnt.h"
12 #include "include/core/SkSize.h"
13 #include "include/gpu/graphite/GraphiteTypes.h"
14 #include "include/gpu/graphite/Recording.h"
15 #include "include/private/base/SingleOwner.h"
16 
17 #include <vector>
18 
19 class SkCanvas;
20 struct SkImageInfo;
21 class SkPixmap;
22 
23 namespace skgpu {
24 class TokenTracker;
25 }
26 
27 namespace sktext::gpu {
28 class StrikeCache;
29 class TextBlobRedrawCoordinator;
30 }
31 
32 namespace skgpu::graphite {
33 
34 class AtlasManager;
35 class BackendTexture;
36 class Caps;
37 class Context;
38 class Device;
39 class DrawBufferManager;
40 class GlobalCache;
41 class ImageProvider;
42 class RecorderPriv;
43 class ResourceProvider;
44 class RuntimeEffectDictionary;
45 class SharedContext;
46 class Task;
47 class TaskGraph;
48 class TextureDataBlock;
49 class TextureInfo;
50 class UniformDataBlock;
51 class UploadBufferManager;
52 
53 template<typename T> class PipelineDataCache;
54 using UniformDataCache = PipelineDataCache<UniformDataBlock>;
55 using TextureDataCache = PipelineDataCache<TextureDataBlock>;
56 
57 struct SK_API RecorderOptions final {
58     RecorderOptions();
59     RecorderOptions(const RecorderOptions&);
60     ~RecorderOptions();
61 
62     sk_sp<ImageProvider> fImageProvider;
63 };
64 
65 class SK_API Recorder final {
66 public:
67     Recorder(const Recorder&) = delete;
68     Recorder(Recorder&&) = delete;
69     Recorder& operator=(const Recorder&) = delete;
70     Recorder& operator=(Recorder&&) = delete;
71 
72     ~Recorder();
73 
74     std::unique_ptr<Recording> snap();
75 
clientImageProvider()76     ImageProvider* clientImageProvider() { return fClientImageProvider.get(); }
clientImageProvider()77     const ImageProvider* clientImageProvider() const { return fClientImageProvider.get(); }
78 
79     /**
80      * Creates a new backend gpu texture matching the dimensions and TextureInfo. If an invalid
81      * TextureInfo or a TextureInfo Skia can't support is passed in, this will return an invalid
82      * BackendTexture. Thus the client should check isValid on the returned BackendTexture to know
83      * if it succeeded or not.
84      *
85      * If this does return a valid BackendTexture, the caller is required to use
86      * Recorder::deleteBackendTexture or Context::deleteBackendTexture to delete the texture. It is
87      * safe to use the Context that created this Recorder or any other Recorder created from the
88      * same Context to call deleteBackendTexture.
89      */
90     BackendTexture createBackendTexture(SkISize dimensions, const TextureInfo&);
91 
92     /**
93      * If possible, updates a backend texture with the provided pixmap data. The client
94      * should check the return value to see if the update was successful. The client is required
95      * to insert a Recording into the Context and call `submit` to send the upload work to the gpu.
96      * The backend texture must be compatible with the provided pixmap(s). Compatible, in this case,
97      * means that the backend format is compatible with the base pixmap's colortype. The src data
98      * can be deleted when this call returns.
99      * If the backend texture is mip mapped, the data for all the mipmap levels must be provided.
100      * In the mipmapped case all the colortypes of the provided pixmaps must be the same.
101      * Additionally, all the miplevels must be sized correctly (please see
102      * SkMipmap::ComputeLevelSize and ComputeLevelCount).
103      * Note: the pixmap's alphatypes and colorspaces are ignored.
104      * For the Vulkan backend after a successful update the layout of the created VkImage will be:
105      *      VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL
106      */
107     bool updateBackendTexture(const BackendTexture&,
108                               const SkPixmap srcData[],
109                               int numLevels);
110 
111     /**
112      * Called to delete the passed in BackendTexture. This should only be called if the
113      * BackendTexture was created by calling Recorder::createBackendTexture on a Recorder that is
114      * associated with the same Context. If the BackendTexture is not valid or does not match the
115      * BackendApi of the Recorder then nothing happens.
116      *
117      * Otherwise this will delete/release the backend object that is wrapped in the BackendTexture.
118      * The BackendTexture will be reset to an invalid state and should not be used again.
119      */
120     void deleteBackendTexture(BackendTexture&);
121 
122     // Returns a canvas that will record to a proxy surface, which must be instantiated on replay.
123     // This can only be called once per Recording; subsequent calls will return null until a
124     // Recording is snapped. Additionally, the returned SkCanvas is only valid until the next
125     // Recording snap, at which point it is deleted.
126     SkCanvas* makeDeferredCanvas(const SkImageInfo&, const TextureInfo&);
127 
128     // Provides access to functions that aren't part of the public API.
129     RecorderPriv priv();
130     const RecorderPriv priv() const;  // NOLINT(readability-const-return-type)
131 
132 #if GR_TEST_UTILS
133     bool deviceIsRegistered(Device*);
134 #endif
135 
136 private:
137     friend class Context; // For ctor
138     friend class Device; // For registering and deregistering Devices;
139     friend class RecorderPriv; // for ctor and hidden methods
140 
141     Recorder(sk_sp<SharedContext>, const RecorderOptions&);
142 
singleOwner()143     SingleOwner* singleOwner() const { return &fSingleOwner; }
144 
145     BackendApi backend() const;
146 
147     // We keep track of all Devices that are connected to a Recorder. This allows the client to
148     // safely delete an SkSurface or a Recorder in any order. If the client deletes the Recorder
149     // we need to notify all Devices that the Recorder is no longer valid. If we delete the
150     // SkSurface/Device first we will flush all the Device's into the Recorder before deregistering
151     // it from the Recorder.
152     //
153     // We do not need to take a ref on the Device since the Device will flush and deregister itself
154     // in its dtor. There is no other need for the Recorder to know about the Device after this
155     // point.
156     //
157     // Note: We could probably get by with only registering Devices directly connected to
158     // SkSurfaces. All other one off Devices will be created in a controlled scope where the
159     // Recorder should still be valid by the time they need to flush their work when the Device is
160     // deleted. We would have to make sure we safely handle cases where a client calls saveLayer
161     // then either deletes the SkSurface or Recorder before calling restore. For simplicity we just
162     // register every device for now, but if we see extra overhead in pushing back the extra
163     // pointers, we can look into only registering SkSurface Devices.
164     void registerDevice(Device*);
165     void deregisterDevice(const Device*);
166 
167     sk_sp<SharedContext> fSharedContext;
168     std::unique_ptr<ResourceProvider> fResourceProvider;
169     std::unique_ptr<RuntimeEffectDictionary> fRuntimeEffectDict;
170 
171     std::unique_ptr<TaskGraph> fGraph;
172     std::unique_ptr<UniformDataCache> fUniformDataCache;
173     std::unique_ptr<TextureDataCache> fTextureDataCache;
174     std::unique_ptr<DrawBufferManager> fDrawBufferManager;
175     std::unique_ptr<UploadBufferManager> fUploadBufferManager;
176     std::vector<Device*> fTrackedDevices;
177 
178     uint32_t fRecorderID;  // Needed for MessageBox handling for text
179     std::unique_ptr<AtlasManager> fAtlasManager;
180     std::unique_ptr<TokenTracker> fTokenTracker;
181     std::unique_ptr<sktext::gpu::StrikeCache> fStrikeCache;
182     std::unique_ptr<sktext::gpu::TextBlobRedrawCoordinator> fTextBlobCache;
183     sk_sp<ImageProvider> fClientImageProvider;
184 
185     // In debug builds we guard against improper thread handling
186     // This guard is passed to the ResourceCache.
187     // TODO: Should we also pass this to Device, DrawContext, and similar classes?
188     mutable SingleOwner fSingleOwner;
189 
190     sk_sp<Device> fTargetProxyDevice;
191     std::unique_ptr<SkCanvas> fTargetProxyCanvas;
192     std::unique_ptr<Recording::LazyProxyData> fTargetProxyData;
193 
194 #if GRAPHITE_TEST_UTILS
195     // For testing use only -- the Context used to create this Recorder
196     Context* fContext = nullptr;
197 #endif
198 };
199 
200 } // namespace skgpu::graphite
201 
202 #endif // skgpu_graphite_Recorder_DEFINED
203