@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.
- package/android/cpp/jni/include/JniSkiaBaseView.h +6 -4
- package/android/cpp/jni/include/JniSkiaDomView.h +6 -4
- package/android/cpp/jni/include/JniSkiaPictureView.h +6 -4
- package/android/cpp/rnskia-android/MainThreadDispatcher.h +5 -0
- package/android/cpp/rnskia-android/OpenGLContext.h +37 -10
- package/android/cpp/rnskia-android/OpenGLWindowContext.cpp +0 -1
- package/android/cpp/rnskia-android/RNSkAndroidView.h +10 -9
- package/android/cpp/rnskia-android/RNSkOpenGLCanvasProvider.cpp +42 -36
- package/android/cpp/rnskia-android/RNSkOpenGLCanvasProvider.h +2 -2
- package/android/src/main/java/com/shopify/reactnative/skia/SkiaAHBView.java +113 -0
- package/android/src/main/java/com/shopify/reactnative/skia/SkiaBaseView.java +45 -54
- package/android/src/main/java/com/shopify/reactnative/skia/SkiaBaseViewManager.java +5 -0
- package/android/src/main/java/com/shopify/reactnative/skia/SkiaDomView.java +2 -2
- package/android/src/main/java/com/shopify/reactnative/skia/SkiaPictureView.java +2 -2
- package/android/src/main/java/com/shopify/reactnative/skia/SkiaSurfaceView.java +42 -0
- package/android/src/main/java/com/shopify/reactnative/skia/SkiaTextureView.java +90 -0
- package/android/src/main/java/com/shopify/reactnative/skia/SkiaViewAPI.java +16 -0
- package/android/src/paper/java/com/facebook/react/viewmanagers/SkiaDomViewManagerDelegate.java +3 -0
- package/android/src/paper/java/com/facebook/react/viewmanagers/SkiaDomViewManagerInterface.java +1 -0
- package/android/src/paper/java/com/facebook/react/viewmanagers/SkiaPictureViewManagerDelegate.java +3 -1
- package/android/src/paper/java/com/facebook/react/viewmanagers/SkiaPictureViewManagerInterface.java +1 -0
- package/cpp/rnskia/RNSkDomView.cpp +0 -20
- package/cpp/rnskia/RNSkDomView.h +0 -2
- package/cpp/rnskia/RNSkPictureView.h +5 -12
- package/cpp/rnskia/RNSkView.h +3 -21
- package/ios/RNSkia-iOS/SkiaCVPixelBufferUtils.mm +4 -8
- package/ios/RNSkia-iOS/SkiaDomViewManager.mm +5 -0
- package/ios/RNSkia-iOS/SkiaPictureView.mm +1 -0
- package/ios/RNSkia-iOS/SkiaPictureViewManager.mm +5 -0
- package/ios/RNSkia-iOS/SkiaUIView.h +1 -0
- package/ios/RNSkia-iOS/SkiaUIView.mm +5 -0
- package/lib/commonjs/skia/types/Image/ColorType.d.ts +21 -0
- package/lib/commonjs/skia/types/Image/ColorType.js +29 -0
- package/lib/commonjs/skia/types/Image/ColorType.js.map +1 -0
- package/lib/commonjs/skia/types/Image/ColorType.web.d.ts +19 -0
- package/lib/commonjs/skia/types/Image/ColorType.web.js +27 -0
- package/lib/commonjs/skia/types/Image/ColorType.web.js.map +1 -0
- package/lib/commonjs/skia/types/Image/ImageFactory.d.ts +1 -19
- package/lib/commonjs/skia/types/Image/ImageFactory.js +1 -21
- package/lib/commonjs/skia/types/Image/ImageFactory.js.map +1 -1
- package/lib/commonjs/skia/types/Image/index.d.ts +1 -0
- package/lib/commonjs/skia/types/Image/index.js +11 -0
- package/lib/commonjs/skia/types/Image/index.js.map +1 -1
- package/lib/commonjs/specs/SkiaPictureViewNativeComponent.d.ts +1 -0
- package/lib/commonjs/specs/SkiaPictureViewNativeComponent.js.map +1 -1
- package/lib/commonjs/views/SkiaDomView.js +3 -1
- package/lib/commonjs/views/SkiaDomView.js.map +1 -1
- package/lib/commonjs/views/SkiaPictureView.js +5 -1
- package/lib/commonjs/views/SkiaPictureView.js.map +1 -1
- package/lib/commonjs/views/types.d.ts +2 -0
- package/lib/commonjs/views/types.js.map +1 -1
- package/lib/module/skia/types/Image/ColorType.d.ts +21 -0
- package/lib/module/skia/types/Image/ColorType.js +23 -0
- package/lib/module/skia/types/Image/ColorType.js.map +1 -0
- package/lib/module/skia/types/Image/ColorType.web.d.ts +19 -0
- package/lib/module/skia/types/Image/ColorType.web.js +21 -0
- package/lib/module/skia/types/Image/ColorType.web.js.map +1 -0
- package/lib/module/skia/types/Image/ImageFactory.d.ts +1 -19
- package/lib/module/skia/types/Image/ImageFactory.js +0 -20
- package/lib/module/skia/types/Image/ImageFactory.js.map +1 -1
- package/lib/module/skia/types/Image/index.d.ts +1 -0
- package/lib/module/skia/types/Image/index.js +1 -0
- package/lib/module/skia/types/Image/index.js.map +1 -1
- package/lib/module/specs/SkiaPictureViewNativeComponent.d.ts +1 -0
- package/lib/module/specs/SkiaPictureViewNativeComponent.js.map +1 -1
- package/lib/module/views/SkiaDomView.js +3 -1
- package/lib/module/views/SkiaDomView.js.map +1 -1
- package/lib/module/views/SkiaPictureView.js +5 -1
- package/lib/module/views/SkiaPictureView.js.map +1 -1
- package/lib/module/views/types.d.ts +2 -0
- package/lib/module/views/types.js.map +1 -1
- package/lib/typescript/lib/commonjs/skia/types/Image/ColorType.d.ts +2 -0
- package/lib/typescript/lib/commonjs/skia/types/Image/ColorType.web.d.ts +2 -0
- package/lib/typescript/lib/commonjs/skia/types/Image/ImageFactory.d.ts +0 -1
- package/lib/typescript/lib/module/skia/types/Image/ColorType.d.ts +1 -0
- package/lib/typescript/lib/module/skia/types/Image/ColorType.web.d.ts +1 -0
- package/lib/typescript/lib/module/skia/types/Image/ImageFactory.d.ts +0 -1
- package/lib/typescript/lib/module/skia/types/Image/index.d.ts +1 -0
- package/lib/typescript/src/skia/types/Image/ColorType.d.ts +21 -0
- package/lib/typescript/src/skia/types/Image/ColorType.web.d.ts +19 -0
- package/lib/typescript/src/skia/types/Image/ImageFactory.d.ts +1 -19
- package/lib/typescript/src/skia/types/Image/index.d.ts +1 -0
- package/lib/typescript/src/specs/SkiaPictureViewNativeComponent.d.ts +1 -0
- package/lib/typescript/src/views/types.d.ts +2 -0
- package/package.json +1 -1
- package/src/skia/__tests__/Enums.spec.ts +2 -2
- package/src/skia/types/Image/ColorType.ts +21 -0
- package/src/skia/types/Image/ColorType.web.ts +19 -0
- package/src/skia/types/Image/ImageFactory.ts +1 -20
- package/src/skia/types/Image/index.ts +1 -0
- package/src/specs/SkiaPictureViewNativeComponent.ts +1 -0
- package/src/views/SkiaDomView.tsx +2 -1
- package/src/views/SkiaPictureView.tsx +4 -1
- 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
|
-
|
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
|
-
|
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
|
50
|
-
|
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
|
54
|
-
|
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
|
52
|
-
|
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
|
56
|
-
|
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,
|
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
|
-
|
132
|
-
|
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
|
-
|
146
|
-
|
147
|
-
|
148
|
-
|
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
|
@@ -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
|
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
|
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
|
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
|
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
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
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
|
-
|
79
|
-
|
80
|
-
|
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
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
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
|
125
|
-
int
|
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(
|
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.
|
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
|
11
|
-
private
|
11
|
+
public abstract class SkiaBaseView extends ReactViewGroup implements SkiaViewAPI {
|
12
|
+
private View mView;
|
12
13
|
|
13
|
-
private
|
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
|
-
|
20
|
-
|
21
|
-
mTexture.setOpaque(false);
|
22
|
-
addView(mTexture);
|
19
|
+
mView = new SkiaTextureView(context, this, debug);
|
20
|
+
addView(mView);
|
23
21
|
}
|
24
22
|
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
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 (
|
44
|
-
|
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
|
-
|
55
|
+
mView.layout(0, 0, right - left, bottom - top);
|
53
56
|
}
|
54
57
|
|
55
58
|
@Override
|
56
|
-
public void
|
57
|
-
|
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
|
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
|
72
|
-
|
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
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
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
|
|