react-native-skia 3.0.3 → 3.0.5

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 (210) hide show
  1. package/android/CMakeLists.txt +0 -2
  2. package/android/build.gradle +15 -7
  3. package/android/cpp/jni/JniPlatformContext.cpp +0 -24
  4. package/android/cpp/jni/include/JniPlatformContext.h +0 -2
  5. package/android/cpp/rnskia-android/RNSkAndroidPlatformContext.h +0 -140
  6. package/android/src/main/java/com/reactnative/skia/BackingViewKind.java +24 -0
  7. package/android/src/main/java/com/reactnative/skia/FrameScheduler.java +104 -0
  8. package/android/src/main/java/com/reactnative/skia/PlatformContext.java +0 -5
  9. package/android/src/main/java/com/reactnative/skia/SkiaView.java +55 -44
  10. package/android/src/test/java/com/reactnative/skia/FrameSchedulerTest.java +186 -0
  11. package/apple/RNSkApplePlatformContext.h +0 -10
  12. package/apple/RNSkApplePlatformContext.mm +0 -182
  13. package/cpp/api/JsiGPUTexture.h +48 -0
  14. package/cpp/api/JsiSkApi.h +1 -16
  15. package/cpp/api/JsiSkImage.h +0 -12
  16. package/cpp/api/JsiSkImageFactory.h +36 -57
  17. package/cpp/api/JsiSkSurface.h +3 -10
  18. package/cpp/api/JsiSkSurfaceFactory.h +13 -18
  19. package/cpp/rnskia/RNDawnContext.h +5 -113
  20. package/cpp/rnskia/RNDawnUtils.h +33 -0
  21. package/cpp/rnskia/RNSkPlatformContext.h +0 -54
  22. package/cpp/rnskia/RNSkView.h +10 -7
  23. package/lib/commonjs/external/reanimated/index.d.ts +0 -1
  24. package/lib/commonjs/external/reanimated/index.js +0 -11
  25. package/lib/commonjs/external/reanimated/index.js.map +1 -1
  26. package/lib/commonjs/mock/index.js +1 -2
  27. package/lib/commonjs/mock/index.js.map +1 -1
  28. package/lib/commonjs/skia/types/GPUTexture.d.ts +11 -0
  29. package/lib/commonjs/skia/types/GPUTexture.js +2 -0
  30. package/lib/commonjs/skia/types/GPUTexture.js.map +1 -0
  31. package/lib/commonjs/skia/types/Image/Image.d.ts +0 -10
  32. package/lib/commonjs/skia/types/Image/Image.js.map +1 -1
  33. package/lib/commonjs/skia/types/Image/ImageFactory.d.ts +25 -48
  34. package/lib/commonjs/skia/types/Image/ImageFactory.js.map +1 -1
  35. package/lib/commonjs/skia/types/Skia.d.ts +0 -4
  36. package/lib/commonjs/skia/types/Skia.js.map +1 -1
  37. package/lib/commonjs/skia/types/Surface/Surface.d.ts +3 -14
  38. package/lib/commonjs/skia/types/Surface/Surface.js.map +1 -1
  39. package/lib/commonjs/skia/types/Surface/SurfaceFactory.d.ts +10 -9
  40. package/lib/commonjs/skia/types/Surface/SurfaceFactory.js.map +1 -1
  41. package/lib/commonjs/skia/types/index.d.ts +1 -2
  42. package/lib/commonjs/skia/types/index.js +11 -22
  43. package/lib/commonjs/skia/types/index.js.map +1 -1
  44. package/lib/commonjs/skia/web/JsiSkImage.d.ts +0 -1
  45. package/lib/commonjs/skia/web/JsiSkImage.js +0 -4
  46. package/lib/commonjs/skia/web/JsiSkImage.js.map +1 -1
  47. package/lib/commonjs/skia/web/JsiSkImageFactory.d.ts +4 -5
  48. package/lib/commonjs/skia/web/JsiSkImageFactory.js +6 -10
  49. package/lib/commonjs/skia/web/JsiSkImageFactory.js.map +1 -1
  50. package/lib/commonjs/skia/web/JsiSkSurface.d.ts +0 -1
  51. package/lib/commonjs/skia/web/JsiSkSurface.js +0 -4
  52. package/lib/commonjs/skia/web/JsiSkSurface.js.map +1 -1
  53. package/lib/commonjs/skia/web/JsiSkSurfaceFactory.d.ts +2 -2
  54. package/lib/commonjs/skia/web/JsiSkSurfaceFactory.js +1 -1
  55. package/lib/commonjs/skia/web/JsiSkSurfaceFactory.js.map +1 -1
  56. package/lib/commonjs/skia/web/JsiSkia.js +0 -4
  57. package/lib/commonjs/skia/web/JsiSkia.js.map +1 -1
  58. package/lib/module/external/reanimated/index.d.ts +0 -1
  59. package/lib/module/external/reanimated/index.js +0 -1
  60. package/lib/module/external/reanimated/index.js.map +1 -1
  61. package/lib/module/mock/index.js +1 -2
  62. package/lib/module/mock/index.js.map +1 -1
  63. package/lib/module/skia/types/GPUTexture.d.ts +11 -0
  64. package/lib/module/skia/types/GPUTexture.js +2 -0
  65. package/lib/module/skia/types/GPUTexture.js.map +1 -0
  66. package/lib/module/skia/types/Image/Image.d.ts +0 -10
  67. package/lib/module/skia/types/Image/Image.js.map +1 -1
  68. package/lib/module/skia/types/Image/ImageFactory.d.ts +25 -48
  69. package/lib/module/skia/types/Image/ImageFactory.js.map +1 -1
  70. package/lib/module/skia/types/Skia.d.ts +0 -4
  71. package/lib/module/skia/types/Skia.js.map +1 -1
  72. package/lib/module/skia/types/Surface/Surface.d.ts +3 -14
  73. package/lib/module/skia/types/Surface/Surface.js.map +1 -1
  74. package/lib/module/skia/types/Surface/SurfaceFactory.d.ts +10 -9
  75. package/lib/module/skia/types/Surface/SurfaceFactory.js.map +1 -1
  76. package/lib/module/skia/types/index.d.ts +1 -2
  77. package/lib/module/skia/types/index.js +1 -2
  78. package/lib/module/skia/types/index.js.map +1 -1
  79. package/lib/module/skia/web/JsiSkImage.d.ts +0 -1
  80. package/lib/module/skia/web/JsiSkImage.js +0 -4
  81. package/lib/module/skia/web/JsiSkImage.js.map +1 -1
  82. package/lib/module/skia/web/JsiSkImageFactory.d.ts +4 -5
  83. package/lib/module/skia/web/JsiSkImageFactory.js +6 -10
  84. package/lib/module/skia/web/JsiSkImageFactory.js.map +1 -1
  85. package/lib/module/skia/web/JsiSkSurface.d.ts +0 -1
  86. package/lib/module/skia/web/JsiSkSurface.js +0 -4
  87. package/lib/module/skia/web/JsiSkSurface.js.map +1 -1
  88. package/lib/module/skia/web/JsiSkSurfaceFactory.d.ts +2 -2
  89. package/lib/module/skia/web/JsiSkSurfaceFactory.js +1 -1
  90. package/lib/module/skia/web/JsiSkSurfaceFactory.js.map +1 -1
  91. package/lib/module/skia/web/JsiSkia.js +0 -4
  92. package/lib/module/skia/web/JsiSkia.js.map +1 -1
  93. package/lib/typescript/src/external/reanimated/index.d.ts +0 -1
  94. package/lib/typescript/src/skia/types/GPUTexture.d.ts +11 -0
  95. package/lib/typescript/src/skia/types/Image/Image.d.ts +0 -10
  96. package/lib/typescript/src/skia/types/Image/ImageFactory.d.ts +25 -48
  97. package/lib/typescript/src/skia/types/Skia.d.ts +0 -4
  98. package/lib/typescript/src/skia/types/Surface/Surface.d.ts +3 -14
  99. package/lib/typescript/src/skia/types/Surface/SurfaceFactory.d.ts +10 -9
  100. package/lib/typescript/src/skia/types/index.d.ts +1 -2
  101. package/lib/typescript/src/skia/web/JsiSkImage.d.ts +0 -1
  102. package/lib/typescript/src/skia/web/JsiSkImageFactory.d.ts +4 -5
  103. package/lib/typescript/src/skia/web/JsiSkSurface.d.ts +0 -1
  104. package/lib/typescript/src/skia/web/JsiSkSurfaceFactory.d.ts +2 -2
  105. package/package.json +1 -1
  106. package/src/external/reanimated/index.ts +0 -1
  107. package/src/mock/index.ts +0 -1
  108. package/src/skia/types/GPUTexture.ts +9 -0
  109. package/src/skia/types/Image/Image.ts +0 -11
  110. package/src/skia/types/Image/ImageFactory.ts +25 -55
  111. package/src/skia/types/Skia.ts +0 -4
  112. package/src/skia/types/Surface/Surface.ts +3 -15
  113. package/src/skia/types/Surface/SurfaceFactory.ts +11 -9
  114. package/src/skia/types/index.ts +1 -2
  115. package/src/skia/web/JsiSkImage.ts +0 -5
  116. package/src/skia/web/JsiSkImageFactory.ts +16 -16
  117. package/src/skia/web/JsiSkSurface.ts +0 -5
  118. package/src/skia/web/JsiSkSurfaceFactory.ts +2 -2
  119. package/src/skia/web/JsiSkia.ts +0 -4
  120. package/android/cpp/rnskia-android/AHardwareBufferUtils.cpp +0 -31
  121. package/android/cpp/rnskia-android/AHardwareBufferUtils.h +0 -13
  122. package/android/cpp/rnskia-android/RNSkAndroidVideo.cpp +0 -200
  123. package/android/cpp/rnskia-android/RNSkAndroidVideo.h +0 -44
  124. package/android/src/main/java/com/reactnative/skia/RNSkVideo.java +0 -320
  125. package/apple/RNSkAppleVideo.h +0 -78
  126. package/apple/RNSkAppleVideo.mm +0 -292
  127. package/cpp/api/JsiNativeBuffer.h +0 -56
  128. package/cpp/api/JsiTextureInfo.h +0 -53
  129. package/cpp/api/JsiVideo.h +0 -101
  130. package/cpp/rnskia/RNSkVideo.h +0 -31
  131. package/lib/commonjs/external/reanimated/useVideo.d.ts +0 -21
  132. package/lib/commonjs/external/reanimated/useVideo.js +0 -150
  133. package/lib/commonjs/external/reanimated/useVideo.js.map +0 -1
  134. package/lib/commonjs/external/reanimated/useVideoLoading.d.ts +0 -4
  135. package/lib/commonjs/external/reanimated/useVideoLoading.js +0 -40
  136. package/lib/commonjs/external/reanimated/useVideoLoading.js.map +0 -1
  137. package/lib/commonjs/external/reanimated/useVideoLoading.web.d.ts +0 -4
  138. package/lib/commonjs/external/reanimated/useVideoLoading.web.js +0 -20
  139. package/lib/commonjs/external/reanimated/useVideoLoading.web.js.map +0 -1
  140. package/lib/commonjs/skia/types/NativeBuffer/NativeBufferFactory.d.ts +0 -29
  141. package/lib/commonjs/skia/types/NativeBuffer/NativeBufferFactory.js +0 -15
  142. package/lib/commonjs/skia/types/NativeBuffer/NativeBufferFactory.js.map +0 -1
  143. package/lib/commonjs/skia/types/NativeBuffer/index.d.ts +0 -1
  144. package/lib/commonjs/skia/types/NativeBuffer/index.js +0 -17
  145. package/lib/commonjs/skia/types/NativeBuffer/index.js.map +0 -1
  146. package/lib/commonjs/skia/types/Video/Video.d.ts +0 -20
  147. package/lib/commonjs/skia/types/Video/Video.js +0 -6
  148. package/lib/commonjs/skia/types/Video/Video.js.map +0 -1
  149. package/lib/commonjs/skia/types/Video/index.d.ts +0 -1
  150. package/lib/commonjs/skia/types/Video/index.js +0 -17
  151. package/lib/commonjs/skia/types/Video/index.js.map +0 -1
  152. package/lib/commonjs/skia/web/CanvasKitWebGLBufferImpl.d.ts +0 -9
  153. package/lib/commonjs/skia/web/CanvasKitWebGLBufferImpl.js +0 -30
  154. package/lib/commonjs/skia/web/CanvasKitWebGLBufferImpl.js.map +0 -1
  155. package/lib/commonjs/skia/web/JsiSkNativeBufferFactory.d.ts +0 -9
  156. package/lib/commonjs/skia/web/JsiSkNativeBufferFactory.js +0 -48
  157. package/lib/commonjs/skia/web/JsiSkNativeBufferFactory.js.map +0 -1
  158. package/lib/commonjs/skia/web/JsiVideo.d.ts +0 -28
  159. package/lib/commonjs/skia/web/JsiVideo.js +0 -96
  160. package/lib/commonjs/skia/web/JsiVideo.js.map +0 -1
  161. package/lib/module/external/reanimated/useVideo.d.ts +0 -21
  162. package/lib/module/external/reanimated/useVideo.js +0 -142
  163. package/lib/module/external/reanimated/useVideo.js.map +0 -1
  164. package/lib/module/external/reanimated/useVideoLoading.d.ts +0 -4
  165. package/lib/module/external/reanimated/useVideoLoading.js +0 -33
  166. package/lib/module/external/reanimated/useVideoLoading.js.map +0 -1
  167. package/lib/module/external/reanimated/useVideoLoading.web.d.ts +0 -4
  168. package/lib/module/external/reanimated/useVideoLoading.web.js +0 -13
  169. package/lib/module/external/reanimated/useVideoLoading.web.js.map +0 -1
  170. package/lib/module/skia/types/NativeBuffer/NativeBufferFactory.d.ts +0 -29
  171. package/lib/module/skia/types/NativeBuffer/NativeBufferFactory.js +0 -5
  172. package/lib/module/skia/types/NativeBuffer/NativeBufferFactory.js.map +0 -1
  173. package/lib/module/skia/types/NativeBuffer/index.d.ts +0 -1
  174. package/lib/module/skia/types/NativeBuffer/index.js +0 -2
  175. package/lib/module/skia/types/NativeBuffer/index.js.map +0 -1
  176. package/lib/module/skia/types/Video/Video.d.ts +0 -20
  177. package/lib/module/skia/types/Video/Video.js +0 -2
  178. package/lib/module/skia/types/Video/Video.js.map +0 -1
  179. package/lib/module/skia/types/Video/index.d.ts +0 -1
  180. package/lib/module/skia/types/Video/index.js +0 -2
  181. package/lib/module/skia/types/Video/index.js.map +0 -1
  182. package/lib/module/skia/web/CanvasKitWebGLBufferImpl.d.ts +0 -9
  183. package/lib/module/skia/web/CanvasKitWebGLBufferImpl.js +0 -23
  184. package/lib/module/skia/web/CanvasKitWebGLBufferImpl.js.map +0 -1
  185. package/lib/module/skia/web/JsiSkNativeBufferFactory.d.ts +0 -9
  186. package/lib/module/skia/web/JsiSkNativeBufferFactory.js +0 -41
  187. package/lib/module/skia/web/JsiSkNativeBufferFactory.js.map +0 -1
  188. package/lib/module/skia/web/JsiVideo.d.ts +0 -28
  189. package/lib/module/skia/web/JsiVideo.js +0 -88
  190. package/lib/module/skia/web/JsiVideo.js.map +0 -1
  191. package/lib/typescript/src/external/reanimated/useVideo.d.ts +0 -21
  192. package/lib/typescript/src/external/reanimated/useVideoLoading.d.ts +0 -4
  193. package/lib/typescript/src/external/reanimated/useVideoLoading.web.d.ts +0 -4
  194. package/lib/typescript/src/skia/types/NativeBuffer/NativeBufferFactory.d.ts +0 -29
  195. package/lib/typescript/src/skia/types/NativeBuffer/index.d.ts +0 -1
  196. package/lib/typescript/src/skia/types/Video/Video.d.ts +0 -20
  197. package/lib/typescript/src/skia/types/Video/index.d.ts +0 -1
  198. package/lib/typescript/src/skia/web/CanvasKitWebGLBufferImpl.d.ts +0 -9
  199. package/lib/typescript/src/skia/web/JsiSkNativeBufferFactory.d.ts +0 -9
  200. package/lib/typescript/src/skia/web/JsiVideo.d.ts +0 -28
  201. package/src/external/reanimated/useVideo.ts +0 -161
  202. package/src/external/reanimated/useVideoLoading.ts +0 -39
  203. package/src/external/reanimated/useVideoLoading.web.ts +0 -17
  204. package/src/skia/types/NativeBuffer/NativeBufferFactory.ts +0 -52
  205. package/src/skia/types/NativeBuffer/index.ts +0 -1
  206. package/src/skia/types/Video/Video.ts +0 -19
  207. package/src/skia/types/Video/index.ts +0 -1
  208. package/src/skia/web/CanvasKitWebGLBufferImpl.ts +0 -25
  209. package/src/skia/web/JsiSkNativeBufferFactory.ts +0 -51
  210. package/src/skia/web/JsiVideo.ts +0 -113
