@shopify/react-native-skia 2.12.0-next.1 → 2.12.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (202) hide show
  1. package/Package.swift +117 -0
  2. package/android/CMakeLists.txt +1 -2
  3. package/android/cpp/rnskia-android/RNSkAndroidPlatformContext.h +0 -10
  4. package/android/src/main/java/com/shopify/reactnative/skia/ViewScreenshotService.java +9 -12
  5. package/apple/RNSkApplePlatformContext.h +0 -3
  6. package/apple/RNSkApplePlatformContext.mm +0 -11
  7. package/cpp/api/JsiSkApi.h +0 -6
  8. package/cpp/api/JsiSkFont.h +5 -10
  9. package/cpp/api/JsiSkMatrix.h +4 -2
  10. package/cpp/api/JsiSkSVGFactory.h +4 -0
  11. package/cpp/api/recorder/Convertor.h +5 -2
  12. package/cpp/api/recorder/Drawings.h +13 -3
  13. package/cpp/api/recorder/ImageFilters.h +15 -1
  14. package/cpp/api/recorder/Paint.h +8 -1
  15. package/cpp/jsi/JSICache.cpp +99 -0
  16. package/cpp/jsi/JSICache.h +90 -0
  17. package/cpp/jsi/NativeObject.h +38 -87
  18. package/cpp/jsi/ViewProperty.h +0 -24
  19. package/cpp/rnskia/RNDawnContext.h +2 -1
  20. package/cpp/rnskia/RNDawnWindowContext.h +22 -0
  21. package/cpp/rnskia/RNSkManager.cpp +0 -6
  22. package/cpp/rnskia/RNSkPlatformContext.h +0 -3
  23. package/cpp/skia/include/core/RasterContext.h +25 -0
  24. package/cpp/skia/include/core/SkCanvas.h +0 -1
  25. package/cpp/skia/include/core/SkContext.h +62 -0
  26. package/cpp/skia/include/core/SkContextOptions.h +15 -0
  27. package/cpp/skia/include/core/SkMilestone.h +1 -1
  28. package/cpp/skia/include/core/SkPicture.h +36 -18
  29. package/cpp/skia/include/core/SkRecorder.h +8 -0
  30. package/cpp/skia/include/core/SkSerialProcs.h +2 -6
  31. package/cpp/skia/include/effects/SkImageFilters.h +15 -2
  32. package/cpp/skia/include/gpu/ganesh/GrDirectContext.h +73 -47
  33. package/cpp/skia/include/gpu/ganesh/SkSurfaceGanesh.h +7 -4
  34. package/cpp/skia/include/gpu/ganesh/d3d/GrD3DDirectContext.h +12 -0
  35. package/cpp/skia/include/gpu/ganesh/gl/GrGLDirectContext.h +11 -0
  36. package/cpp/skia/include/gpu/ganesh/mtl/GrMtlDirectContext.h +11 -0
  37. package/cpp/skia/include/gpu/ganesh/vk/GrVkDirectContext.h +13 -0
  38. package/cpp/skia/include/gpu/graphite/ContextOptions.h +6 -0
  39. package/cpp/skia/include/gpu/graphite/GraphiteTypes.h +5 -4
  40. package/cpp/skia/include/gpu/graphite/PrecompileContext.h +9 -1
  41. package/cpp/skia/include/gpu/graphite/Recorder.h +0 -2
  42. package/cpp/skia/include/gpu/graphite/Recording.h +3 -0
  43. package/cpp/skia/include/gpu/graphite/dawn/DawnBackendContext.h +8 -0
  44. package/cpp/skia/include/gpu/graphite/mtl/MtlBackendContext.h +11 -0
  45. package/cpp/skia/include/gpu/graphite/vk/VulkanGraphiteContext.h +11 -0
  46. package/cpp/skia/include/private/SkLog.h +1 -19
  47. package/cpp/skia/include/private/chromium/GrVkSecondaryCBDrawContext.h +2 -1
  48. package/cpp/skia/include/utils/SkLogHandler.h +53 -0
  49. package/cpp/skia/include/utils/SkNWayCanvas.h +1 -0
  50. package/cpp/skia/modules/skcms/src/Transform_inl.h +9 -10
  51. package/cpp/skia/modules/skcms/src/skcms_internals.h +8 -3
  52. package/cpp/skia/modules/skottie/include/SkottieProperty.h +2 -0
  53. package/cpp/skia/modules/skottie/include/TextShaper.h +1 -0
  54. package/cpp/skia/modules/skshaper/include/SkShaper.h +23 -1
  55. package/include/ReactNativeSkia.h +6 -0
  56. package/lib/commonjs/dom/nodes/datatypes/Rect.js +5 -1
  57. package/lib/commonjs/dom/nodes/datatypes/Rect.js.map +1 -1
  58. package/lib/commonjs/external/reanimated/useVideo.js +8 -2
  59. package/lib/commonjs/external/reanimated/useVideo.js.map +1 -1
  60. package/lib/commonjs/renderer/components/Mask.js +3 -9
  61. package/lib/commonjs/renderer/components/Mask.js.map +1 -1
  62. package/lib/commonjs/skia/types/JsiInstance.d.ts +1 -0
  63. package/lib/commonjs/skia/types/JsiInstance.js.map +1 -1
  64. package/lib/commonjs/skia/types/Matrix4.js +7 -2
  65. package/lib/commonjs/skia/types/Matrix4.js.map +1 -1
  66. package/lib/commonjs/skia/types/Skia.d.ts +1 -6
  67. package/lib/commonjs/skia/types/Skia.js.map +1 -1
  68. package/lib/commonjs/skia/web/JsiSkCanvas.js +4 -4
  69. package/lib/commonjs/skia/web/JsiSkCanvas.js.map +1 -1
  70. package/lib/commonjs/skia/web/JsiSkImage.js +6 -3
  71. package/lib/commonjs/skia/web/JsiSkImage.js.map +1 -1
  72. package/lib/commonjs/skia/web/JsiSkPathBuilder.d.ts +1 -1
  73. package/lib/commonjs/skia/web/JsiSkPathBuilder.js +2 -2
  74. package/lib/commonjs/skia/web/JsiSkPathBuilder.js.map +1 -1
  75. package/lib/commonjs/skia/web/JsiSkTextStyle.js +5 -5
  76. package/lib/commonjs/skia/web/JsiSkTextStyle.js.map +1 -1
  77. package/lib/commonjs/skia/web/JsiSkia.js +0 -3
  78. package/lib/commonjs/skia/web/JsiSkia.js.map +1 -1
  79. package/lib/commonjs/skia/web/JsiSkottieAnimation.js +8 -8
  80. package/lib/commonjs/skia/web/JsiSkottieAnimation.js.map +1 -1
  81. package/lib/commonjs/sksg/Recorder/DrawingContext.d.ts +1 -0
  82. package/lib/commonjs/sksg/Recorder/DrawingContext.js +15 -0
  83. package/lib/commonjs/sksg/Recorder/DrawingContext.js.map +1 -1
  84. package/lib/commonjs/sksg/Recorder/Player.js +1 -1
  85. package/lib/commonjs/sksg/Recorder/Player.js.map +1 -1
  86. package/lib/commonjs/sksg/Recorder/Visitor.js +6 -1
  87. package/lib/commonjs/sksg/Recorder/Visitor.js.map +1 -1
  88. package/lib/commonjs/sksg/Recorder/commands/Drawing.js +12 -9
  89. package/lib/commonjs/sksg/Recorder/commands/Drawing.js.map +1 -1
  90. package/lib/commonjs/sksg/Recorder/commands/ImageFilters.js +15 -1
  91. package/lib/commonjs/sksg/Recorder/commands/ImageFilters.js.map +1 -1
  92. package/lib/commonjs/sksg/Recorder/commands/Shaders.js +1 -1
  93. package/lib/commonjs/sksg/Recorder/commands/Shaders.js.map +1 -1
  94. package/lib/commonjs/views/SkiaPictureView.web.js +247 -57
  95. package/lib/commonjs/views/SkiaPictureView.web.js.map +1 -1
  96. package/lib/module/dom/nodes/datatypes/Rect.js +5 -1
  97. package/lib/module/dom/nodes/datatypes/Rect.js.map +1 -1
  98. package/lib/module/external/reanimated/useVideo.js +8 -2
  99. package/lib/module/external/reanimated/useVideo.js.map +1 -1
  100. package/lib/module/renderer/components/Mask.js +3 -9
  101. package/lib/module/renderer/components/Mask.js.map +1 -1
  102. package/lib/module/skia/types/JsiInstance.d.ts +1 -0
  103. package/lib/module/skia/types/JsiInstance.js.map +1 -1
  104. package/lib/module/skia/types/Matrix4.js +7 -2
  105. package/lib/module/skia/types/Matrix4.js.map +1 -1
  106. package/lib/module/skia/types/Skia.d.ts +1 -6
  107. package/lib/module/skia/types/Skia.js.map +1 -1
  108. package/lib/module/skia/web/JsiSkCanvas.js +4 -4
  109. package/lib/module/skia/web/JsiSkCanvas.js.map +1 -1
  110. package/lib/module/skia/web/JsiSkImage.js +6 -3
  111. package/lib/module/skia/web/JsiSkImage.js.map +1 -1
  112. package/lib/module/skia/web/JsiSkPathBuilder.d.ts +1 -1
  113. package/lib/module/skia/web/JsiSkPathBuilder.js +2 -2
  114. package/lib/module/skia/web/JsiSkPathBuilder.js.map +1 -1
  115. package/lib/module/skia/web/JsiSkTextStyle.js +5 -5
  116. package/lib/module/skia/web/JsiSkTextStyle.js.map +1 -1
  117. package/lib/module/skia/web/JsiSkia.js +0 -3
  118. package/lib/module/skia/web/JsiSkia.js.map +1 -1
  119. package/lib/module/skia/web/JsiSkottieAnimation.js +8 -8
  120. package/lib/module/skia/web/JsiSkottieAnimation.js.map +1 -1
  121. package/lib/module/sksg/Recorder/DrawingContext.d.ts +1 -0
  122. package/lib/module/sksg/Recorder/DrawingContext.js +15 -0
  123. package/lib/module/sksg/Recorder/DrawingContext.js.map +1 -1
  124. package/lib/module/sksg/Recorder/Player.js +1 -1
  125. package/lib/module/sksg/Recorder/Player.js.map +1 -1
  126. package/lib/module/sksg/Recorder/Visitor.js +6 -1
  127. package/lib/module/sksg/Recorder/Visitor.js.map +1 -1
  128. package/lib/module/sksg/Recorder/commands/Drawing.js +12 -9
  129. package/lib/module/sksg/Recorder/commands/Drawing.js.map +1 -1
  130. package/lib/module/sksg/Recorder/commands/ImageFilters.js +15 -1
  131. package/lib/module/sksg/Recorder/commands/ImageFilters.js.map +1 -1
  132. package/lib/module/sksg/Recorder/commands/Shaders.js +1 -1
  133. package/lib/module/sksg/Recorder/commands/Shaders.js.map +1 -1
  134. package/lib/module/views/SkiaPictureView.web.js +247 -57
  135. package/lib/module/views/SkiaPictureView.web.js.map +1 -1
  136. package/lib/typescript/lib/commonjs/skia/web/JsiSkPathBuilder.d.ts +1 -1
  137. package/lib/typescript/lib/commonjs/skia/web/JsiSkia.d.ts +0 -1
  138. package/lib/typescript/lib/commonjs/sksg/Recorder/DrawingContext.d.ts +1 -0
  139. package/lib/typescript/lib/module/skia/Skia.web.d.ts +0 -1
  140. package/lib/typescript/lib/module/skia/web/JsiSkPathBuilder.d.ts +1 -1
  141. package/lib/typescript/lib/module/skia/web/JsiSkia.d.ts +0 -1
  142. package/lib/typescript/lib/module/sksg/Recorder/DrawingContext.d.ts +1 -0
  143. package/lib/typescript/react-native.config.d.ts +3 -0
  144. package/lib/typescript/src/skia/types/JsiInstance.d.ts +1 -0
  145. package/lib/typescript/src/skia/types/Skia.d.ts +1 -6
  146. package/lib/typescript/src/skia/web/JsiSkPathBuilder.d.ts +1 -1
  147. package/lib/typescript/src/sksg/Recorder/DrawingContext.d.ts +1 -0
  148. package/package.json +13 -10
  149. package/react-native.config.js +5 -0
  150. package/src/dom/nodes/datatypes/Rect.ts +6 -1
  151. package/src/external/reanimated/useVideo.ts +7 -2
  152. package/src/renderer/components/Mask.tsx +10 -3
  153. package/src/skia/types/JsiInstance.ts +2 -0
  154. package/src/skia/types/Matrix4.ts +6 -2
  155. package/src/skia/types/Skia.ts +1 -7
  156. package/src/skia/web/JsiSkCanvas.ts +11 -6
  157. package/src/skia/web/JsiSkImage.ts +6 -3
  158. package/src/skia/web/JsiSkPathBuilder.ts +2 -2
  159. package/src/skia/web/JsiSkTextStyle.ts +20 -15
  160. package/src/skia/web/JsiSkia.ts +0 -4
  161. package/src/skia/web/JsiSkottieAnimation.ts +8 -8
  162. package/src/sksg/Recorder/DrawingContext.ts +15 -0
  163. package/src/sksg/Recorder/Player.ts +1 -1
  164. package/src/sksg/Recorder/Visitor.ts +9 -6
  165. package/src/sksg/Recorder/commands/Drawing.ts +12 -9
  166. package/src/sksg/Recorder/commands/ImageFilters.ts +20 -1
  167. package/src/sksg/Recorder/commands/Shaders.ts +1 -1
  168. package/src/views/SkiaPictureView.web.tsx +245 -57
  169. package/cpp/api/JsiSkiaContext.h +0 -94
  170. package/cpp/dawn/include/dawn/dawn_proc.h +0 -53
  171. package/cpp/dawn/include/dawn/dawn_proc_table.h +0 -330
  172. package/cpp/dawn/include/dawn/dawn_thread_dispatch_proc.h +0 -47
  173. package/cpp/dawn/include/dawn/dawn_version.h +0 -41
  174. package/cpp/dawn/include/dawn/native/D3D11Backend.h +0 -65
  175. package/cpp/dawn/include/dawn/native/D3D12Backend.h +0 -103
  176. package/cpp/dawn/include/dawn/native/D3DBackend.h +0 -56
  177. package/cpp/dawn/include/dawn/native/DawnNative.h +0 -368
  178. package/cpp/dawn/include/dawn/native/MetalBackend.h +0 -56
  179. package/cpp/dawn/include/dawn/native/NullBackend.h +0 -39
  180. package/cpp/dawn/include/dawn/native/OpenGLBackend.h +0 -89
  181. package/cpp/dawn/include/dawn/native/VulkanBackend.h +0 -183
  182. package/cpp/dawn/include/dawn/native/WebGPUBackend.h +0 -49
  183. package/cpp/dawn/include/dawn/native/dawn_native_export.h +0 -49
  184. package/cpp/dawn/include/dawn/platform/DawnPlatform.h +0 -207
  185. package/cpp/dawn/include/dawn/platform/dawn_platform_export.h +0 -49
  186. package/cpp/dawn/include/dawn/replay/Replay.h +0 -99
  187. package/cpp/dawn/include/dawn/replay/dawn_replay_export.h +0 -49
  188. package/cpp/dawn/include/dawn/webgpu_cpp_print.h +0 -2856
  189. package/cpp/dawn/include/tint/tint.h +0 -91
  190. package/cpp/dawn/include/webgpu/webgpu.h +0 -5029
  191. package/cpp/dawn/include/webgpu/webgpu_cpp.h +0 -10353
  192. package/cpp/dawn/include/webgpu/webgpu_cpp_chained_struct.h +0 -57
  193. package/cpp/dawn/include/webgpu/webgpu_enum_class_bitmasks.h +0 -162
  194. package/cpp/dawn/include/webgpu/webgpu_glfw.h +0 -88
  195. package/cpp/jsi/RuntimeAwareCache.cpp +0 -7
  196. package/cpp/jsi/RuntimeAwareCache.h +0 -117
  197. package/cpp/jsi/RuntimeLifecycleMonitor.cpp +0 -72
  198. package/cpp/jsi/RuntimeLifecycleMonitor.h +0 -32
  199. package/cpp/skia/src/gpu/graphite/ContextOptionsPriv.h +0 -45
  200. package/cpp/skia/src/gpu/graphite/ResourceTypes.h +0 -360
  201. package/cpp/skia/src/gpu/graphite/TextureProxyView.h +0 -105
  202. package/libs/.graphite +0 -1
