@shopify/react-native-skia 1.5.9 → 1.6.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 (101) hide show
  1. package/android/cpp/jni/include/JniSkiaBaseView.h +6 -4
  2. package/android/cpp/jni/include/JniSkiaDomView.h +6 -4
  3. package/android/cpp/jni/include/JniSkiaPictureView.h +6 -4
  4. package/android/cpp/rnskia-android/MainThreadDispatcher.h +5 -0
  5. package/android/cpp/rnskia-android/OpenGLContext.h +37 -10
  6. package/android/cpp/rnskia-android/OpenGLWindowContext.cpp +0 -1
  7. package/android/cpp/rnskia-android/RNSkAndroidView.h +10 -9
  8. package/android/cpp/rnskia-android/RNSkOpenGLCanvasProvider.cpp +42 -36
  9. package/android/cpp/rnskia-android/RNSkOpenGLCanvasProvider.h +2 -2
  10. package/android/src/main/java/com/shopify/reactnative/skia/SkiaAHBView.java +113 -0
  11. package/android/src/main/java/com/shopify/reactnative/skia/SkiaBaseView.java +45 -54
  12. package/android/src/main/java/com/shopify/reactnative/skia/SkiaBaseViewManager.java +5 -0
  13. package/android/src/main/java/com/shopify/reactnative/skia/SkiaDomView.java +2 -2
  14. package/android/src/main/java/com/shopify/reactnative/skia/SkiaPictureView.java +2 -2
  15. package/android/src/main/java/com/shopify/reactnative/skia/SkiaSurfaceView.java +42 -0
  16. package/android/src/main/java/com/shopify/reactnative/skia/SkiaTextureView.java +90 -0
  17. package/android/src/main/java/com/shopify/reactnative/skia/SkiaViewAPI.java +16 -0
  18. package/android/src/paper/java/com/facebook/react/viewmanagers/SkiaDomViewManagerDelegate.java +3 -0
  19. package/android/src/paper/java/com/facebook/react/viewmanagers/SkiaDomViewManagerInterface.java +1 -0
  20. package/android/src/paper/java/com/facebook/react/viewmanagers/SkiaPictureViewManagerDelegate.java +3 -1
  21. package/android/src/paper/java/com/facebook/react/viewmanagers/SkiaPictureViewManagerInterface.java +1 -0
  22. package/cpp/rnskia/RNSkDomView.cpp +0 -20
  23. package/cpp/rnskia/RNSkDomView.h +0 -2
  24. package/cpp/rnskia/RNSkPictureView.h +5 -12
  25. package/cpp/rnskia/RNSkPlatformContext.h +1 -2
  26. package/cpp/rnskia/RNSkView.h +13 -24
  27. package/ios/RNSkia-iOS/SkiaCVPixelBufferUtils.mm +4 -8
  28. package/ios/RNSkia-iOS/SkiaDomViewManager.mm +5 -0
  29. package/ios/RNSkia-iOS/SkiaPictureView.mm +1 -0
  30. package/ios/RNSkia-iOS/SkiaPictureViewManager.mm +5 -0
  31. package/ios/RNSkia-iOS/SkiaUIView.h +1 -0
  32. package/ios/RNSkia-iOS/SkiaUIView.mm +5 -0
  33. package/lib/commonjs/skia/types/Image/ColorType.d.ts +21 -0
  34. package/lib/commonjs/skia/types/Image/ColorType.js +29 -0
  35. package/lib/commonjs/skia/types/Image/ColorType.js.map +1 -0
  36. package/lib/commonjs/skia/types/Image/ColorType.web.d.ts +19 -0
  37. package/lib/commonjs/skia/types/Image/ColorType.web.js +27 -0
  38. package/lib/commonjs/skia/types/Image/ColorType.web.js.map +1 -0
  39. package/lib/commonjs/skia/types/Image/ImageFactory.d.ts +1 -19
  40. package/lib/commonjs/skia/types/Image/ImageFactory.js +1 -21
  41. package/lib/commonjs/skia/types/Image/ImageFactory.js.map +1 -1
  42. package/lib/commonjs/skia/types/Image/index.d.ts +1 -0
  43. package/lib/commonjs/skia/types/Image/index.js +11 -0
  44. package/lib/commonjs/skia/types/Image/index.js.map +1 -1
  45. package/lib/commonjs/specs/SkiaDomViewNativeComponent.d.ts +0 -1
  46. package/lib/commonjs/specs/SkiaDomViewNativeComponent.js.map +1 -1
  47. package/lib/commonjs/specs/SkiaPictureViewNativeComponent.d.ts +1 -0
  48. package/lib/commonjs/specs/SkiaPictureViewNativeComponent.js.map +1 -1
  49. package/lib/commonjs/views/SkiaDomView.js +3 -1
  50. package/lib/commonjs/views/SkiaDomView.js.map +1 -1
  51. package/lib/commonjs/views/SkiaPictureView.js +5 -1
  52. package/lib/commonjs/views/SkiaPictureView.js.map +1 -1
  53. package/lib/commonjs/views/types.d.ts +2 -0
  54. package/lib/commonjs/views/types.js.map +1 -1
  55. package/lib/module/skia/types/Image/ColorType.d.ts +21 -0
  56. package/lib/module/skia/types/Image/ColorType.js +23 -0
  57. package/lib/module/skia/types/Image/ColorType.js.map +1 -0
  58. package/lib/module/skia/types/Image/ColorType.web.d.ts +19 -0
  59. package/lib/module/skia/types/Image/ColorType.web.js +21 -0
  60. package/lib/module/skia/types/Image/ColorType.web.js.map +1 -0
  61. package/lib/module/skia/types/Image/ImageFactory.d.ts +1 -19
  62. package/lib/module/skia/types/Image/ImageFactory.js +0 -20
  63. package/lib/module/skia/types/Image/ImageFactory.js.map +1 -1
  64. package/lib/module/skia/types/Image/index.d.ts +1 -0
  65. package/lib/module/skia/types/Image/index.js +1 -0
  66. package/lib/module/skia/types/Image/index.js.map +1 -1
  67. package/lib/module/specs/SkiaDomViewNativeComponent.d.ts +0 -1
  68. package/lib/module/specs/SkiaDomViewNativeComponent.js.map +1 -1
  69. package/lib/module/specs/SkiaPictureViewNativeComponent.d.ts +1 -0
  70. package/lib/module/specs/SkiaPictureViewNativeComponent.js.map +1 -1
  71. package/lib/module/views/SkiaDomView.js +3 -1
  72. package/lib/module/views/SkiaDomView.js.map +1 -1
  73. package/lib/module/views/SkiaPictureView.js +5 -1
  74. package/lib/module/views/SkiaPictureView.js.map +1 -1
  75. package/lib/module/views/types.d.ts +2 -0
  76. package/lib/module/views/types.js.map +1 -1
  77. package/lib/typescript/lib/commonjs/skia/types/Image/ColorType.d.ts +2 -0
  78. package/lib/typescript/lib/commonjs/skia/types/Image/ColorType.web.d.ts +2 -0
  79. package/lib/typescript/lib/commonjs/skia/types/Image/ImageFactory.d.ts +0 -1
  80. package/lib/typescript/lib/module/skia/types/Image/ColorType.d.ts +1 -0
  81. package/lib/typescript/lib/module/skia/types/Image/ColorType.web.d.ts +1 -0
  82. package/lib/typescript/lib/module/skia/types/Image/ImageFactory.d.ts +0 -1
  83. package/lib/typescript/lib/module/skia/types/Image/index.d.ts +1 -0
  84. package/lib/typescript/src/skia/types/Image/ColorType.d.ts +21 -0
  85. package/lib/typescript/src/skia/types/Image/ColorType.web.d.ts +19 -0
  86. package/lib/typescript/src/skia/types/Image/ImageFactory.d.ts +1 -19
  87. package/lib/typescript/src/skia/types/Image/index.d.ts +1 -0
  88. package/lib/typescript/src/specs/SkiaDomViewNativeComponent.d.ts +0 -1
  89. package/lib/typescript/src/specs/SkiaPictureViewNativeComponent.d.ts +1 -0
  90. package/lib/typescript/src/views/types.d.ts +2 -0
  91. package/package.json +1 -1
  92. package/src/skia/__tests__/Enums.spec.ts +2 -2
  93. package/src/skia/types/Image/ColorType.ts +21 -0
  94. package/src/skia/types/Image/ColorType.web.ts +19 -0
  95. package/src/skia/types/Image/ImageFactory.ts +1 -20
  96. package/src/skia/types/Image/index.ts +1 -0
  97. package/src/specs/SkiaDomViewNativeComponent.ts +0 -1
  98. package/src/specs/SkiaPictureViewNativeComponent.ts +1 -0
  99. package/src/views/SkiaDomView.tsx +2 -1
  100. package/src/views/SkiaPictureView.tsx +4 -1
  101. package/src/views/types.ts +3 -0
