1 //
2 // Copyright 2016 Pixar
3 //
4 // Licensed under the Apache License, Version 2.0 (the "Apache License")
5 // with the following modification; you may not use this file except in
6 // compliance with the Apache License and the following modification to it:
7 // Section 6. Trademarks. is deleted and replaced with:
8 //
9 // 6. Trademarks. This License does not grant permission to use the trade
10 //    names, trademarks, service marks, or product names of the Licensor
11 //    and its affiliates, except as required to comply with Section 4(c) of
12 //    the License and to reproduce the content of the NOTICE file.
13 //
14 // You may obtain a copy of the Apache License at
15 //
16 //     http://www.apache.org/licenses/LICENSE-2.0
17 //
18 // Unless required by applicable law or agreed to in writing, software
19 // distributed under the Apache License with the above modification is
20 // distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
21 // KIND, either express or implied. See the Apache License for the specific
22 // language governing permissions and limitations under the Apache License.
23 //
24 #ifndef PXR_USD_PCP_LAYER_STACK_H
25 #define PXR_USD_PCP_LAYER_STACK_H
26 
27 /// \file pcp/layerStack.h
28 
29 #include "pxr/pxr.h"
30 #include "pxr/usd/pcp/api.h"
31 #include "pxr/usd/pcp/errors.h"
32 #include "pxr/usd/pcp/layerStackIdentifier.h"
33 #include "pxr/usd/pcp/mapExpression.h"
34 #include "pxr/usd/sdf/layerTree.h"
35 #include "pxr/base/tf/declarePtrs.h"
36 
37 #include <tbb/spin_mutex.h>
38 #include <iosfwd>
39 #include <memory>
40 #include <string>
41 #include <vector>
42 
43 PXR_NAMESPACE_OPEN_SCOPE
44 
45 TF_DECLARE_REF_PTRS(SdfLayer);
46 TF_DECLARE_WEAK_AND_REF_PTRS(PcpLayerStack);
47 TF_DECLARE_WEAK_AND_REF_PTRS(Pcp_LayerStackRegistry);
48 
49 class ArResolverContext;
50 class Pcp_LayerStackRegistry;
51 class Pcp_MutedLayers;
52 class PcpLayerStackChanges;
53 class PcpLifeboat;
54 
55 /// \class PcpLayerStack
56 ///
57 /// Represents a stack of layers that contribute opinions to composition.
58 ///
59 /// Each PcpLayerStack is identified by a PcpLayerStackIdentifier. This
60 /// identifier contains all of the parameters needed to construct a layer stack,
61 /// such as the root layer, session layer, and path resolver context.
62 ///
63 /// PcpLayerStacks are constructed and managed by a Pcp_LayerStackRegistry.
64 ///
65 class PcpLayerStack : public TfRefBase, public TfWeakBase {
66     PcpLayerStack(const PcpLayerStack&) = delete;
67     PcpLayerStack& operator=(const PcpLayerStack&) = delete;
68 
69 public:
70     // See Pcp_LayerStackRegistry for creating layer stacks.
71     PCP_API
72     virtual ~PcpLayerStack();
73 
74     /// Returns the identifier for this layer stack.
75     PCP_API
76     const PcpLayerStackIdentifier& GetIdentifier() const;
77 
78     /// Returns the layers in this layer stack in strong-to-weak order.
79     /// Note that this is only the *local* layer stack -- it does not
80     /// include any layers brought in by references inside prims.
81     PCP_API
82     const SdfLayerRefPtrVector& GetLayers() const;
83 
84     /// Returns only the session layers in the layer stack in strong-to-weak
85     /// order.
86     PCP_API
87     SdfLayerHandleVector GetSessionLayers() const;
88 
89     /// Returns the layer tree representing the structure of this layer
90     /// stack.
91     PCP_API
92     const SdfLayerTreeHandle& GetLayerTree() const;
93 
94     /// Returns the layer offset for the given layer, or NULL if the layer
95     /// can't be found or is the identity.
96     PCP_API
97     const SdfLayerOffset* GetLayerOffsetForLayer(const SdfLayerHandle&) const;
98 
99     /// Return the layer offset for the given layer, or NULL if the layer
100     /// can't be found or is the identity.
101     PCP_API
102     const SdfLayerOffset* GetLayerOffsetForLayer(const SdfLayerRefPtr&) const;
103 
104     /// Returns the layer offset for the layer at the given index in this
105     /// layer stack. Returns NULL if the offset is the identity.
106     PCP_API
107     const SdfLayerOffset* GetLayerOffsetForLayer(size_t layerIdx) const;
108 
109     /// Returns the set of layers that were muted in this layer
110     /// stack.
111     PCP_API
112     const std::set<std::string>& GetMutedLayers() const;
113 
114     /// Return the list of errors local to this layer stack.
GetLocalErrors()115     PcpErrorVector GetLocalErrors() const {
116         return _localErrors ? *_localErrors.get() : PcpErrorVector();
117     }
118 
119     /// Returns true if this layer stack contains the given layer, false
120     /// otherwise.
121     PCP_API
122     bool HasLayer(const SdfLayerHandle& layer) const;
123     PCP_API
124     bool HasLayer(const SdfLayerRefPtr& layer) const;
125 
126     /// Return the time codes per second value of the layer stack. This is
127     /// usually the same as the computed time codes per second of the root layer
128     /// but may be computed from the session layer when its present.
GetTimeCodesPerSecond()129     double GetTimeCodesPerSecond() const { return _timeCodesPerSecond; }
130 
131     /// Returns relocation source-to-target mapping for this layer stack.
132     ///
133     /// This map combines the individual relocation entries found across
134     /// all layers in this layer stack; multiple entries that affect a single
135     /// prim will be combined into a single entry. For instance, if this
136     /// layer stack contains relocations { /A: /B } and { /A/C: /A/D }, this
137     /// map will contain { /A: /B } and { /B/C: /B/D }. This allows consumers
138     /// to go from unrelocated namespace to relocated namespace in a single
139     /// step.
140     PCP_API
141     const SdfRelocatesMap& GetRelocatesSourceToTarget() const;
142 
143     /// Returns relocation target-to-source mapping for this layer stack.
144     ///
145     /// See GetRelocatesSourceToTarget for more details.
146     PCP_API
147     const SdfRelocatesMap& GetRelocatesTargetToSource() const;
148 
149     /// Returns incremental relocation source-to-target mapping for this layer
150     /// stack.
151     ///
152     /// This map contains the individual relocation entries found across
153     /// all layers in this layer stack; it does not combine ancestral
154     /// entries with descendant entries. For instance, if this
155     /// layer stack contains relocations { /A: /B } and { /A/C: /A/D }, this
156     /// map will contain { /A: /B } and { /A/C: /A/D }.
157     PCP_API
158     const SdfRelocatesMap& GetIncrementalRelocatesSourceToTarget() const;
159 
160     /// Returns incremental relocation target-to-source mapping for this layer
161     /// stack.
162     ///
163     /// See GetIncrementalRelocatesTargetToSource for more details.
164     PCP_API
165     const SdfRelocatesMap& GetIncrementalRelocatesTargetToSource() const;
166 
167     /// Returns a list of paths to all prims across all layers in this
168     /// layer stack that contained relocates.
169     PCP_API
170     const SdfPathVector& GetPathsToPrimsWithRelocates() const;
171 
172     /// Apply the changes in \p changes.  This blows caches.  It's up to
173     /// the client to pull on those caches again as needed.
174     ///
175     /// Objects that are no longer needed and would be destroyed are
176     /// retained in \p lifeboat and won't be destroyed until \p lifeboat is
177     /// itself destroyed.  This gives the client control over the timing
178     /// of the destruction of those objects.  Clients may choose to pull
179     /// on the caches before destroying \p lifeboat.  That may cause the
180     /// caches to again retain the objects, meaning they won't be destroyed
181     /// when \p lifeboat is destroyed.
182     ///
183     /// For example, if blowing a cache means an SdfLayer is no longer
184     /// needed then \p lifeboat will hold an SdfLayerRefPtr to that layer.
185     /// The client can then pull on that cache, which could cause the
186     /// cache to hold an SdfLayerRefPtr to the layer again.  If so then
187     /// destroying \p changes will not destroy the layer.  In any case,
188     /// we don't destroy the layer and then read it again.  However, if
189     /// the client destroys \p lifeboat before pulling on the cache then
190     /// we would destroy the layer then read it again.
191     PCP_API
192     void Apply(const PcpLayerStackChanges& changes, PcpLifeboat* lifeboat);
193 
194     /// Return a PcpMapExpression representing the relocations that affect
195     /// namespace at and below the given path.  The value of this
196     /// expression will continue to track the effective relocations if
197     /// they are changed later.
198     PCP_API
199     PcpMapExpression GetExpressionForRelocatesAtPath(const SdfPath &path);
200 
201 private:
202     // Only a registry can create a layer stack.
203     friend class Pcp_LayerStackRegistry;
204     // PcpCache needs access to check the _registry.
205     friend class PcpCache;
206     // Needs access to _sublayerSourceInfo
207     friend bool Pcp_NeedToRecomputeDueToAssetPathChange(const PcpLayerStackPtr&);
208 
209     // It's a coding error to construct a layer stack with a NULL root layer.
210     PcpLayerStack(const PcpLayerStackIdentifier &identifier,
211                   const std::string &fileFormatTarget,
212                   const Pcp_MutedLayers &mutedLayers,
213                   bool isUsd);
214 
215     void _BlowLayers();
216     void _BlowRelocations();
217     void _Compute(const std::string &fileFormatTarget,
218                   const Pcp_MutedLayers &mutedLayers);
219 
220     SdfLayerTreeHandle _BuildLayerStack(
221         const SdfLayerHandle & layer,
222         const SdfLayerOffset & offset,
223         double layerTcps,
224         const ArResolverContext & pathResolverContext,
225         const SdfLayer::FileFormatArguments & layerArgs,
226         const std::string & sessionOwner,
227         const Pcp_MutedLayers & mutedLayers,
228         SdfLayerHandleSet *seenLayers,
229         PcpErrorVector *errors);
230 
231 private:
232     /// The identifier that uniquely identifies this layer stack.
233     const PcpLayerStackIdentifier _identifier;
234     /// The registry (1:1 with a PcpCache) this layer stack belongs to.  This
235     /// may not be set, particularly when a registry is creating a layer stack
236     /// but before it's been installed in the registry.
237     Pcp_LayerStackRegistryPtr _registry;
238 
239     /// Data representing the computed layer stack contents.
240     ///
241     /// This is built by examining the session and root layers for
242     /// sublayers, resolving their asset paths with the path resolver context,
243     /// and recursively building up the layer stack.
244     ///
245     /// Note that this is only the *local* layer stack -- it does not
246     /// include any layers brought in by references inside prims.
247 
248     /// Retained references to the layers in the stack,
249     /// in strong-to-weak order.
250     SdfLayerRefPtrVector _layers;
251 
252     /// The corresponding map functions for each entry in 'layers'.
253     /// Each map function contains a time offset that should be applied
254     /// to its corresponding layer.
255     std::vector<PcpMapFunction> _mapFunctions;
256 
257     /// Stores the computed time codes per second value of the layer stack which
258     /// has some special logic when a session layer is present.
259     double _timeCodesPerSecond;
260 
261     /// The tree structure of the layer stack.
262     /// Stored separately because this is needed only occasionally.
263     SdfLayerTreeHandle _layerTree;
264 
265     /// Tracks information used to compute sublayer asset paths.
266     struct _SublayerSourceInfo {
_SublayerSourceInfo_SublayerSourceInfo267         _SublayerSourceInfo(
268             const SdfLayerHandle& layer_,
269             const std::string& authoredSublayerPath_,
270             const std::string& computedSublayerPath_)
271         : layer(layer_)
272         , authoredSublayerPath(authoredSublayerPath_)
273         , computedSublayerPath(computedSublayerPath_) { }
274 
275         SdfLayerHandle layer;
276         std::string authoredSublayerPath;
277         std::string computedSublayerPath;
278     };
279 
280     /// List of source info for sublayer asset path computations.
281     std::vector<_SublayerSourceInfo> _sublayerSourceInfo;
282 
283     /// Set of asset paths that were muted in this layer stack.
284     std::set<std::string> _mutedAssetPaths;
285 
286     /// The errors, if any, discovered while computing this layer stack.
287     /// NULL if no errors were found (the expected common case).
288     std::unique_ptr<PcpErrorVector> _localErrors;
289 
290     /// Pre-computed table of local relocates.
291     SdfRelocatesMap _relocatesSourceToTarget;
292     SdfRelocatesMap _relocatesTargetToSource;
293     SdfRelocatesMap _incrementalRelocatesSourceToTarget;
294     SdfRelocatesMap _incrementalRelocatesTargetToSource;
295 
296     /// A map of PcpMapExpressions::Variable instances used to represent
297     /// the current value of relocations given out by
298     /// GetExpressionForRelocatesAtPath().  This map is used to update
299     /// those values when relocations change.
300     typedef std::map<SdfPath, PcpMapExpression::VariableUniquePtr,
301             SdfPath::FastLessThan> _RelocatesVarMap;
302     _RelocatesVarMap _relocatesVariables;
303     tbb::spin_mutex _relocatesVariablesMutex;
304 
305     /// List of all prim spec paths where relocations were found.
306     SdfPathVector _relocatesPrimPaths;
307 
308     bool _isUsd;
309 };
310 
311 PCP_API
312 std::ostream& operator<<(std::ostream&, const PcpLayerStackPtr&);
313 PCP_API
314 std::ostream& operator<<(std::ostream&, const PcpLayerStackRefPtr&);
315 
316 /// Compose the relocation arcs in the given stack of layers,
317 /// putting the results into the given sourceToTarget and targetToSource
318 /// maps.
319 void
320 Pcp_ComputeRelocationsForLayerStack(
321     const SdfLayerRefPtrVector & layers,
322     SdfRelocatesMap *relocatesSourceToTarget,
323     SdfRelocatesMap *relocatesTargetToSource,
324     SdfRelocatesMap *incrementalRelocatesSourceToTarget,
325     SdfRelocatesMap *incrementalRelocatesTargetToSource,
326     SdfPathVector *relocatesPrimPaths);
327 
328 // Returns true if \p layerStack should be recomputed due to changes to
329 // any computed asset paths that were used to find or open layers
330 // when originally composing \p layerStack. This may be due to scene
331 // description changes or external changes to asset resolution that
332 // may affect the computation of those asset paths.
333 bool
334 Pcp_NeedToRecomputeDueToAssetPathChange(const PcpLayerStackPtr& layerStack);
335 
336 // Returns true if the \p layerStack should be recomputed because
337 // \p changedLayer has had changes that would cause the layer stack to have
338 // a different computed overall time codes per second value.
339 bool
340 Pcp_NeedToRecomputeLayerStackTimeCodesPerSecond(
341     const PcpLayerStackPtr& layerStack, const SdfLayerHandle &changedLayer);
342 
343 /// Returns true when the environment variable has been set to disable the
344 /// behavior where differing time codes per second metadata in layers sublayered
345 /// or referenced by another layer are used to apply a layer offset scale to the
346 /// map function.
347 PCP_API
348 bool
349 PcpIsTimeScalingForLayerTimeCodesPerSecondDisabled();
350 
351 PXR_NAMESPACE_CLOSE_SCOPE
352 
353 #endif // PXR_USD_PCP_LAYER_STACK_H
354