@@ -8,14 +8,14 @@
8
8
  #include <jsi/jsi.h>
9
9
  #include <memory>
10
10
  #include <mutex>
11
- #include <optional>
12
11
  #include <string>
13
12
  #include <type_traits>
13
+ #include <typeindex>
14
14
  #include <unordered_map>
15
15
  #include <utility>
16
16
 
17
17
  #include "jsi/BoxedNativeObject.h"
18
- #include "jsi/RuntimeAwareCache.h" // Use Skia's RuntimeAwareCache
18
+ #include "jsi/JSICache.h"
19
19
 
20
20
  // Forward declare to avoid circular dependency
21
21
  namespace RNJsi {
@@ -37,45 +37,6 @@ static constexpr size_t kMinMemoryPressure = 256;
37
37
  // Forward declaration
38
38
  template <typename Derived> class NativeObject;
39
39
 
40
- /**
41
- * Per-runtime cache entry for a prototype object.
42
- * Uses std::optional<jsi::Object> so the prototype is stored directly
43
- * without extra indirection.
44
- */
45
- struct PrototypeCacheEntry {
46
- std::optional<jsi::Object> prototype;
47
- };
48
-
49
- /**
50
- * Wrapper for static RuntimeAwareCache that handles hot reload.
51
- *
52
- * When used with static storage (like prototype caches), the cache persists
53
- * across hot reloads. But the JSI objects inside become invalid when the
54
- * runtime is destroyed. This wrapper tracks which runtime the cache was
55
- * created for and allocates a new cache when the runtime changes.
56
- *
57
- * The old cache is intentionally leaked - we cannot safely destroy JSI
58
- * objects after their runtime is gone.
59
- */
60
- template <typename T> struct StaticRuntimeAwareCache {
61
- RNJsi::RuntimeAwareCache<T> *cache = nullptr;
62
- jsi::Runtime *cacheRuntime = nullptr;
63
-
64
- RNJsi::RuntimeAwareCache<T> &get(jsi::Runtime &rt) {
65
- auto mainRuntime = RNJsi::BaseRuntimeAwareCache::getMainJsRuntime();
66
- if (&rt == mainRuntime && cacheRuntime != mainRuntime) {
67
- // Main runtime changed (hot reload) - allocate new cache, leak old one
68
- cache = new RNJsi::RuntimeAwareCache<T>();
69
- cacheRuntime = mainRuntime;
70
- }
71
- if (cache == nullptr) {
72
- cache = new RNJsi::RuntimeAwareCache<T>();
73
- cacheRuntime = mainRuntime;
74
- }
75
- return *cache;
76
- }
77
- };
78
-
79
40
  /**
80
41
  * Base class for native objects using the NativeState pattern.
81
42
  *
@@ -112,29 +73,20 @@ public:
112
73
  using IsNativeObject = std::true_type;
113
74
 
114
75
  /**
115
- * Get the prototype cache for this type.
116
- * Each NativeObject<Derived> type has its own static cache.
117
- * Uses StaticRuntimeAwareCache to properly handle runtime lifecycle
118
- * and hot reload (where the main runtime is destroyed and recreated).
119
- *
120
- * Callers must hold getPrototypeCacheMutex(): the cache is reached
121
- * concurrently from the main JS thread (create()) and from worklet
122
- * runtime threads (BoxedNativeObject::unbox() -> installPrototype()).
76
+ * Key under which this class's prototype is stored in the per-runtime
77
+ * JSICache: the C++ type of Derived.
123
78
  */
124
- static RNJsi::RuntimeAwareCache<PrototypeCacheEntry> &
125
- getPrototypeCache(jsi::Runtime &runtime) {
126
- static StaticRuntimeAwareCache<PrototypeCacheEntry> cache;
127
- return cache.get(runtime);
79
+ static JSICache::PrototypeKey prototypeKey() {
80
+ return std::type_index(typeid(Derived));
128
81
  }
129
82
 
130
83
  /**
131
- * Per-class mutex guarding getPrototypeCache() and prototype
132
- * installation. Serializes the StaticRuntimeAwareCache pointer swap
133
- * (hot reload) and the per-runtime cache lookups.
84
+ * Returns this class's prototype on `runtime`, or nullptr if it has not
85
+ * been installed there yet. The prototype is owned by the runtime (see
86
+ * JSICache), so the pointer is valid for as long as `runtime` is.
134
87
  */
135
- static std::mutex &getPrototypeCacheMutex() {
136
- static std::mutex mutex;
137
- return mutex;
88
+ static jsi::Object *getCachedPrototype(jsi::Runtime &runtime) {
89
+ return JSICache::get(runtime).getPrototype(prototypeKey());
138
90
  }
139
91
 
140
92
  /**
@@ -142,10 +94,21 @@ public:
142
94
  * Called automatically by create(), but can be called manually.
143
95
  */
144
96
  static void installPrototype(jsi::Runtime &runtime) {
145
- std::lock_guard<std::mutex> lock(getPrototypeCacheMutex());
146
- auto &entry = getPrototypeCache(runtime).get(runtime);
147
- if (entry.prototype.has_value()) {
148
- return; // Already installed
97
+ ensurePrototype(runtime);
98
+ }
99
+
100
+ /**
101
+ * Look up (and install on first use) the prototype for this runtime.
102
+ *
103
+ * The returned reference is owned by the runtime's JSICache and stays
104
+ * valid for as long as the runtime does (std::unordered_map keeps
105
+ * references to its elements stable across rehashes). No locking is
106
+ * needed: a jsi::Runtime is single-threaded and its cache is only ever
107
+ * touched from its own thread.
108
+ */
109
+ static jsi::Object &ensurePrototype(jsi::Runtime &runtime) {
110
+ if (auto *cached = getCachedPrototype(runtime)) {
111
+ return *cached; // Already installed on this runtime
149
112
  }
150
113
 
151
114
  // Create prototype object
@@ -262,8 +225,9 @@ public:
262
225
  });
263
226
  });
264
227
 
265
- // Cache the prototype
266
- entry.prototype = std::move(prototype);
228
+ // Hand the prototype to the runtime-owned cache
229
+ return JSICache::get(runtime).setPrototype(prototypeKey(),
230
+ std::move(prototype));
267
231
  }