@@ -29,12 +29,14 @@ public:
29
29
  }
30
30
 
31
31
  protected:
32
- virtual void surfaceAvailable(jobject surface, int width, int height) {
33
- _skiaAndroidView->surfaceAvailable(surface, width, height);
32
+ virtual void surfaceAvailable(jobject surface, int width, int height,
33
+ bool opaque) {
34
+ _skiaAndroidView->surfaceAvailable(surface, width, height, opaque);
34
35
  }
35
36
 
36
- virtual void surfaceSizeChanged(jobject surface, int width, int height) {
37
- _skiaAndroidView->surfaceSizeChanged(surface, width, height);
37
+ virtual void surfaceSizeChanged(jobject surface, int width, int height,
38
+ bool opaque) {
39
+ _skiaAndroidView->surfaceSizeChanged(surface, width, height, opaque);
38
40
  }
39
41
 
40
42
  virtual void surfaceDestroyed() { _skiaAndroidView->surfaceDestroyed(); }
@@ -46,12 +46,14 @@ public:
46
46
  }
47
47
 
48
48
  protected:
49
- void surfaceAvailable(jobject surface, int width, int height) override {
50
- JniSkiaBaseView::surfaceAvailable(surface, width, height);
49
+ void surfaceAvailable(jobject surface, int width, int height,
50
+ bool opaque) override {
51
+ JniSkiaBaseView::surfaceAvailable(surface, width, height, opaque);
51
52
  }
52
53
 
53
- void surfaceSizeChanged(jobject surface, int width, int height) override {
54
- JniSkiaBaseView::surfaceSizeChanged(surface, width, height);
54
+ void surfaceSizeChanged(jobject surface, int width, int height,
55
+ bool opaque) override {
56
+ JniSkiaBaseView::surfaceSizeChanged(surface, width, height, opaque);
55
57
  }
56
58
 
57
59
  void surfaceDestroyed() override { JniSkiaBaseView::surfaceDestroyed(); }
@@ -48,12 +48,14 @@ public:
48
48
  }
49
49
 
50
50
  protected:
51
- void surfaceAvailable(jobject surface, int width, int height) override {
52
- JniSkiaBaseView::surfaceAvailable(surface, width, height);
51
+ void surfaceAvailable(jobject surface, int width, int height,
52
+ bool opaque) override {
53
+ JniSkiaBaseView::surfaceAvailable(surface, width, height, opaque);
53
54
  }
54
55
 
55
- void surfaceSizeChanged(jobject surface, int width, int height) override {
56
- JniSkiaBaseView::surfaceSizeChanged(surface, width, height);
56
+ void surfaceSizeChanged(jobject surface, int width, int height,
57
+ bool opaque) override {
58
+ JniSkiaBaseView::surfaceSizeChanged(surface, width, height, opaque);
57
59
  }
58
60
 
59
61
  void surfaceDestroyed() override { JniSkiaBaseView::surfaceDestroyed(); }
@@ -2,6 +2,7 @@
2
2
 
3
3
  #include <android/looper.h>
4
4
  #include <unistd.h>
5
+ #include <queue>
5
6
 
6
7
  class MainThreadDispatcher {
7
8
  private:
@@ -27,6 +28,10 @@ public:
27
28
  return instance;
28
29
  }
29
30
 
31
+ bool isOnMainThread() {
32
+ return ALooper_forThread() == mainLooper;
33
+ }
34
+
30
35
  void post(std::function<void()> task) {
31
36
  // TODO: this is disabled for now but we can clean this up
32
37
  // if (ALooper_forThread() == mainLooper) {
@@ -16,6 +16,30 @@
16
16
 
17
17
  namespace RNSkia {
18
18
 
19
+ class OpenGLSharedContext {
20
+ public:
21
+ OpenGLSharedContext(const OpenGLSharedContext &) = delete;
22
+ OpenGLSharedContext &operator=(const OpenGLSharedContext &) = delete;
23
+
24
+ static OpenGLSharedContext &getInstance() {
25
+ static OpenGLSharedContext instance;
26
+ return instance;
27
+ }
28
+
29
+ gl::Display *getDisplay() { return _glDisplay.get(); }
30
+ gl::Context *getContext() { return _glContext.get(); }
31
+
32
+ private:
33
+ std::unique_ptr<gl::Display> _glDisplay;
34
+ std::unique_ptr<gl::Context> _glContext;
35
+
36
+ OpenGLSharedContext() {
37
+ _glDisplay = std::make_unique<gl::Display>();
38
+ auto glConfig = _glDisplay->chooseConfig();
39
+ _glContext = _glDisplay->makeContext(glConfig, nullptr);
40
+ }
41
+ };
42
+
19
43
  class OpenGLContext {
20
44
  public:
21
45
  friend class OpenGLWindowContext;
@@ -39,8 +63,11 @@ public:
39
63
  }
40
64
 
41
65
  // Create texture
66
+ auto GL_RGBA8 = 0x8058;
67
+ auto format = GrBackendFormats::MakeGL(GL_RGBA8, GL_TEXTURE_2D);
42
68
  auto texture = _directContext->createBackendTexture(
43
- width, height, colorType, skgpu::Mipmapped::kNo, GrRenderable::kYes);
69
+ width, height, format, SkColors::kTransparent, skgpu::Mipmapped::kNo,
70
+ GrRenderable::kYes);
44
71
 
45
72
  if (!texture.isValid()) {
46
73
  RNSkLogger::logToConsole("couldn't create offscreen texture %dx%d", width,
@@ -128,24 +155,24 @@ public:
128
155
  // TODO: remove width, height
129
156
  std::unique_ptr<WindowContext> MakeWindow(ANativeWindow *window, int width,
130
157
  int height) {
131
- return std::make_unique<OpenGLWindowContext>(
132
- _directContext.get(), _glDisplay.get(), _glContext.get(), window);
158
+ auto display = OpenGLSharedContext::getInstance().getDisplay();
159
+ return std::make_unique<OpenGLWindowContext>(_directContext.get(), display,
160
+ _glContext.get(), window);
133
161
  }
134
162
 
135
163
  GrDirectContext *getDirectContext() { return _directContext.get(); }
136
164
 
137
165
  private:
138
- EGLConfig _glConfig;
139
- std::unique_ptr<gl::Display> _glDisplay;
140
166
  std::unique_ptr<gl::Context> _glContext;
141
167
  std::unique_ptr<gl::Surface> _glSurface;
142
168
  sk_sp<GrDirectContext> _directContext;
143
169
 
144
170
  OpenGLContext() {
145
- _glDisplay = std::make_unique<gl::Display>();
146
- _glConfig = _glDisplay->chooseConfig();
147
- _glContext = _glDisplay->makeContext(_glConfig, nullptr);
148
- _glSurface = _glDisplay->makePixelBufferSurface(_glConfig, 1, 1);
171
+ auto display = OpenGLSharedContext::getInstance().getDisplay();
172
+ auto sharedContext = OpenGLSharedContext::getInstance().getContext();
173
+ auto glConfig = display->chooseConfig();
174
+ _glContext = display->makeContext(glConfig, sharedContext);
175
+ _glSurface = display->makePixelBufferSurface(glConfig, 1, 1);
149
176
  _glContext->makeCurrent(_glSurface.get());
150
177
  auto backendInterface = GrGLMakeNativeInterface();
151
178
  _directContext = GrDirectContexts::MakeGL(backendInterface);
@@ -156,4 +183,4 @@ private:
156
183
  }
157
184
  };
158
185
 
159
- } // namespace RNSkia
186
+ } // namespace RNSkia
@@ -53,7 +53,6 @@ sk_sp<SkSurface> OpenGLWindowContext::getSurface() {
53
53
 
54
54
  void OpenGLWindowContext::present() {
55
55
  _glContext->makeCurrent(_glSurface.get());
56
- // TODO: is flushAndSubmit needed here?
57
56
  _directContext->flushAndSubmit();
58
57
  _glSurface->present();
59
58
  }
@@ -11,11 +11,13 @@ namespace RNSkia {
11
11
 
12
12
  class RNSkBaseAndroidView {
13
13
  public:
14
- virtual void surfaceAvailable(jobject surface, int width, int height) = 0;
14
+ virtual void surfaceAvailable(jobject surface, int width, int height,
15
+ bool opaque) = 0;
15
16
 
16
17
  virtual void surfaceDestroyed() = 0;
17
18
 
18
- virtual void surfaceSizeChanged(jobject surface, int width, int height) = 0;
19
+ virtual void surfaceSizeChanged(jobject surface, int width, int height,
20
+ bool opaque) = 0;
19
21
 
20
22
  virtual float getPixelDensity() = 0;
21
23
 
@@ -34,12 +36,10 @@ public:
34
36
  std::make_shared<RNSkOpenGLCanvasProvider>(
35
37
  std::bind(&RNSkia::RNSkView::requestRedraw, this), context)) {}
36
38
 
37
- void surfaceAvailable(jobject surface, int width, int height) override {
39
+ void surfaceAvailable(jobject surface, int width, int height,
40
+ bool opaque) override {
38
41
  std::static_pointer_cast<RNSkOpenGLCanvasProvider>(T::getCanvasProvider())
39
- ->surfaceAvailable(surface, width, height);
40
-
41
- // Try to render directly when the surface has been set so that
42
- // we don't have to wait until the draw loop returns.
42
+ ->surfaceAvailable(surface, width, height, opaque);
43
43
  RNSkView::redraw();
44
44
  }
45
45
 
@@ -48,9 +48,10 @@ public:
48
48
  ->surfaceDestroyed();
49
49
  }
50
50
 
51
- void surfaceSizeChanged(jobject surface, int width, int height) override {
51
+ void surfaceSizeChanged(jobject surface, int width, int height,
52
+ bool opaque) override {
52
53
  std::static_pointer_cast<RNSkOpenGLCanvasProvider>(T::getCanvasProvider())
53
- ->surfaceSizeChanged(surface, width, height);
54
+ ->surfaceSizeChanged(surface, width, height, opaque);
54
55
  // This is only need for the first time to frame, this renderImmediate call
55
56
  // will invoke updateTexImage for the previous frame
56
57
  RNSkView::redraw();
@@ -46,22 +46,24 @@ float RNSkOpenGLCanvasProvider::getScaledHeight() {
46
46
 
47
47
  bool RNSkOpenGLCanvasProvider::renderToCanvas(
48
48
  const std::function<void(SkCanvas *)> &cb) {
49
- JNIEnv *env = facebook::jni::Environment::current();
50
49
  if (_surfaceHolder != nullptr && cb != nullptr) {
51
50
  // Get the surface
52
51
  auto surface = _surfaceHolder->getSurface();
53
- env->CallVoidMethod(_jSurfaceTexture, _updateTexImageMethod);
54
-
55
- // Check for exceptions
56
- if (env->ExceptionCheck()) {
57
- RNSkLogger::logToConsole("updateAndRelease() failed. The exception above "
58
- "can safely be ignored");
59
- env->ExceptionClear();
52
+ if (_jSurfaceTexture) {
53
+ JNIEnv *env = facebook::jni::Environment::current();
54
+ env->CallVoidMethod(_jSurfaceTexture, _updateTexImageMethod);
55
+
56
+ // Check for exceptions
57
+ if (env->ExceptionCheck()) {
58
+ RNSkLogger::logToConsole(
59
+ "updateAndRelease() failed. The exception above "
60
+ "can safely be ignored");
61
+ env->ExceptionClear();
62
+ }
60
63
  }
61
64
  if (surface) {
62
65
  // Draw into canvas using callback
63
66
  cb(surface->getCanvas());
64
-
65
67
  // Swap buffers and show on screen
66
68
  _surfaceHolder->present();
67
69
  return true;
@@ -74,32 +76,36 @@ bool RNSkOpenGLCanvasProvider::renderToCanvas(
74
76
  }
75
77
 
76
78
  void RNSkOpenGLCanvasProvider::surfaceAvailable(jobject jSurfaceTexture,
77
- int width, int height) {
78
- // If the surface is 0, we can skip it
79
- if (width == 0 && height == 0) {
80
- return;
81
- }
79
+ int width, int height,
80
+ bool opaque) {
81
+ // Release the old surface
82
+ _surfaceHolder = nullptr;
83
+
82
84
  // Create renderer!
85
+ ANativeWindow *window = nullptr;
83
86
  JNIEnv *env = facebook::jni::Environment::current();
84
-
85
- _jSurfaceTexture = env->NewGlobalRef(jSurfaceTexture);
86
- jclass surfaceClass = env->FindClass("android/view/Surface");
87
- jmethodID surfaceConstructor = env->GetMethodID(
88
- surfaceClass, "<init>", "(Landroid/graphics/SurfaceTexture;)V");
89
- // Create a new Surface instance
90
- jobject jSurface =
91
- env->NewObject(surfaceClass, surfaceConstructor, jSurfaceTexture);
92
-
93
- jclass surfaceTextureClass = env->GetObjectClass(_jSurfaceTexture);
94
- _updateTexImageMethod =
95
- env->GetMethodID(surfaceTextureClass, "updateTexImage", "()V");
96
-
97
- // Acquire the native window from the Surface
98
- auto window = ANativeWindow_fromSurface(env, jSurface);
99
- // Clean up local references
100
- env->DeleteLocalRef(jSurface);
101
- env->DeleteLocalRef(surfaceClass);
102
- env->DeleteLocalRef(surfaceTextureClass);
87
+ if (!opaque) {
88
+ _jSurfaceTexture = env->NewGlobalRef(jSurfaceTexture);
89
+ jclass surfaceClass = env->FindClass("android/view/Surface");
90
+ jmethodID surfaceConstructor = env->GetMethodID(
91
+ surfaceClass, "<init>", "(Landroid/graphics/SurfaceTexture;)V");
92
+ // Create a new Surface instance
93
+ auto jSurface =
94
+ env->NewObject(surfaceClass, surfaceConstructor, jSurfaceTexture);
95
+ window = ANativeWindow_fromSurface(env, jSurface);
96
+
97
+ jclass surfaceTextureClass = env->GetObjectClass(_jSurfaceTexture);
98
+ _updateTexImageMethod =
99
+ env->GetMethodID(surfaceTextureClass, "updateTexImage", "()V");
100
+
101
+ // Acquire the native window from the Surface
102
+ // Clean up local references
103
+ env->DeleteLocalRef(jSurface);
104
+ env->DeleteLocalRef(surfaceClass);
105
+ env->DeleteLocalRef(surfaceTextureClass);
106
+ } else {
107
+ window = ANativeWindow_fromSurface(env, jSurfaceTexture);
108
+ }
103
109
  #if defined(SK_GRAPHITE)
104
110
  _surfaceHolder = DawnContext::getInstance().MakeWindow(window, width, height);
105
111
  #else
@@ -121,8 +127,8 @@ void RNSkOpenGLCanvasProvider::surfaceDestroyed() {
121
127
  }
122
128
  }
123
129
 
124
- void RNSkOpenGLCanvasProvider::surfaceSizeChanged(jobject jSurfaceTexture,
125
- int width, int height) {
130
+ void RNSkOpenGLCanvasProvider::surfaceSizeChanged(jobject jSurface, int width,
131
+ int height, bool opaque) {
126
132
  if (width == 0 && height == 0) {
127
133
  // Setting width/height to zero is nothing we need to care about when
128
134
  // it comes to invalidating the surface.
@@ -131,7 +137,7 @@ void RNSkOpenGLCanvasProvider::surfaceSizeChanged(jobject jSurfaceTexture,
131
137
 
132
138
  if (_surfaceHolder == nullptr) {
133
139
  _surfaceHolder = nullptr;
134
- surfaceAvailable(jSurfaceTexture, width, height);
140
+ surfaceAvailable(jSurface, width, height, opaque);
135
141
  } else {
136
142
  _surfaceHolder->resize(width, height);
137
143
  }
@@ -27,11 +27,11 @@ public:
27
27
 
28
28
  bool renderToCanvas(const std::function<void(SkCanvas *)> &cb) override;
29
29
 
30
- void surfaceAvailable(jobject surface, int width, int height);
30
+ void surfaceAvailable(jobject surface, int width, int height, bool opaque);
31
31
 
32
32
  void surfaceDestroyed();
33
33
 
34
- void surfaceSizeChanged(jobject jSurface, int width, int height);
34
+ void surfaceSizeChanged(jobject jSurface, int width, int height, bool opaque);
35
35
 
36
36
  private:
37
37
  std::unique_ptr<WindowContext> _surfaceHolder = nullptr;
@@ -0,0 +1,113 @@
1
+ package com.shopify.reactnative.skia;
2
+
3
+
4
+ import android.annotation.SuppressLint;
5
+ import android.content.Context;
6
+ import android.graphics.Bitmap;
7
+ import android.graphics.Canvas;
8
+ import android.graphics.Matrix;
9
+ import android.graphics.PixelFormat;
10
+ import android.hardware.HardwareBuffer;
11
+ import android.media.Image;
12
+ import android.media.ImageReader;
13
+ import android.os.Build;
14
+ import android.util.Log;
15
+ import android.view.View;
16
+
17
+ import androidx.annotation.NonNull;
18
+ import androidx.annotation.RequiresApi;
19
+
20
+ @SuppressLint("ViewConstructor")
21
+ @RequiresApi(api = Build.VERSION_CODES.Q)
22
+ public class SkiaAHBView extends View implements ImageReader.OnImageAvailableListener {
23
+
24
+ private ImageReader mReader;
25
+
26
+ private Bitmap mBitmap = null;
27
+
28
+ private final Matrix matrix = new Matrix();
29
+
30
+ SkiaViewAPI mApi;
31
+ boolean mDebug;
32
+
33
+ public SkiaAHBView(Context context, SkiaViewAPI api, boolean debug) {
34
+ super(context);
35
+ mApi = api;
36
+ mDebug = debug;
37
+ }
38
+
39
+ private ImageReader createReader() {
40
+ ImageReader reader = ImageReader.newInstance(getWidth(), getHeight(), PixelFormat.RGBA_8888, 2, HardwareBuffer.USAGE_GPU_SAMPLED_IMAGE |
41
+ HardwareBuffer.USAGE_GPU_COLOR_OUTPUT);
42
+ reader.setOnImageAvailableListener(this, null);
43
+ return reader;
44
+ }
45
+
46
+ @Override
47
+ protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
48
+ super.onLayout(changed, left, top, right, bottom);
49
+ int width = getWidth();
50
+ int height = getHeight();
51
+ if (mReader == null) {
52
+ mReader = createReader();
53
+ mApi.onSurfaceCreated(mReader.getSurface(), width, height);
54
+ } else {
55
+ mReader = createReader();
56
+ mApi.onSurfaceChanged(mReader.getSurface(), width, height);
57
+ }
58
+ }
59
+
60
+ @Override
61
+ public void onImageAvailable(ImageReader reader) {
62
+ try (Image image = reader.acquireLatestImage()) {
63
+ if (image != null) {
64
+ HardwareBuffer hb = image.getHardwareBuffer();
65
+ if (mDebug) {
66
+ textureUpdated(image.getTimestamp());
67
+ }
68
+ if (hb != null) {
69
+ Bitmap bitmap = Bitmap.wrapHardwareBuffer(hb, null);
70
+ if (bitmap != null) {
71
+ mBitmap = bitmap;
72
+ hb.close();
73
+ invalidate();
74
+ }
75
+ }
76
+ }
77
+ }
78
+ }
79
+
80
+ @Override
81
+ protected void onDraw(@NonNull Canvas canvas) {
82
+ super.onDraw(canvas);
83
+ if (mBitmap != null) {
84
+ float viewWidth = getWidth();
85
+ float viewHeight = getHeight();
86
+ float bitmapWidth = mBitmap.getWidth();
87
+ float bitmapHeight = mBitmap.getHeight();
88
+
89
+ // Calculate the scale factors
90
+ float scaleX = viewWidth / bitmapWidth;
91
+ float scaleY = viewHeight / bitmapHeight;
92
+
93
+ // Reset the matrix and apply scaling
94
+ matrix.reset();
95
+ matrix.setScale(scaleX, scaleY);
96
+
97
+ canvas.drawBitmap(mBitmap, matrix, null);
98
+ }
99
+ }
100
+
101
+ private long _prevTimestamp = 0;
102
+ public void textureUpdated(long ts) {
103
+ long frameDuration = (ts - _prevTimestamp)/1000000;
104
+ Log.i("SkiaAHBView", "onSurfaceTextureUpdated "+frameDuration+"ms");
105
+ _prevTimestamp = ts;
106
+ }
107
+
108
+ @Override
109
+ protected void onDetachedFromWindow() {
110
+ super.onDetachedFromWindow();
111
+ mApi.onSurfaceDestroyed();
112
+ }
113
+ }
@@ -3,97 +3,88 @@ package com.shopify.reactnative.skia;
3
3
  import android.content.Context;
4
4
  import android.graphics.SurfaceTexture;
5
5
  import android.util.Log;
6
- import android.view.TextureView;
6
+ import android.view.Surface;
7
+ import android.view.View;
7
8
 
8
9
  import com.facebook.react.views.view.ReactViewGroup;
9
10
 
10
- public abstract class SkiaBaseView extends ReactViewGroup implements TextureView.SurfaceTextureListener {
11
- private TextureView mTexture;
11
+ public abstract class SkiaBaseView extends ReactViewGroup implements SkiaViewAPI {
12
+ private View mView;
12
13
 
13
- private String tag = "SkiaView";
14
-
15
- private boolean isDropped = false;
14
+ private final boolean debug = false;
15
+ private final String tag = "SkiaView";
16
16
 
17
17
  public SkiaBaseView(Context context) {
18
18
  super(context);
19
- mTexture = new TextureView(context);
20
- mTexture.setSurfaceTextureListener(this);
21
- mTexture.setOpaque(false);
22
- addView(mTexture);
19
+ mView = new SkiaTextureView(context, this, debug);
20
+ addView(mView);
23
21
  }
24
22
 
25
- private void createSurfaceTexture() {
26
- // This API Level is >= 26, we created our own SurfaceTexture to have a faster time to first frame
27
- if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.O) {
28
- Log.i(tag, "Create SurfaceTexture");
29
- SurfaceTexture surface = new SurfaceTexture(false);
30
- mTexture.setSurfaceTexture(surface);
31
- this.onSurfaceTextureAvailable(surface, this.getMeasuredWidth(), this.getMeasuredHeight());
23
+ public void setOpaque(boolean value) {
24
+ if (value && mView instanceof SkiaTextureView) {
25
+ removeView(mView);
26
+ mView = new SkiaSurfaceView(getContext(), this, debug);
27
+ addView(mView);
28
+ } else if (!value && mView instanceof SkiaSurfaceView) {
29
+ removeView(mView);
30
+ mView = new SkiaTextureView(getContext(), this, debug);
31
+ addView(mView);
32
32
  }
33
33
  }
34
34
 
35
- void dropInstance() {
36
- isDropped = true;
37
- unregisterView();
38
- }
39
-
40
35
  @Override
41
36
  protected void onAttachedToWindow() {
42
37
  super.onAttachedToWindow();
43
- if (this.getMeasuredWidth() == 0) {
44
- createSurfaceTexture();
38
+ if (getMeasuredWidth() == 0) {
39
+ if (mView instanceof SkiaTextureView) {
40
+ ((SkiaTextureView) mView).createSurfaceTexture();
41
+ }
42
+ }
43
+ }
44
+
45
+ void dropInstance() {
46
+ if (mView instanceof SkiaTextureView) {
47
+ ((SkiaTextureView)mView).isDropped = true;
45
48
  }
49
+ unregisterView();
46
50
  }
47
51
 
48
52
  @Override
49
53
  protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
50
- Log.i(tag, "onLayout " + this.getMeasuredWidth() + "/" + this.getMeasuredHeight());
51
54
  super.onLayout(changed, left, top, right, bottom);
52
- mTexture.layout(0, 0, this.getMeasuredWidth(), this.getMeasuredHeight());
55
+ mView.layout(0, 0, right - left, bottom - top);
53
56
  }
54
57
 
55
58
  @Override
56
- public void onSurfaceTextureAvailable(SurfaceTexture surface, int width, int height) {
57
- Log.i(tag, "onSurfaceTextureAvailable " + width + "/" + height);
58
- surfaceAvailable(surface, width, height);
59
+ public void onSurfaceCreated(Surface surface, int width, int height) {
60
+ surfaceAvailable(surface, width, height, true);
59
61
  }
60
62
 
61
63
  @Override
62
- public void onSurfaceTextureSizeChanged(SurfaceTexture surface, int width, int height) {
63
- if (isDropped) {
64
- return;
65
- }
64
+ public void onSurfaceChanged(Surface surface, int width, int height) {
66
65
  Log.i(tag, "onSurfaceTextureSizeChanged " + width + "/" + height);
67
- surfaceSizeChanged(surface, width, height);
66
+ surfaceSizeChanged(surface, width, height, true);
68
67
  }
69
68
 
70
69
  @Override
71
- public boolean onSurfaceTextureDestroyed(SurfaceTexture surface) {
72
- Log.i(tag, "onSurfaceTextureDestroyed");
73
- // https://developer.android.com/reference/android/view/TextureView.SurfaceTextureListener#onSurfaceTextureDestroyed(android.graphics.SurfaceTexture)
74
- surfaceDestroyed();
75
- // Because of React Native Screens (which dettach the view), we always keep the surface alive.
76
- // If not, Texture view will recreate the texture surface by itself and
77
- // we will lose the fast first time to frame.
78
- // We only delete the surface when the view is dropped (destroySurface invoked by SkiaBaseViewManager);
79
- if (!isDropped) {
80
- createSurfaceTexture();
81
- }
82
- return false;
70
+ public void onSurfaceTextureCreated(SurfaceTexture surface, int width, int height) {
71
+ surfaceAvailable(surface, width, height, false);
83
72
  }
84
73
 
85
- private long _prevTimestamp = 0;
86
74
  @Override
87
- public void onSurfaceTextureUpdated(SurfaceTexture surface) {
88
- long timestamp = surface.getTimestamp();
89
- long frameDuration = (timestamp - _prevTimestamp)/1000000;
90
- Log.i(tag, "onSurfaceTextureUpdated "+frameDuration+"ms");
91
- _prevTimestamp = timestamp;
75
+ public void onSurfaceTextureChanged(SurfaceTexture surface, int width, int height) {
76
+ Log.i(tag, "onSurfaceTextureSizeChanged " + width + "/" + height);
77
+ surfaceSizeChanged(surface, width, height, false);
78
+ }
79
+
80
+ @Override
81
+ public void onSurfaceDestroyed() {
82
+ surfaceDestroyed();
92
83
  }
93
84
 
94
- protected abstract void surfaceAvailable(Object surface, int width, int height);
85
+ protected abstract void surfaceAvailable(Object surface, int width, int height, boolean opaque);
95
86
 
96
- protected abstract void surfaceSizeChanged(Object surface, int width, int height);
87
+ protected abstract void surfaceSizeChanged(Object surface, int width, int height, boolean opaque);
97
88
 
98
89
  protected abstract void surfaceDestroyed();
99
90
 
@@ -26,6 +26,11 @@ public abstract class SkiaBaseViewManager<T extends SkiaBaseView> extends ReactV
26
26
  ((SkiaBaseView)view).setDebugMode(show);
27
27
  }
28
28
 
29
+ @ReactProp(name = "opaque")
30
+ public void setOpaque(T view, boolean value) {
31
+ ((SkiaBaseView)view).setOpaque(value);
32
+ }
33
+
29
34
  @Override
30
35
  public void onDropViewInstance(@NonNull ReactViewGroup view) {
31
36
  super.onDropViewInstance(view);
@@ -25,9 +25,9 @@ public class SkiaDomView extends SkiaBaseView {
25
25
 
26
26
  private native HybridData initHybrid(SkiaManager skiaManager);
27
27
 
28
- protected native void surfaceAvailable(Object surface, int width, int height);
28
+ protected native void surfaceAvailable(Object surface, int width, int height, boolean opaque);
29
29
 
30
- protected native void surfaceSizeChanged(Object surface, int width, int height);
30
+ protected native void surfaceSizeChanged(Object surface, int width, int height, boolean opaque);
31
31
 
32
32
  protected native void surfaceDestroyed();
33
33
 
@@ -24,9 +24,9 @@ public class SkiaPictureView extends SkiaBaseView {
24
24
 
25
25
  private native HybridData initHybrid(SkiaManager skiaManager);
26
26
 
27
- protected native void surfaceAvailable(Object surface, int width, int height);
27
+ protected native void surfaceAvailable(Object surface, int width, int height, boolean opaque);
28
28
 
29
- protected native void surfaceSizeChanged(Object surface, int width, int height);
29
+ protected native void surfaceSizeChanged(Object surface, int width, int height, boolean opaque);
30
30
 
31
31
  protected native void surfaceDestroyed();
32
32