@shopify/react-native-skia 1.5.10 → 1.6.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (94) 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/RNSkView.h +3 -21
  26. package/ios/RNSkia-iOS/SkiaCVPixelBufferUtils.mm +4 -8
  27. package/ios/RNSkia-iOS/SkiaDomViewManager.mm +5 -0
  28. package/ios/RNSkia-iOS/SkiaPictureView.mm +1 -0
  29. package/ios/RNSkia-iOS/SkiaPictureViewManager.mm +5 -0
  30. package/ios/RNSkia-iOS/SkiaUIView.h +1 -0
  31. package/ios/RNSkia-iOS/SkiaUIView.mm +5 -0
  32. package/lib/commonjs/skia/types/Image/ColorType.d.ts +21 -0
  33. package/lib/commonjs/skia/types/Image/ColorType.js +29 -0
  34. package/lib/commonjs/skia/types/Image/ColorType.js.map +1 -0
  35. package/lib/commonjs/skia/types/Image/ColorType.web.d.ts +19 -0
  36. package/lib/commonjs/skia/types/Image/ColorType.web.js +27 -0
  37. package/lib/commonjs/skia/types/Image/ColorType.web.js.map +1 -0
  38. package/lib/commonjs/skia/types/Image/ImageFactory.d.ts +1 -19
  39. package/lib/commonjs/skia/types/Image/ImageFactory.js +1 -21
  40. package/lib/commonjs/skia/types/Image/ImageFactory.js.map +1 -1
  41. package/lib/commonjs/skia/types/Image/index.d.ts +1 -0
  42. package/lib/commonjs/skia/types/Image/index.js +11 -0
  43. package/lib/commonjs/skia/types/Image/index.js.map +1 -1
  44. package/lib/commonjs/specs/SkiaPictureViewNativeComponent.d.ts +1 -0
  45. package/lib/commonjs/specs/SkiaPictureViewNativeComponent.js.map +1 -1
  46. package/lib/commonjs/views/SkiaDomView.js +3 -1
  47. package/lib/commonjs/views/SkiaDomView.js.map +1 -1
  48. package/lib/commonjs/views/SkiaPictureView.js +5 -1
  49. package/lib/commonjs/views/SkiaPictureView.js.map +1 -1
  50. package/lib/commonjs/views/types.d.ts +2 -0
  51. package/lib/commonjs/views/types.js.map +1 -1
  52. package/lib/module/skia/types/Image/ColorType.d.ts +21 -0
  53. package/lib/module/skia/types/Image/ColorType.js +23 -0
  54. package/lib/module/skia/types/Image/ColorType.js.map +1 -0
  55. package/lib/module/skia/types/Image/ColorType.web.d.ts +19 -0
  56. package/lib/module/skia/types/Image/ColorType.web.js +21 -0
  57. package/lib/module/skia/types/Image/ColorType.web.js.map +1 -0
  58. package/lib/module/skia/types/Image/ImageFactory.d.ts +1 -19
  59. package/lib/module/skia/types/Image/ImageFactory.js +0 -20
  60. package/lib/module/skia/types/Image/ImageFactory.js.map +1 -1
  61. package/lib/module/skia/types/Image/index.d.ts +1 -0
  62. package/lib/module/skia/types/Image/index.js +1 -0
  63. package/lib/module/skia/types/Image/index.js.map +1 -1
  64. package/lib/module/specs/SkiaPictureViewNativeComponent.d.ts +1 -0
  65. package/lib/module/specs/SkiaPictureViewNativeComponent.js.map +1 -1
  66. package/lib/module/views/SkiaDomView.js +3 -1
  67. package/lib/module/views/SkiaDomView.js.map +1 -1
  68. package/lib/module/views/SkiaPictureView.js +5 -1
  69. package/lib/module/views/SkiaPictureView.js.map +1 -1
  70. package/lib/module/views/types.d.ts +2 -0
  71. package/lib/module/views/types.js.map +1 -1
  72. package/lib/typescript/lib/commonjs/skia/types/Image/ColorType.d.ts +2 -0
  73. package/lib/typescript/lib/commonjs/skia/types/Image/ColorType.web.d.ts +2 -0
  74. package/lib/typescript/lib/commonjs/skia/types/Image/ImageFactory.d.ts +0 -1
  75. package/lib/typescript/lib/module/skia/types/Image/ColorType.d.ts +1 -0
  76. package/lib/typescript/lib/module/skia/types/Image/ColorType.web.d.ts +1 -0
  77. package/lib/typescript/lib/module/skia/types/Image/ImageFactory.d.ts +0 -1
  78. package/lib/typescript/lib/module/skia/types/Image/index.d.ts +1 -0
  79. package/lib/typescript/src/skia/types/Image/ColorType.d.ts +21 -0
  80. package/lib/typescript/src/skia/types/Image/ColorType.web.d.ts +19 -0
  81. package/lib/typescript/src/skia/types/Image/ImageFactory.d.ts +1 -19
  82. package/lib/typescript/src/skia/types/Image/index.d.ts +1 -0
  83. package/lib/typescript/src/specs/SkiaPictureViewNativeComponent.d.ts +1 -0
  84. package/lib/typescript/src/views/types.d.ts +2 -0
  85. package/package.json +1 -1
  86. package/src/skia/__tests__/Enums.spec.ts +2 -2
  87. package/src/skia/types/Image/ColorType.ts +21 -0
  88. package/src/skia/types/Image/ColorType.web.ts +19 -0
  89. package/src/skia/types/Image/ImageFactory.ts +1 -20
  90. package/src/skia/types/Image/index.ts +1 -0
  91. package/src/specs/SkiaPictureViewNativeComponent.ts +1 -0
  92. package/src/views/SkiaDomView.tsx +2 -1
  93. package/src/views/SkiaPictureView.tsx +4 -1
  94. 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