@@ -60,8 +60,6 @@ add_library(
60
60
 
61
61
  "${PROJECT_SOURCE_DIR}/cpp/jni/JniPlatformContext.cpp"
62
62
  "${PROJECT_SOURCE_DIR}/cpp/rnskia-android/RNSkAndroidCanvasProvider.cpp"
63
- "${PROJECT_SOURCE_DIR}/cpp/rnskia-android/AHardwareBufferUtils.cpp"
64
- "${PROJECT_SOURCE_DIR}/cpp/rnskia-android/RNSkAndroidVideo.cpp"
65
63
 
66
64
  "${PROJECT_SOURCE_DIR}/../cpp/jsi/JSICache.cpp"
67
65
  "${PROJECT_SOURCE_DIR}/../cpp/jsi/JsiPromises.cpp"
@@ -147,7 +147,7 @@ logger.warn("react-native-skia: buildDir: ${buildDir}")
147
147
  logger.warn("react-native-skia: node_modules: ${nodeModules}")
148
148
 
149
149
  android {
150
- namespace "com.reactnative.skia"
150
+ namespace = "com.reactnative.skia"
151
151
 
152
152
  compileSdkVersion safeExtGet('compileSdkVersion', DEFAULT_COMPILE_SDK_VERSION)
153
153
  buildToolsVersion safeExtGet('buildToolsVersion', DEFAULT_BUILD_TOOLS_VERSION)
@@ -155,10 +155,10 @@ android {
155
155
  // Used to override the NDK path/version on internal CI or by allowing
156
156
  // users to customize the NDK path/version from their root project.
157
157
  if (rootProject.hasProperty("ndkPath")) {
158
- ndkPath rootProject.ext.ndkPath
158
+ ndkPath = rootProject.ext.ndkPath
159
159
  }
160
160
  if (rootProject.hasProperty("ndkVersion")) {
161
- ndkVersion rootProject.ext.ndkVersion
161
+ ndkVersion = rootProject.ext.ndkVersion
162
162
  }
163
163
 
164
164
  defaultConfig {
@@ -181,8 +181,15 @@ android {
181
181
  }
182
182
  }
183
183
  }
184
+ // The Java sources use switch expressions (Java 14+). React Native's Gradle
185
+ // plugin aligns every module on 17 from the app's plugin block, but a host
186
+ // that opts out of that alignment must still compile this library.
187
+ compileOptions {
188
+ sourceCompatibility = JavaVersion.VERSION_17
189
+ targetCompatibility = JavaVersion.VERSION_17
190
+ }
184
191
  lintOptions {
185
- abortOnError false
192
+ abortOnError = false
186
193
  }
187
194
 
188
195
  publishing {
@@ -214,12 +221,12 @@ android {
214
221
  }
215
222
 
216
223
  buildFeatures {
217
- prefab true
218
- prefabPublishing true
224
+ prefab = true
225
+ prefabPublishing = true
219
226
  }
220
227
  prefab {
221
228
  rnskia {
222
- headers "${project.buildDir}/headers/rnskia/"
229
+ headers = "${project.buildDir}/headers/rnskia/"
223
230
  }
224
231
  }
225
232
  }
@@ -238,6 +245,7 @@ repositories {
238
245
  dependencies {
239
246
  //noinspection GradleDynamicVersion
240
247
  implementation 'com.facebook.react:react-native:+' // From node_modules
248
+ testImplementation 'junit:junit:4.13.2'
241
249
  }
242
250
 
243
251
  // Package all the cpp code in a flattened directory structure
@@ -73,30 +73,6 @@ TSelf JniPlatformContext::initHybrid(jni::alias_ref<jhybridobject> jThis,
73
73
  return makeCxxInstance(jThis, pixelDensity);
74
74
  }
75
75
 
76
- jni::global_ref<jobject>
77
- JniPlatformContext::createVideo(const std::string &url) {
78
- jni::Environment::ensureCurrentThreadIsAttached();
79
-
80
- jni::ThreadScope ts; // Manages JNI thread attachment/detachment
81
-
82
- // Get the JNI environment
83
- JNIEnv *env = facebook::jni::Environment::current();
84
-
85
- // Convert std::string to jstring
86
- jstring jUrl = env->NewStringUTF(url.c_str());
87
-
88
- static auto method =
89
- javaPart_->getClass()->getMethod<jobject(jstring)>("createVideo");
90
-
91
- // Call the method and receive a local reference to the video object
92
- auto videoObject = method(javaPart_.get(), jUrl);
93
- env->DeleteLocalRef(jUrl);
94
-
95
- // Clean up the jstring local reference
96
- auto result = jni::make_global(videoObject);
97
- return result;
98
- }
99
-
100
76
  sk_sp<SkImage> JniPlatformContext::takeScreenshotFromViewTag(size_t tag) {
101
77
  // Call the java method for creating a view screenshot as a bitmap:
102
78
  auto env = jni::Environment::current();
@@ -44,8 +44,6 @@ public:
44
44
 
45
45
  sk_sp<SkImage> takeScreenshotFromViewTag(size_t tag);
46
46
 
47
- jni::global_ref<jobject> createVideo(const std::string &url);
48
-
49
47
  private:
50
48
  friend HybridBase;
51
49
  jni::global_ref<JniPlatformContext::javaobject> javaPart_;
@@ -1,10 +1,5 @@
1
1
  #pragma once
2
2
 
3
- #if __ANDROID_API__ >= 26
4
- #include <android/hardware_buffer.h>
5
- #endif
6
- #include <algorithm>
7
- #include <cstdint>
8
3
  #include <exception>
9
4
  #include <functional>
10
5
  #include <memory>
@@ -12,9 +7,7 @@
12
7
 
13
8
  #include "RNDawnContext.h"
14
9
 
15
- #include "AHardwareBufferUtils.h"
16
10
  #include "JniPlatformContext.h"
17
- #include "RNSkAndroidVideo.h"
18
11
  #include "RNSkPlatformContext.h"
19
12
 
20
13
  #pragma clang diagnostic push
@@ -54,139 +47,6 @@ public:
54
47
  useP3ColorSpace);
55
48
  }
56
49
 
57
- sk_sp<SkImage> makeImageFromNativeBuffer(void *buffer) override {
58
- return DawnContext::getInstance().MakeImageFromBuffer(buffer);
59
- }
60
-
61
- std::shared_ptr<RNSkVideo> createVideo(const std::string &url) override {
62
- auto jniVideo = _jniPlatformContext->createVideo(url);
63
- return std::make_shared<RNSkAndroidVideo>(jniVideo);
64
- }
65
-
66
- void releaseNativeBuffer(uint64_t pointer) override {
67
- #if __ANDROID_API__ >= 26
68
- auto *buffer = reinterpret_cast<AHardwareBuffer *>(pointer);
69
- AHardwareBuffer_release(buffer);
70
- #endif
71
- }
72
-
73
- uint64_t makeNativeBuffer(sk_sp<SkImage> image) override {
74
- #if __ANDROID_API__ >= 26
75
- // A Graphite GPU texture can't be read with readPixels(nullptr); read it
76
- // back to a raster image first or the buffer ends up uninitialized/black.
77
- if (image && image->isTextureBacked()) {
78
- image = DawnContext::getInstance().MakeRasterImage(image);
79
- }
80
- auto bytesPerPixel = image->imageInfo().bytesPerPixel();
81
- int bytesPerRow = image->width() * bytesPerPixel;
82
- auto buf = SkData::MakeUninitialized(image->width() * image->height() *
83
- bytesPerPixel);
84
- SkImageInfo info =
85
- SkImageInfo::Make(image->width(), image->height(), image->colorType(),
86
- image->alphaType());
87
- image->readPixels(nullptr, info, const_cast<void *>(buf->data()),
88
- bytesPerRow, 0, 0);
89
- const void *pixelData = buf->data();
90
-
91
- // Define the buffer description
92
- AHardwareBuffer_Desc desc = {};
93
- // TODO: use image info here
94
- desc.width = image->width();
95
- desc.height = image->height();
96
- desc.layers = 1; // Single image layer
97
- desc.format = GetBufferFormatFromSkColorType(
98
- image->colorType()); // Assuming the image
99
- // is in this format
100
- desc.usage = AHARDWAREBUFFER_USAGE_CPU_READ_OFTEN |
101
- AHARDWAREBUFFER_USAGE_CPU_WRITE_OFTEN |
102
- AHARDWAREBUFFER_USAGE_GPU_COLOR_OUTPUT |
103
- AHARDWAREBUFFER_USAGE_GPU_SAMPLED_IMAGE;
104
- desc.stride = bytesPerRow; // Stride in pixels, not in bytes
105
-
106
- // Allocate the buffer
107
- AHardwareBuffer *buffer = nullptr;
108
- if (AHardwareBuffer_allocate(&desc, &buffer) != 0) {
109
- // Handle allocation failure
110
- return 0;
111
- }
112
-
113
- // Map the buffer to gain access to its memory
114
- void *mappedBuffer = nullptr;
115
- AHardwareBuffer_lock(buffer, AHARDWAREBUFFER_USAGE_CPU_WRITE_OFTEN, -1,
116
- nullptr, &mappedBuffer);
117
- if (mappedBuffer == nullptr) {
118
- // Handle mapping failure
119
- AHardwareBuffer_release(buffer);
120
- return 0;
121
- }
122
-
123
- // Copy the image data to the buffer
124
- memcpy(mappedBuffer, pixelData, desc.height * bytesPerRow);
125
-
126
- // Unmap the buffer
127
- AHardwareBuffer_unlock(buffer, nullptr);
128
-
129
- // Return the buffer pointer as a uint64_t. It's the caller's responsibility
130
- // to manage this buffer.
131
- return reinterpret_cast<uint64_t>(buffer);
132
- #else
133
- return 0;
134
- #endif
135
- }
136
-
137
- uint64_t makeTestNativeBuffer(int width, int height) override {
138
- #if __ANDROID_API__ >= 26
139
- // Allocate an RGBA8 AHardwareBuffer and fill it with a procedural test
140
- // pattern (RGB gradient + diagonal stripes), entirely on the CPU. We read
141
- // the buffer's actual row stride after locking (the allocator may pad it),
142
- // so the upload is correct regardless of width alignment.
143
- AHardwareBuffer_Desc desc = {};
144
- desc.width = static_cast<uint32_t>(width);
145
- desc.height = static_cast<uint32_t>(height);
146
- desc.layers = 1;
147
- desc.format = AHARDWAREBUFFER_FORMAT_R8G8B8A8_UNORM;
148
- desc.usage = AHARDWAREBUFFER_USAGE_CPU_WRITE_RARELY |
149
- AHARDWAREBUFFER_USAGE_CPU_READ_RARELY |
150
- AHARDWAREBUFFER_USAGE_GPU_SAMPLED_IMAGE;
151
-
152
- AHardwareBuffer *buffer = nullptr;
153
- if (AHardwareBuffer_allocate(&desc, &buffer) != 0) {
154
- return 0;
155
- }
156
-
157
- AHardwareBuffer_Desc allocated = {};
158
- AHardwareBuffer_describe(buffer, &allocated);
159
- const size_t rowBytes = static_cast<size_t>(allocated.stride) * 4;
160
-
161
- void *mappedBuffer = nullptr;
162
- AHardwareBuffer_lock(buffer, AHARDWAREBUFFER_USAGE_CPU_WRITE_RARELY, -1,
163
- nullptr, &mappedBuffer);
164
- if (mappedBuffer == nullptr) {
165
- AHardwareBuffer_release(buffer);
166
- return 0;
167
- }
168
-
169
- auto *base = static_cast<uint8_t *>(mappedBuffer);
170
- for (int y = 0; y < height; ++y) {
171
- uint8_t *row = base + y * rowBytes;
172
- for (int x = 0; x < width; ++x) {
173
- uint8_t r = static_cast<uint8_t>((x * 255) / std::max(width - 1, 1));
174
- uint8_t g = static_cast<uint8_t>((y * 255) / std::max(height - 1, 1));
175
- uint8_t b = static_cast<uint8_t>(((x + y) & 0x20) ? 220 : 30);
176
- row[x * 4 + 0] = r; // RGBA byte order
177
- row[x * 4 + 1] = g;
178
- row[x * 4 + 2] = b;
179
- row[x * 4 + 3] = 0xFF;
180
- }
181
- }
182
-
183
- AHardwareBuffer_unlock(buffer, nullptr);
184
- return reinterpret_cast<uint64_t>(buffer);
185
- #else
186
- return 0;
187
- #endif
188
- }
189
-
190
50
  sk_sp<SkFontMgr> createFontMgr() override {
191
51
  return SkFontMgr_New_Android(nullptr, SkFontScanner_Make_FreeType());
192
52
  }
@@ -0,0 +1,24 @@
1
+ package com.reactnative.skia;
2
+
3
+ import androidx.annotation.Nullable;
4
+
5
+ /** The Android view a SkiaView draws into, see SkiaView.updateView(). */
6
+ enum BackingViewKind {
7
+ SURFACE_VIEW,
8
+ TEXTURE_VIEW;
9
+
10
+ /**
11
+ * The kind the androidSurfaceType prop asks for, or null for "auto", which
12
+ * leaves the choice to the opaque prop.
13
+ */
14
+ @Nullable
15
+ static BackingViewKind fromSurfaceType(@Nullable String surfaceType) {
16
+ if ("SurfaceView".equals(surfaceType)) {
17
+ return SURFACE_VIEW;
18
+ }
19
+ if ("TextureView".equals(surfaceType)) {
20
+ return TEXTURE_VIEW;
21
+ }
22
+ return null;
23
+ }
24
+ }
@@ -0,0 +1,104 @@
1
+ package com.reactnative.skia;
2
+
3
+ import androidx.annotation.Nullable;
4
+
5
+ /**
6
+ * Decides when a SkiaView presents the recordings queued for it: a SurfaceView
7
+ * on the next vsync, a TextureView behind the draw its window has pending, so
8
+ * that the window has taken the previous frame by then. Keeps at most one
9
+ * frame callback and one posted present outstanding. Main thread.
10
+ */
11
+ final class FrameScheduler {
12
+ /** What the scheduler asks of the view. */
13
+ interface Host {
14
+ /** Calls onFrame() on the next Choreographer frame. */
15
+ void postFrameCallback();
16
+
17
+ /** Calls onPosted() from the main looper, behind any draw the window has pending. */
18
+ void postBehindPendingDraw();
19
+
20
+ /** Presents the queued recordings, returning whether any are left. */
21
+ boolean presentFrame();
22
+ }
23
+
24
+ private final Host mHost;
25
+ private boolean mFrameCallbackPosted = false;
26
+ private boolean mPresentPosted = false;
27
+
28
+ FrameScheduler(Host host) {
29
+ mHost = host;
30
+ }
31
+
32
+ /** A recording was submitted. Without a backing view there is no surface to present on yet. */
33
+ void requestFrame(@Nullable BackingViewKind kind) {
34
+ if (kind == null) {
35
+ return;
36
+ }
37
+ // A frame callback still outstanding (a retry, see presentOrRetry) presents
38
+ // the new recording along with the leftovers on that vsync.
39
+ if (mFrameCallbackPosted) {
40
+ return;
41
+ }
42
+ if (presentsOnVsync(kind)) {
43
+ postFrameCallback();
44
+ } else {
45
+ postBehindPendingDraw();
46
+ }
47
+ }
48
+
49
+ /** The Choreographer frame asked for with Host.postFrameCallback(). */
50
+ void onFrame(@Nullable BackingViewKind kind) {
51
+ mFrameCallbackPosted = false;
52
+ if (kind == null) {
53
+ return;
54
+ }
55
+ if (presentsOnVsync(kind)) {
56
+ presentOrRetry();
57
+ } else {
58
+ postBehindPendingDraw();
59
+ }
60
+ }
61
+
62
+ /** The message posted with Host.postBehindPendingDraw(). */
63
+ void onPosted() {
64
+ mPresentPosted = false;
65
+ presentOrRetry();
66
+ }
67
+
68
+ /** The view left its window, and the host removed both callbacks. */
69
+ void cancel() {
70
+ mFrameCallbackPosted = false;
71
+ mPresentPosted = false;
72
+ }
73
+
74
+ // The compositor takes a SurfaceView's buffer at the vsync. A TextureView's frame
75
+ // shows when its window draws, and its buffer queue replaces a frame not drawn yet.
76
+ private static boolean presentsOnVsync(BackingViewKind kind) {
77
+ return switch (kind) {
78
+ case SURFACE_VIEW -> true;
79
+ case TEXTURE_VIEW -> false;
80
+ };
81
+ }
82
+
83
+ // Recordings left over (the present failed, or more were submitted meanwhile)
84
+ // are tried again on the next vsync, never straight away.
85
+ private void presentOrRetry() {
86
+ if (mHost.presentFrame()) {
87
+ postFrameCallback();
88
+ }
89
+ }
90
+
91
+ private void postFrameCallback() {
92
+ if (!mFrameCallbackPosted) {
93
+ mFrameCallbackPosted = true;
94
+ mHost.postFrameCallback();
95
+ }
96
+ }
97
+
98
+ private void postBehindPendingDraw() {
99
+ if (!mPresentPosted) {
100
+ mPresentPosted = true;
101
+ mHost.postBehindPendingDraw();
102
+ }
103
+ }
104
+ }
@@ -32,11 +32,6 @@ public class PlatformContext {
32
32
  mHybridData = initHybrid(reactContext.getResources().getDisplayMetrics().density);
33
33
  }
34
34
 
35
- @DoNotStrip
36
- public Object createVideo(String url) {
37
- return new RNSkVideo(mContext, url);
38
- }
39
-
40
35
  private byte[] getStreamAsBytes(InputStream is) throws IOException {
41
36
  ByteArrayOutputStream buffer = new ByteArrayOutputStream();
42
37
  int nRead;
@@ -8,6 +8,8 @@ import android.view.MotionEvent;
8
8
  import android.view.Surface;
9
9
  import android.view.View;
10
10
 
11
+ import androidx.annotation.Nullable;
12
+
11
13
  import com.facebook.jni.HybridData;
12
14
  import com.facebook.jni.annotations.DoNotStrip;
13
15
  import com.facebook.react.bridge.ReactContext;
@@ -17,14 +19,10 @@ import com.facebook.react.views.view.ReactViewGroup;
17
19
  /**
18
20
  * The Android view behind <Canvas>, <SkiaPictureView> and <SkiaGraphiteView>.
19
21
  * It is backed by a SurfaceView or a TextureView (see updateView()) that the
20
- * native side draws into with Graphite, presenting the queued recordings on
21
- * the Choreographer.
22
+ * native side draws into with Graphite, presenting the queued recordings when
23
+ * the backing view can show them (see FrameScheduler).
22
24
  */
23
25
  public class SkiaView extends ReactViewGroup implements SkiaViewAPI, Choreographer.FrameCallback {
24
- // Backing view kinds, see updateView().
25
- private static final int KIND_SURFACE_VIEW = 0;
26
- private static final int KIND_TEXTURE_VIEW = 1;
27
-
28
26
  private static final String TAG = "SkiaView";
29
27
 
30
28
  @DoNotStrip
@@ -32,18 +30,36 @@ public class SkiaView extends ReactViewGroup implements SkiaViewAPI, Choreograph
32
30
 
33
31
  private View mView;
34
32
 
35
- // Props, applied together in updateView().
33
+ // Props, applied together in updateView(). A null kind is "auto".
36
34
  private boolean mOpaque = false;
37
- private String mSurfaceType = "auto";
35
+ @Nullable
36
+ private BackingViewKind mRequestedKind = null;
38
37
  private boolean mZOrderOnTop = false;
39
38
  private boolean mHighBitDepth = false;
40
39
 
41
- // What the current backing view was created with.
42
- private int mAppliedKind = -1;
40
+ // What the current backing view was created with; no kind before the first one.
41
+ @Nullable
42
+ private BackingViewKind mAppliedKind = null;
43
43
  private boolean mAppliedZOrderOnTop;
44
44
  private boolean mAppliedHighBitDepth;
45
45
 
46
- private boolean mFramePending = false;
46
+ private final Runnable mPostedPresent = this::onPostedPresent;
47
+ private final FrameScheduler mFrameScheduler = new FrameScheduler(new FrameScheduler.Host() {
48
+ @Override
49
+ public void postFrameCallback() {
50
+ Choreographer.getInstance().postFrameCallback(SkiaView.this);
51
+ }
52
+
53
+ @Override
54
+ public void postBehindPendingDraw() {
55
+ post(mPostedPresent);
56
+ }
57
+
58
+ @Override
59
+ public boolean presentFrame() {
60
+ return SkiaView.this.presentFrame();
61
+ }
62
+ });
47
63
 
48
64
  public SkiaView(Context context) {
49
65
  super(context);
@@ -65,8 +81,8 @@ public class SkiaView extends ReactViewGroup implements SkiaViewAPI, Choreograph
65
81
  mOpaque = value;
66
82
  }
67
83
 
68
- public void setSurfaceType(String value) {
69
- mSurfaceType = value == null ? "auto" : value;
84
+ public void setSurfaceType(@Nullable String value) {
85
+ mRequestedKind = BackingViewKind.fromSurfaceType(value);
70
86
  }
71
87
 
72
88
  public void setZOrderOnTop(boolean value) {
@@ -79,25 +95,22 @@ public class SkiaView extends ReactViewGroup implements SkiaViewAPI, Choreograph
79
95
 
80
96
  // Resolve the backing view from the props. "auto" picks SurfaceView for an
81
97
  // opaque canvas and TextureView for a non-opaque one.
82
- private int resolveKind() {
83
- if ("SurfaceView".equals(mSurfaceType)) {
84
- return KIND_SURFACE_VIEW;
98
+ private BackingViewKind resolveKind() {
99
+ if (mRequestedKind != null) {
100
+ return mRequestedKind;
85
101
  }
86
- if ("TextureView".equals(mSurfaceType)) {
87
- return KIND_TEXTURE_VIEW;
88
- }
89
- return mOpaque ? KIND_SURFACE_VIEW : KIND_TEXTURE_VIEW;
102
+ return mOpaque ? BackingViewKind.SURFACE_VIEW : BackingViewKind.TEXTURE_VIEW;
90
103
  }
91
104
 
92
105
  // The 10-bit buffer format only has 2 bits of alpha, which would visibly
93
106
  // break translucency, and the extra precision would be lost in the 8-bit
94
107
  // composition pass of a TextureView anyway. So the flag only applies to an
95
108
  // opaque SurfaceView.
96
- private boolean resolveHighBitDepth(int kind) {
109
+ private boolean resolveHighBitDepth(BackingViewKind kind) {
97
110
  if (!mHighBitDepth) {
98
111
  return false;
99
112
  }
100
- if (kind != KIND_SURFACE_VIEW || !mOpaque) {
113
+ if (kind != BackingViewKind.SURFACE_VIEW || !mOpaque) {
101
114
  Log.w(TAG, "highBitDepth requires an opaque SurfaceView on Android, falling back to the 8-bit format");
102
115
  return false;
103
116
  }
@@ -109,8 +122,8 @@ public class SkiaView extends ReactViewGroup implements SkiaViewAPI, Choreograph
109
122
  // it attaches (zOrderOnTop, the buffer format), replaces the child; opacity
110
123
  // is applied in place.
111
124
  void updateView() {
112
- int kind = resolveKind();
113
- boolean zOrderOnTop = kind == KIND_SURFACE_VIEW && mZOrderOnTop;
125
+ BackingViewKind kind = resolveKind();
126
+ boolean zOrderOnTop = kind == BackingViewKind.SURFACE_VIEW && mZOrderOnTop;
114
127
  boolean highBitDepth = resolveHighBitDepth(kind);
115
128
  if (mView == null
116
129
  || kind != mAppliedKind
@@ -122,9 +135,10 @@ public class SkiaView extends ReactViewGroup implements SkiaViewAPI, Choreograph
122
135
  mAppliedKind = kind;
123
136
  mAppliedZOrderOnTop = zOrderOnTop;
124
137
  mAppliedHighBitDepth = highBitDepth;
125
- mView = kind == KIND_SURFACE_VIEW
126
- ? new SkiaSurfaceView(getContext(), this, zOrderOnTop, mOpaque)
127
- : new SkiaTextureView(getContext(), this, mOpaque);
138
+ mView = switch (kind) {
139
+ case SURFACE_VIEW -> new SkiaSurfaceView(getContext(), this, zOrderOnTop, mOpaque);
140
+ case TEXTURE_VIEW -> new SkiaTextureView(getContext(), this, mOpaque);
141
+ };
128
142
  addView(mView);
129
143
  // React Native sizes native children explicitly through onLayout, so
130
144
  // the requestLayout triggered by addView is ignored; size the new
@@ -132,10 +146,11 @@ public class SkiaView extends ReactViewGroup implements SkiaViewAPI, Choreograph
132
146
  if (getWidth() > 0 || getHeight() > 0) {
133
147
  mView.layout(0, 0, getWidth(), getHeight());
134
148
  }
135
- } else if (kind == KIND_SURFACE_VIEW) {
136
- ((SkiaSurfaceView) mView).setOpaque(mOpaque);
137
149
  } else {
138
- ((SkiaTextureView) mView).setOpaque(mOpaque);
150
+ switch (kind) {
151
+ case SURFACE_VIEW -> ((SkiaSurfaceView) mView).setOpaque(mOpaque);
152
+ case TEXTURE_VIEW -> ((SkiaTextureView) mView).setOpaque(mOpaque);
153
+ }
139
154
  }
140
155
  }
141
156
 
@@ -157,31 +172,27 @@ public class SkiaView extends ReactViewGroup implements SkiaViewAPI, Choreograph
157
172
 
158
173
  // Frames --------------------------------------------------------------
159
174
 
160
- /**
161
- * Presents the queued recordings on the next vsync. Main thread; called
162
- * from native when a recording is submitted.
163
- */
175
+ /** A recording was submitted. Main thread; called from native. */
164
176
  @DoNotStrip
165
177
  public void scheduleFrame() {
166
- if (!mFramePending) {
167
- mFramePending = true;
168
- Choreographer.getInstance().postFrameCallback(this);
169
- }
178
+ mFrameScheduler.requestFrame(mAppliedKind);
170
179
  }
171
180
 
172
181
  @Override
173
182
  public void doFrame(long frameTimeNanos) {
174
- mFramePending = false;
175
- if (presentFrame()) {
176
- scheduleFrame();
177
- }
183
+ mFrameScheduler.onFrame(mAppliedKind);
184
+ }
185
+
186
+ private void onPostedPresent() {
187
+ mFrameScheduler.onPosted();
178
188
  }
179
189
 
180
190
  @Override
181
191
  protected void onDetachedFromWindow() {
182
192
  super.onDetachedFromWindow();
183
193
  Choreographer.getInstance().removeFrameCallback(this);
184
- mFramePending = false;
194
+ removeCallbacks(mPostedPresent);
195
+ mFrameScheduler.cancel();
185
196
  }
186
197
 
187
198
  @Override
@@ -242,6 +253,6 @@ public class SkiaView extends ReactViewGroup implements SkiaViewAPI, Choreograph
242
253
 
243
254
  private native void unregisterView();
244
255
 
245
- /** Choreographer tick: returns whether more recordings are waiting. */
256
+ /** Presents the queued recordings, returning whether any are left. */
246
257
  private native boolean presentFrame();
247
258
  }