268
232
 
269
233
  /**
@@ -274,13 +238,7 @@ public:
274
238
  * created internally by the native code).
275
239
  */
276
240
  static void installConstructor(jsi::Runtime &runtime) {
277
- installPrototype(runtime);
278
-
279
- std::lock_guard<std::mutex> lock(getPrototypeCacheMutex());
280
- auto &entry = getPrototypeCache(runtime).get(runtime);
281
- if (!entry.prototype.has_value()) {
282
- return;
283
- }
241
+ auto &prototype = ensurePrototype(runtime);
284
242
 
285
243
  // Create a constructor function that throws when called directly
286
244
  auto ctor = jsi::Function::createFromHostFunction(
@@ -294,10 +252,10 @@ public:
294
252
 
295
253
  // Set the prototype property on the constructor
296
254
  // This is what makes `instanceof` work
297
- ctor.setProperty(runtime, "prototype", *entry.prototype);
255
+ ctor.setProperty(runtime, "prototype", prototype);
298
256
 
299
257
  // Set constructor property on prototype pointing back to constructor
300
- entry.prototype->setProperty(runtime, "constructor", ctor);
258
+ prototype.setProperty(runtime, "constructor", ctor);
301
259
 
302
260
  // Install on global
303
261
  runtime.global().setProperty(runtime, Derived::CLASS_NAME, std::move(ctor));
@@ -308,8 +266,6 @@ public:
308
266
  */
309
267
  static jsi::Value create(jsi::Runtime &runtime,
310
268
  std::shared_ptr<Derived> instance) {
311
- installPrototype(runtime);
312
-
313
269
  // Store creation runtime for logging etc.
314
270
  instance->setCreationRuntime(&runtime);
315
271
 
@@ -319,18 +275,13 @@ public:
319
275
  // Attach native state
320
276
  obj.setNativeState(runtime, instance);
321
277
 
322
- // Set prototype
278
+ // Install (on first use) and apply the prototype
323
279
  {
324
- std::lock_guard<std::mutex> lock(getPrototypeCacheMutex());
325
- auto &entry = getPrototypeCache(runtime).get(runtime);
326
- if (entry.prototype.has_value()) {
327
- // Use Object.setPrototypeOf to set the prototype
328
- auto objectCtor =
329
- runtime.global().getPropertyAsObject(runtime, "Object");
330
- auto setPrototypeOf =
331
- objectCtor.getPropertyAsFunction(runtime, "setPrototypeOf");
332
- setPrototypeOf.call(runtime, obj, *entry.prototype);
333
- }
280
+ auto &prototype = ensurePrototype(runtime);
281
+ auto objectCtor = runtime.global().getPropertyAsObject(runtime, "Object");
282
+ auto setPrototypeOf =
283
+ objectCtor.getPropertyAsFunction(runtime, "setPrototypeOf");
284
+ setPrototypeOf.call(runtime, obj, prototype);
334
285
  }
335
286
 
336
287
  // Set memory pressure hint for GC
@@ -1,40 +1,16 @@
1
1
  #pragma once
2
2
 
3
- #include <atomic>
4
3
  #include <functional>
5
4
  #include <jsi/jsi.h>
6
5
  #include <memory>
7
6
  #include <string>
8
7
  #include <variant>
9
8
 
10
- #include "RuntimeLifecycleMonitor.h"
11
9
  #include "api/JsiSkPicture.h"
12
10
 
13
11
  namespace RNJsi {
14
12
  namespace jsi = facebook::jsi;
15
13
 
16
- class RuntimeAwareRuntimeGuard : public RuntimeLifecycleListener {
17
- public:
18
- explicit RuntimeAwareRuntimeGuard(jsi::Runtime &runtime)
19
- : _runtime(&runtime) {
20
- RuntimeLifecycleMonitor::addListener(runtime, this);
21
- }
22
-
23
- ~RuntimeAwareRuntimeGuard() override {
24
- auto runtime = _runtime.load();
25
- if (runtime != nullptr) {
26
- RuntimeLifecycleMonitor::removeListener(*runtime, this);
27
- }
28
- }
29
-
30
- void onRuntimeDestroyed(jsi::Runtime *) override { _runtime.store(nullptr); }
31
-
32
- jsi::Runtime *getRuntime() const { return _runtime.load(); }
33
-
34
- private:
35
- std::atomic<jsi::Runtime *> _runtime;
36
- };
37
-
38
14
  class ViewProperty {
39
15
  public:
40
16
  ViewProperty(jsi::Runtime &runtime, const jsi::Value &value) {
@@ -147,7 +147,8 @@ public:
147
147
  vkBegin.newLayout = 0;
148
148
  beginAccessDesc.nextInChain = &vkBegin;
149
149
  #endif
150
- bool success = memory.BeginAccess(texture, &beginAccessDesc);
150
+ bool success =
151
+ memory.BeginAccess(texture, &beginAccessDesc) == wgpu::Status::Success;
151
152
 
152
153
  if (success) {
153
154
  skgpu::graphite::BackendTexture betFromView =
@@ -82,6 +82,7 @@ private:
82
82
  config.width = _width;
83
83
  config.height = _height;
84
84
  config.presentMode = wgpu::PresentMode::Fifo;
85
+ config.usage = supportedSurfaceUsage();
85
86
  #ifdef __APPLE__
86
87
  config.alphaMode = wgpu::CompositeAlphaMode::Premultiplied;
87
88
  #endif
@@ -93,6 +94,27 @@ private:
93
94
  #endif
94
95
  }
95
96
 
97
+ // Graphite needs more than RenderAttachment on the swapchain texture:
98
+ // TextureBinding so a render pass can reload the existing contents through
99
+ // LoadOp::ExpandResolveTexture (any backdrop filter or mid-frame readback
100
+ // splits the pass), and CopySrc for copy tasks. Only request what the
101
+ // surface reports as supported.
102
+ wgpu::TextureUsage supportedSurfaceUsage() {
103
+ wgpu::TextureUsage usage = wgpu::TextureUsage::RenderAttachment;
104
+ wgpu::SurfaceCapabilities capabilities;
105
+ if (_surface.GetCapabilities(_device.GetAdapter(), &capabilities) !=
106
+ wgpu::Status::Success) {
107
+ return usage;
108
+ }
109
+ for (auto extra :
110
+ {wgpu::TextureUsage::TextureBinding, wgpu::TextureUsage::CopySrc}) {
111
+ if (capabilities.usages & extra) {
112
+ usage |= extra;
113
+ }
114
+ }
115
+ return usage;
116
+ }
117
+
96
118
  bool surfaceSupportsFormat(wgpu::TextureFormat format) {
97
119
  wgpu::SurfaceCapabilities capabilities;
98
120
  if (_surface.GetCapabilities(_device.GetAdapter(), &capabilities) !=
@@ -9,8 +9,6 @@
9
9
  #include "RNSkView.h"
10
10
  #include "api/JsiSkApi.h"
11
11
 
12
- #include "jsi/RuntimeAwareCache.h"
13
-
14
12
  namespace RNSkia {
15
13
  namespace jsi = facebook::jsi;
16
14
 
@@ -21,10 +19,6 @@ RNSkManager::RNSkManager(
21
19
  : _jsRuntime(jsRuntime), _platformContext(platformContext),
22
20
  _jsCallInvoker(jsCallInvoker),
23
21
  _viewApi(std::make_shared<RNSkJsiViewApi>(platformContext)) {
24
-
25
- // Register main runtime
26
- RNJsi::BaseRuntimeAwareCache::setMainJsRuntime(_jsRuntime);
27
-
28
22
  // Install bindings
29
23
  installBindings();
30
24
  }
@@ -96,9 +96,6 @@ public:
96
96
  virtual sk_sp<SkSurface>
97
97
  makeOffscreenSurface(int width, int height, bool useP3ColorSpace = false) = 0;
98
98
 
99
- virtual std::shared_ptr<WindowContext>
100
- makeContextFromNativeSurface(void *surface, int width, int height) = 0;
101
-
102
99
  /**
103
100
  * Creates an image from a native buffer.
104
101
  * - On iOS, this is a `CVPixelBufferRef`
@@ -0,0 +1,25 @@
1
+ /*
2
+ * Copyright 2026 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 RasterContext_DEFINED
9
+ #define RasterContext_DEFINED
10
+
11
+ #include "include/core/SkRefCnt.h"
12
+
13
+ #include <memory>
14
+
15
+ class SkContext;
16
+ struct SkContextOptions;
17
+
18
+ namespace SkContexts {
19
+
20
+ // Creates a context for SkContext with only Software Rasterization
21
+ std::unique_ptr<SkContext> MakeRaster(const SkContextOptions& options);
22
+
23
+ } // namespace SkContexts
24
+
25
+ #endif // RasterContext_DEFINED
@@ -2529,7 +2529,6 @@ private:
2529
2529
  std::unique_ptr<SkRasterHandleAllocator> fAllocator;
2530
2530
 
2531
2531
  SkSurface_Base* fSurfaceBase;
2532
- virtual SkSurface_Base* getSurfaceBase() const { return fSurfaceBase; }
2533
2532
  void setSurfaceBase(SkSurface_Base* sb) {
2534
2533
  fSurfaceBase = sb;
2535
2534
  }
@@ -0,0 +1,62 @@
1
+ /*
2
+ * Copyright 2026 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 SkContext_DEFINED
9
+ #define SkContext_DEFINED
10
+
11
+ #include "include/core/SkRefCnt.h"
12
+ #include "include/private/SkAPI.h"
13
+
14
+ class SkContextPriv;
15
+ class SkResourceCache;
16
+ class SkSharedContext;
17
+ class SkStrikeCache;
18
+ class SkTraceMemoryDump;
19
+ class SkTypefaceCache;
20
+ struct SkContextOptions;
21
+
22
+ /**
23
+ * @brief SkContext is a central context object that serves as the mandatory first point of
24
+ * initialization for all Skia clients. SkContext consolidates global state, management of shared
25
+ * resources, and internal caches.
26
+ */
27
+ class SK_API SkContext final {
28
+ public:
29
+ SkContext(const SkContext&) = delete;
30
+ SkContext(SkContext&&) = delete;
31
+ SkContext& operator=(const SkContext&) = delete;
32
+ SkContext& operator=(SkContext&&) = delete;
33
+
34
+ ~SkContext();
35
+
36
+ SkContextPriv priv();
37
+ const SkContextPriv priv() const;
38
+
39
+ private:
40
+ SkContext(sk_sp<SkSharedContext>);
41
+
42
+ SkResourceCache* resourceCache() const;
43
+ SkStrikeCache* fontCache() const;
44
+ SkTypefaceCache* typefaceCache() const;
45
+
46
+ size_t fontCacheLimit() const;
47
+ size_t setFontCacheLimit(size_t bytes);
48
+ size_t fontCacheUsed() const;
49
+
50
+ int fontCacheCountLimit() const;
51
+ int setFontCacheCountLimit(int count);
52
+ int fontCacheCountUsed() const;
53
+
54
+ void purgeFontCache();
55
+ void purgePinnedFontCache();
56
+
57
+ void dumpMemoryStatistics(SkTraceMemoryDump* dump);
58
+
59
+ sk_sp<SkSharedContext> fSharedContext;
60
+ };
61
+
62
+ #endif // SkContext_DEFINED
@@ -0,0 +1,15 @@
1
+ /*
2
+ * Copyright 2026 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 SkContextOptions_DEFINED
9
+ #define SkContextOptions_DEFINED
10
+
11
+ #include "include/private/SkAPI.h"
12
+
13
+ struct SK_API SkContextOptions {};
14
+
15
+ #endif // SkContextOptions_DEFINED
@@ -5,5 +5,5 @@
5
5
  * found in the LICENSE file.
6
6
  */
7
7
  #ifndef SK_MILESTONE
8
- #define SK_MILESTONE 152
8
+ #define SK_MILESTONE 154
9
9
  #endif
@@ -16,12 +16,16 @@
16
16
  #include <atomic>
17
17
  #include <cstddef>
18
18
  #include <cstdint>
19
+ #include <memory>
19
20
 
21
+ class SkBBoxHierarchy;
20
22
  class SkCanvas;
21
23
  class SkData;
22
24
  class SkMatrix;
25
+ class SkRecord;
23
26
  class SkStream;
24
27
  class SkWStream;
28
+ class SkSnapshotArray;
25
29
  enum class SkFilterMode;
26
30
  struct SkDeserialProcs;
27
31
  struct SkSerialProcs;
@@ -33,8 +37,8 @@ struct SkSerialProcs;
33
37
  SkPicture records drawing commands made to SkCanvas. The command stream may be
34
38
  played in whole or in part at a later time.
35
39
 
36
- SkPicture is an abstract class. SkPicture may be generated by SkPictureRecorder
37
- or SkDrawable, or from SkPicture previously saved to SkData or SkStream.
40
+ SkPicture may be generated by SkPictureRecorder or SkDrawable, or from a
41
+ SkPicture previously saved to SkData or SkStream.
38
42
 
39
43
  SkPicture may contain any SkCanvas drawing command, as well as one or more
40
44
  SkCanvas matrix or SkCanvas clip. SkPicture has a cull SkRect, which is used as
@@ -84,7 +88,8 @@ public:
84
88
  @param procs custom serial data decoders; may be nullptr
85
89
  @return SkPicture constructed from data
86
90
  */
87
- static sk_sp<SkPicture> MakeFromData(const void* data, size_t size,
91
+ static sk_sp<SkPicture> MakeFromData(const void* data,
92
+ size_t size,
88
93
  const SkDeserialProcs* procs = nullptr);
89
94
 
90
95
  /** \class SkPicture::AbortCallback
@@ -133,7 +138,7 @@ public:
133
138
 
134
139
  example: https://fiddle.skia.org/c/@Picture_playback
135
140
  */
136
- virtual void playback(SkCanvas* canvas, AbortCallback* callback = nullptr) const = 0;
141
+ void playback(SkCanvas* canvas, AbortCallback* callback = nullptr) const;
137
142
 
138
143
  /** Returns cull SkRect for this picture, passed in when SkPicture was created.
139
144
  Returned SkRect does not specify clipping SkRect for SkPicture; cull is hint
@@ -146,7 +151,7 @@ public:
146
151
 
147
152
  example: https://fiddle.skia.org/c/@Picture_cullRect
148
153
  */
149
- virtual SkRect cullRect() const = 0;
154
+ SkRect cullRect() const { return fCullRect; }
150
155
 
151
156
  /** Returns a non-zero value unique among SkPicture in Skia process.
152
157
 
@@ -212,11 +217,12 @@ public:
212
217
 
213
218
  @param nested if true, include the op-counts of nested pictures as well, else
214
219
  just return count the ops in the top-level picture.
215
- @return approximate operation count
220
+ @return approximate operation count. If 0 is returned, we say the SkPicture is "empty"
221
+ meaning its cullRect is the result of an SkRect::MakeEmpty().
216
222
 
217
223
  example: https://fiddle.skia.org/c/@Picture_approximateOpCount
218
224
  */
219
- virtual int approximateOpCount(bool nested = false) const = 0;
225
+ int approximateOpCount(bool nested = false) const;
220
226
 
221
227
  /** Returns the approximate byte size of SkPicture. Does not include large objects
222
228
  referenced by SkPicture.
@@ -225,7 +231,7 @@ public:
225
231
 
226
232
  example: https://fiddle.skia.org/c/@Picture_approximateBytesUsed
227
233
  */
228
- virtual size_t approximateBytesUsed() const = 0;
234
+ size_t approximateBytesUsed() const;
229
235
 
230
236
  /** Return a new shader that will draw with this picture.
231
237
  *
@@ -240,18 +246,23 @@ public:
240
246
  * bounds.
241
247
  * @return Returns a new shader object. Note: this function never returns null.
242
248
  */
243
- sk_sp<SkShader> makeShader(SkTileMode tmx, SkTileMode tmy, SkFilterMode mode,
244
- const SkMatrix* localMatrix, const SkRect* tileRect) const;
249
+ sk_sp<SkShader> makeShader(SkTileMode tmx,
250
+ SkTileMode tmy,
251
+ SkFilterMode mode,
252
+ const SkMatrix* localMatrix,
253
+ const SkRect* tileRect) const;
245
254
 
246
255
  sk_sp<SkShader> makeShader(SkTileMode tmx, SkTileMode tmy, SkFilterMode mode) const {
247
256
  return this->makeShader(tmx, tmy, mode, nullptr, nullptr);
248
257
  }
249
258
 
250
259
  private:
251
- // Allowed subclasses.
252
- SkPicture();
253
- friend class SkBigPicture;
254
- friend class SkEmptyPicture;
260
+ SkPicture(const SkRect& cull,
261
+ sk_sp<const SkRecord> record,
262
+ std::unique_ptr<const SkSnapshotArray> drawablePicts,
263
+ sk_sp<const SkBBoxHierarchy> bbh,
264
+ size_t approxBytesUsedBySubPictures);
265
+
255
266
  friend class SkPicturePriv;
256
267
 
257
268
  void serialize(SkWStream*, const SkSerialProcs*, class SkRefCntSet* typefaces,
@@ -273,9 +284,6 @@ private:
273
284
  static bool BufferIsSKP(class SkReadBuffer*, struct SkPictInfo*);
274
285
  friend bool SkPicture_StreamIsSKP(SkStream*, struct SkPictInfo*);
275
286
 
276
- // Returns NULL if this is not an SkBigPicture.
277
- virtual const class SkBigPicture* asSkBigPicture() const { return nullptr; }
278
-
279
287
  static bool IsValidPictInfo(const struct SkPictInfo& info);
280
288
  static sk_sp<SkPicture> Forwardport(const struct SkPictInfo&,
281
289
  const class SkPictureData*,
@@ -284,7 +292,17 @@ private:
284
292
  struct SkPictInfo createHeader() const;
285
293
  class SkPictureData* backport() const;
286
294
 
287
- uint32_t fUniqueID;
295
+ // When fRecord is nullptr, then we treat the SkPicture as a "placeholder"
296
+ // placeholders provide the bare minimum to operate on an SkPicture
297
+ bool isPlaceholder() const { return !fRecord; }
298
+
299
+ const uint32_t fUniqueID;
300
+ const SkRect fCullRect;
301
+ const size_t fApproxBytesUsedBySubPictures;
302
+ const sk_sp<const SkRecord> fRecord;
303
+ const std::unique_ptr<const SkSnapshotArray> fDrawablePicts;
304
+ const sk_sp<const SkBBoxHierarchy> fBBH;
305
+
288
306
  mutable std::atomic<bool> fAddedToCache{false};
289
307
  };
290
308
 
@@ -7,7 +7,9 @@
7
7
  #ifndef SkRecorder_DEFINED
8
8
  #define SkRecorder_DEFINED
9
9
 
10
+ #include "include/core/SkPicture.h"
10
11
  #include "include/private/SkAPI.h"
12
+ #include "include/private/SkTArray.h"
11
13
 
12
14
  class SkCanvas;
13
15
  class SkSurface;
@@ -34,11 +36,17 @@ public:
34
36
 
35
37
  virtual skcpu::Recorder* cpuRecorder() = 0;
36
38
 
39
+ protected:
40
+ skia_private::TArray<sk_sp<SkPicture>> fCapturedPictures;
41
+
37
42
  private:
38
43
 
39
44
  /**
40
45
  * Attempts to create and return an SkCaptureCanvas that wraps the provided base canvas.
41
46
  * Returns nullptr if capture is not enabled.
47
+ *
48
+ * TODO: When implementing in all Recorder subclasses, see if the implementations can be shared
49
+ * and moved here.
42
50
  */
43
51
  virtual SkCanvas* makeCaptureCanvas(SkCanvas*) = 0;
44
52
  virtual void createCaptureBreakpoint(SkSurface*) = 0;
@@ -47,8 +47,7 @@ using SkSerialTypefaceProc = SkSerialReturnType (*)(SkTypeface*, void* ctx);
47
47
  using SkDeserialPictureProc = sk_sp<SkPicture> (*)(const void* data, size_t length, void* ctx);
48
48
 
49
49
  /**
50
- * Called with the encoded form of an image. The proc can return an image object, or if it
51
- * returns nullptr, then Skia will take its default action to try to create an image from the data.
50
+ * Called with the encoded form of an image. If this is not set, no image decoding will be done.
52
51
  *
53
52
  * This will also be used to decode the internal mipmap layers that are saved on some images.
54
53
  *
@@ -60,14 +59,11 @@ using SkDeserialPictureProc = sk_sp<SkPicture> (*)(const void* data, size_t leng
60
59
  * must make a copy of any data they needed after the proc finishes, since the data will go away
61
60
  * after serialization ends.
62
61
  */
63
- #if !defined(SK_LEGACY_DESERIAL_IMAGE_PROC)
64
- using SkDeserialImageProc = sk_sp<SkImage> (*)(const void* data, size_t length, void* ctx);
65
- #else
66
62
  using SkDeserialImageProc = sk_sp<SkImage> (*)(const void* data,
67
63
  size_t length,
68
64
  std::optional<SkAlphaType>,
69
65
  void* ctx);
70
- #endif
66
+
71
67
  using SkDeserialImageFromDataProc = sk_sp<SkImage> (*)(sk_sp<SkData>,
72
68
  std::optional<SkAlphaType>,
73
69
  void* ctx);
@@ -414,12 +414,21 @@ public:
414
414
  * This allows Skia to provide sampleable values for the image filter without worrying about
415
415
  * boundary conditions.
416
416
  *
417
+ * By default the output of a runtime shader is unbounded, since Skia cannot know what colors
418
+ * the SkSL will produce for pixels outside of its inputs' bounds. If
419
+ * 'restrictOutputToInputBounds' is true, the caller promises that the SkSL evaluates to
420
+ * transparent black wherever its child shaders are transparent black, so the filter's output
421
+ * bounds can be restricted to the union of its inputs' output bounds (the source image's
422
+ * bounds when 'input' is null). This lets downstream filters (e.g. a blur with a non-decal
423
+ * tile mode) see the original content bounds instead of an unbounded result.
424
+ *
417
425
  * This requires a GPU backend or SkSL to be compiled in.
418
426
  */
419
427
  static sk_sp<SkImageFilter> RuntimeShader(const SkRuntimeEffectBuilder& builder,
420
428
  SkScalar sampleRadius,
421
429
  std::string_view childShaderName,
422
- sk_sp<SkImageFilter> input);
430
+ sk_sp<SkImageFilter> input,
431
+ bool restrictOutputToInputBounds = false);
423
432
 
424
433
  /**
425
434
  * Create a filter that fills the output with the per-pixel evaluation of the SkShader produced
@@ -453,13 +462,17 @@ public:
453
462
  * childShaderNames) will be evaluated with coordinates at most 'maxSampleRadius' away from the
454
463
  * coordinate provided to the runtime shader itself.
455
464
  *
465
+ * If 'restrictOutputToInputBounds' is true, the filter's output bounds are restricted to the
466
+ * union of its inputs' output bounds; see the single-child variant for details.
467
+ *
456
468
  * This requires a GPU backend or SkSL to be compiled in.
457
469
  */
458
470
  static sk_sp<SkImageFilter> RuntimeShader(const SkRuntimeEffectBuilder& builder,
459
471
  SkScalar maxSampleRadius,
460
472
  std::string_view childShaderNames[],
461
473
  const sk_sp<SkImageFilter> inputs[],
462
- int inputCount);
474
+ int inputCount,
475
+ bool restrictOutputToInputBounds = false);
463
476
 
464
477
  enum class Dither : bool {
465
478
  kNo = false,