@shopify/react-native-skia 1.5.0 → 1.5.2

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 (51) hide show
  1. package/android/cpp/jni/include/JniSkiaBaseView.h +0 -1
  2. package/android/cpp/jni/include/JniSkiaPictureView.h +0 -1
  3. package/android/cpp/rnskia-android/OpenGLContext.h +40 -0
  4. package/android/cpp/rnskia-android/RNSkAndroidPlatformContext.h +5 -5
  5. package/android/cpp/rnskia-android/RNSkAndroidVideo.cpp +2 -2
  6. package/android/cpp/rnskia-android/RNSkOpenGLCanvasProvider.cpp +49 -14
  7. package/android/cpp/rnskia-android/RNSkOpenGLCanvasProvider.h +5 -2
  8. package/android/cpp/rnskia-android/SkiaOpenGLSurfaceFactory.cpp +19 -133
  9. package/android/cpp/rnskia-android/SkiaOpenGLSurfaceFactory.h +30 -138
  10. package/cpp/api/JsiSkTypefaceFontProvider.h +1 -1
  11. package/cpp/api/JsiSkiaContext.h +6 -3
  12. package/cpp/jsi/JsiValue.cpp +1 -2
  13. package/cpp/rnskia/RNSkPlatformContext.h +2 -2
  14. package/cpp/rnskia/{SkiaContext.h → WindowContext.h} +5 -2
  15. package/ios/RNSkia-iOS/DisplayLink.mm +7 -0
  16. package/ios/RNSkia-iOS/MetalContext.h +46 -0
  17. package/ios/RNSkia-iOS/MetalContext.mm +33 -0
  18. package/ios/RNSkia-iOS/RNSkMetalCanvasProvider.mm +8 -28
  19. package/ios/RNSkia-iOS/RNSkiOSPlatformContext.h +1 -1
  20. package/ios/RNSkia-iOS/RNSkiOSPlatformContext.mm +8 -9
  21. package/ios/RNSkia-iOS/RNSkiOSView.mm +0 -2
  22. package/ios/RNSkia-iOS/SkiaMetalSurfaceFactory.h +28 -32
  23. package/ios/RNSkia-iOS/SkiaMetalSurfaceFactory.mm +18 -60
  24. package/ios/RNSkia-iOS/SkiaUIView.h +0 -2
  25. package/ios/RNSkia-iOS/ViewScreenshotService.mm +1 -8
  26. package/lib/commonjs/web/WithSkiaWeb.js +4 -1
  27. package/lib/commonjs/web/WithSkiaWeb.js.map +1 -1
  28. package/lib/module/web/WithSkiaWeb.js +4 -1
  29. package/lib/module/web/WithSkiaWeb.js.map +1 -1
  30. package/libs/ios/libskia.xcframework/ios-arm64_arm64e/libskia.a +0 -0
  31. package/libs/ios/libskia.xcframework/ios-arm64_arm64e_x86_64-simulator/libskia.a +0 -0
  32. package/libs/ios/libskottie.xcframework/Info.plist +5 -5
  33. package/libs/ios/libskottie.xcframework/ios-arm64_arm64e/libskottie.a +0 -0
  34. package/libs/ios/libskottie.xcframework/ios-arm64_arm64e_x86_64-simulator/libskottie.a +0 -0
  35. package/libs/ios/libskparagraph.xcframework/Info.plist +5 -5
  36. package/libs/ios/libskparagraph.xcframework/ios-arm64_arm64e/libskparagraph.a +0 -0
  37. package/libs/ios/libskparagraph.xcframework/ios-arm64_arm64e_x86_64-simulator/libskparagraph.a +0 -0
  38. package/libs/ios/libsksg.xcframework/ios-arm64_arm64e/libsksg.a +0 -0
  39. package/libs/ios/libsksg.xcframework/ios-arm64_arm64e_x86_64-simulator/libsksg.a +0 -0
  40. package/libs/ios/libskshaper.xcframework/Info.plist +5 -5
  41. package/libs/ios/libskshaper.xcframework/ios-arm64_arm64e/libskshaper.a +0 -0
  42. package/libs/ios/libskshaper.xcframework/ios-arm64_arm64e_x86_64-simulator/libskshaper.a +0 -0
  43. package/libs/ios/libskunicode_core.xcframework/ios-arm64_arm64e/libskunicode_core.a +0 -0
  44. package/libs/ios/libskunicode_core.xcframework/ios-arm64_arm64e_x86_64-simulator/libskunicode_core.a +0 -0
  45. package/libs/ios/libskunicode_libgrapheme.xcframework/ios-arm64_arm64e/libskunicode_libgrapheme.a +0 -0
  46. package/libs/ios/libskunicode_libgrapheme.xcframework/ios-arm64_arm64e_x86_64-simulator/libskunicode_libgrapheme.a +0 -0
  47. package/libs/ios/libsvg.xcframework/Info.plist +5 -5
  48. package/libs/ios/libsvg.xcframework/ios-arm64_arm64e/libsvg.a +0 -0
  49. package/libs/ios/libsvg.xcframework/ios-arm64_arm64e_x86_64-simulator/libsvg.a +0 -0
  50. package/package.json +3 -6
  51. package/src/web/WithSkiaWeb.tsx +3 -1
@@ -29,7 +29,6 @@ public:
29
29
  }
30
30
 
31
31
  protected:
32
-
33
32
  virtual void surfaceAvailable(jobject surface, int width, int height) {
34
33
  _skiaAndroidView->surfaceAvailable(surface, width, height);
35
34
  }
@@ -49,7 +49,6 @@ public:
49
49
  }
50
50
 
51
51
  protected:
52
-
53
52
  void surfaceAvailable(jobject surface, int width, int height) override {
54
53
  JniSkiaBaseView::surfaceAvailable(surface, width, height);
55
54
  }
@@ -0,0 +1,40 @@
1
+ #pragma once
2
+
3
+ #include "SkiaOpenGLSurfaceFactory.h"
4
+ #include "WindowContext.h"
5
+
6
+ #include "include/core/SkSurface.h"
7
+
8
+ class OpenGLContext {
9
+ public:
10
+ OpenGLContext(const OpenGLContext &) = delete;
11
+ OpenGLContext &operator=(const OpenGLContext &) = delete;
12
+
13
+ static OpenGLContext &getInstance() {
14
+ static thread_local OpenGLContext instance;
15
+ return instance;
16
+ }
17
+
18
+ sk_sp<SkSurface> MakeOffscreen(int width, int height) {
19
+ return RNSkia::SkiaOpenGLSurfaceFactory::makeOffscreenSurface(
20
+ &_context, width, height);
21
+ }
22
+
23
+ sk_sp<SkImage> MakeImageFromBuffer(void *buffer) {
24
+ return RNSkia::SkiaOpenGLSurfaceFactory::makeImageFromHardwareBuffer(
25
+ &_context, buffer);
26
+ }
27
+
28
+ std::unique_ptr<RNSkia::WindowContext> MakeWindow(ANativeWindow *window,
29
+ int width, int height) {
30
+ return RNSkia::SkiaOpenGLSurfaceFactory::makeContext(&_context, window,
31
+ width, height);
32
+ }
33
+
34
+ private:
35
+ RNSkia::SkiaOpenGLContext _context;
36
+
37
+ OpenGLContext() {
38
+ RNSkia::SkiaOpenGLHelper::createSkiaDirectContextIfNecessary(&_context);
39
+ }
40
+ };
@@ -11,9 +11,9 @@
11
11
 
12
12
  #include "AHardwareBufferUtils.h"
13
13
  #include "JniPlatformContext.h"
14
+ #include "OpenGLContext.h"
14
15
  #include "RNSkAndroidVideo.h"
15
16
  #include "RNSkPlatformContext.h"
16
- #include "SkiaOpenGLSurfaceFactory.h"
17
17
 
18
18
  #pragma clang diagnostic push
19
19
  #pragma clang diagnostic ignored "-Wdocumentation"
@@ -51,17 +51,17 @@ public:
51
51
  }
52
52
 
53
53
  sk_sp<SkSurface> makeOffscreenSurface(int width, int height) override {
54
- return SkiaOpenGLSurfaceFactory::makeOffscreenSurface(width, height);
54
+ return OpenGLContext::getInstance().MakeOffscreen(width, height);
55
55
  }
56
56
 
57
- std::shared_ptr<SkiaContext>
57
+ std::shared_ptr<WindowContext>
58
58
  makeContextFromNativeSurface(void *surface, int width, int height) override {
59
- return SkiaOpenGLSurfaceFactory::makeContext(
59
+ return OpenGLContext::getInstance().MakeWindow(
60
60
  reinterpret_cast<ANativeWindow *>(surface), width, height);
61
61
  }
62
62
 
63
63
  sk_sp<SkImage> makeImageFromNativeBuffer(void *buffer) override {
64
- return SkiaOpenGLSurfaceFactory::makeImageFromHardwareBuffer(buffer);
64
+ return OpenGLContext::getInstance().MakeImageFromBuffer(buffer);
65
65
  }
66
66
 
67
67
  std::shared_ptr<RNSkVideo> createVideo(const std::string &url) override {
@@ -13,8 +13,8 @@
13
13
 
14
14
  #pragma clang diagnostic pop
15
15
 
16
+ #include "OpenGLContext.h"
16
17
  #include "RNSkAndroidVideo.h"
17
- #include "SkiaOpenGLSurfaceFactory.h"
18
18
 
19
19
  namespace RNSkia {
20
20
 
@@ -52,7 +52,7 @@ sk_sp<SkImage> RNSkAndroidVideo::nextImage(double *timeStamp) {
52
52
  // Convert jobject to AHardwareBuffer
53
53
  AHardwareBuffer *buffer =
54
54
  AHardwareBuffer_fromHardwareBuffer(env, jHardwareBuffer);
55
- return SkiaOpenGLSurfaceFactory::makeImageFromHardwareBuffer(buffer);
55
+ return OpenGLContext::getInstance().MakeImageFromBuffer(buffer);
56
56
  #else
57
57
  return nullptr;
58
58
  #endif
@@ -2,6 +2,8 @@
2
2
 
3
3
  #include <memory>
4
4
 
5
+ #include "OpenGLContext.h"
6
+
5
7
  #pragma clang diagnostic push
6
8
  #pragma clang diagnostic ignored "-Wdocumentation"
7
9
 
@@ -20,33 +22,41 @@ RNSkOpenGLCanvasProvider::RNSkOpenGLCanvasProvider(
20
22
  RNSkOpenGLCanvasProvider::~RNSkOpenGLCanvasProvider() {}
21
23
 
22
24
  float RNSkOpenGLCanvasProvider::getScaledWidth() {
23
- return _surfaceHolder ? _surfaceHolder->getWidth() : 0;
25
+ if (_surfaceHolder) {
26
+ return static_cast<float>(_surfaceHolder->getWidth());
27
+ }
28
+ return 0;
24
29
  }
25
30
 
26
31
  float RNSkOpenGLCanvasProvider::getScaledHeight() {
27
- return _surfaceHolder ? _surfaceHolder->getHeight() : 0;
32
+ if (_surfaceHolder) {
33
+ return static_cast<float>(_surfaceHolder->getHeight());
34
+ }
35
+ return 0;
28
36
  }
29
37
 
30
38
  bool RNSkOpenGLCanvasProvider::renderToCanvas(
31
39
  const std::function<void(SkCanvas *)> &cb) {
32
-
40
+ JNIEnv *env = facebook::jni::Environment::current();
33
41
  if (_surfaceHolder != nullptr && cb != nullptr) {
34
42
  // Get the surface
35
43
  auto surface = _surfaceHolder->getSurface();
36
- if (surface) {
37
-
38
- // Ensure we are ready to render
39
- if (!_surfaceHolder->makeCurrent()) {
40
- return false;
41
- }
42
- _surfaceHolder->updateTexImage();
44
+ env->CallVoidMethod(_jSurfaceTexture, _updateTexImageMethod);
43
45
 
46
+ // Check for exceptions
47
+ if (env->ExceptionCheck()) {
48
+ RNSkLogger::logToConsole("updateAndRelease() failed. The exception above "
49
+ "can safely be ignored");
50
+ env->ExceptionClear();
51
+ }
52
+ if (surface) {
44
53
  // Draw into canvas using callback
45
54
  cb(surface->getCanvas());
46
55
 
47
56
  // Swap buffers and show on screen
48
- return _surfaceHolder->present();
57
+ _surfaceHolder->present();
49
58
 
59
+ return true;
50
60
  } else {
51
61
  // the render context did not provide a surface
52
62
  return false;
@@ -56,11 +66,31 @@ bool RNSkOpenGLCanvasProvider::renderToCanvas(
56
66
  return false;
57
67
  }
58
68
 
59
- void RNSkOpenGLCanvasProvider::surfaceAvailable(jobject surface, int width,
60
- int height) {
69
+ void RNSkOpenGLCanvasProvider::surfaceAvailable(jobject jSurfaceTexture,
70
+ int width, int height) {
61
71
  // Create renderer!
72
+ JNIEnv *env = facebook::jni::Environment::current();
73
+
74
+ _jSurfaceTexture = env->NewGlobalRef(jSurfaceTexture);
75
+ jclass surfaceClass = env->FindClass("android/view/Surface");
76
+ jmethodID surfaceConstructor = env->GetMethodID(
77
+ surfaceClass, "<init>", "(Landroid/graphics/SurfaceTexture;)V");
78
+ // Create a new Surface instance
79
+ jobject jSurface =
80
+ env->NewObject(surfaceClass, surfaceConstructor, jSurfaceTexture);
81
+
82
+ jclass surfaceTextureClass = env->GetObjectClass(_jSurfaceTexture);
83
+ _updateTexImageMethod =
84
+ env->GetMethodID(surfaceTextureClass, "updateTexImage", "()V");
85
+
86
+ // Acquire the native window from the Surface
87
+ auto window = ANativeWindow_fromSurface(env, jSurface);
88
+ // Clean up local references
89
+ env->DeleteLocalRef(jSurface);
90
+ env->DeleteLocalRef(surfaceClass);
91
+ env->DeleteLocalRef(surfaceTextureClass);
62
92
  _surfaceHolder =
63
- SkiaOpenGLSurfaceFactory::makeWindowedSurface(surface, width, height);
93
+ OpenGLContext::getInstance().MakeWindow(window, width, height);
64
94
 
65
95
  // Post redraw request to ensure we paint in the next draw cycle.
66
96
  _requestRedraw();
@@ -69,6 +99,11 @@ void RNSkOpenGLCanvasProvider::surfaceDestroyed() {
69
99
  // destroy the renderer (a unique pointer so the dtor will be called
70
100
  // immediately.)
71
101
  _surfaceHolder = nullptr;
102
+ if (_jSurfaceTexture) {
103
+ JNIEnv *env = facebook::jni::Environment::current();
104
+ env->DeleteGlobalRef(_jSurfaceTexture);
105
+ _jSurfaceTexture = nullptr;
106
+ }
72
107
  }
73
108
 
74
109
  void RNSkOpenGLCanvasProvider::surfaceSizeChanged(int width, int height) {
@@ -5,7 +5,8 @@
5
5
  #include <memory>
6
6
 
7
7
  #include "RNSkView.h"
8
- #include "SkiaOpenGLSurfaceFactory.h"
8
+ #include "WindowContext.h"
9
+
9
10
  #include <android/native_window.h>
10
11
 
11
12
  namespace RNSkia {
@@ -33,7 +34,9 @@ public:
33
34
  void surfaceSizeChanged(int width, int height);
34
35
 
35
36
  private:
36
- std::unique_ptr<WindowSurfaceHolder> _surfaceHolder = nullptr;
37
+ std::unique_ptr<WindowContext> _surfaceHolder = nullptr;
37
38
  std::shared_ptr<RNSkPlatformContext> _platformContext;
39
+ jobject _jSurfaceTexture = nullptr;
40
+ jmethodID _updateTexImageMethod = nullptr;
38
41
  };
39
42
  } // namespace RNSkia
@@ -13,17 +13,9 @@
13
13
 
14
14
  namespace RNSkia {
15
15
 
16
- thread_local SkiaOpenGLContext ThreadContextHolder::ThreadSkiaOpenGLContext;
17
-
18
- sk_sp<SkImage>
19
- SkiaOpenGLSurfaceFactory::makeImageFromHardwareBuffer(void *buffer,
20
- bool requireKnownFormat) {
16
+ sk_sp<SkImage> SkiaOpenGLSurfaceFactory::makeImageFromHardwareBuffer(
17
+ SkiaOpenGLContext *context, void *buffer, bool requireKnownFormat) {
21
18
  #if __ANDROID_API__ >= 26
22
- // Setup OpenGL and Skia:
23
- if (!SkiaOpenGLHelper::createSkiaDirectContextIfNecessary(
24
- &ThreadContextHolder::ThreadSkiaOpenGLContext)) [[unlikely]] {
25
- throw std::runtime_error("Failed to create Skia Context for this Thread!");
26
- }
27
19
  const AHardwareBuffer *hardwareBuffer =
28
20
  static_cast<AHardwareBuffer *>(buffer);
29
21
  DeleteImageProc deleteImageProc = nullptr;
@@ -59,7 +51,7 @@ SkiaOpenGLSurfaceFactory::makeImageFromHardwareBuffer(void *buffer,
59
51
  }
60
52
 
61
53
  auto backendTex = MakeGLBackendTexture(
62
- ThreadContextHolder::ThreadSkiaOpenGLContext.directContext.get(),
54
+ context->directContext.get(),
63
55
  const_cast<AHardwareBuffer *>(hardwareBuffer), description.width,
64
56
  description.height, &deleteImageProc, &updateImageProc, &deleteImageCtx,
65
57
  false, format, false);
@@ -69,9 +61,9 @@ SkiaOpenGLSurfaceFactory::makeImageFromHardwareBuffer(void *buffer,
69
61
  return nullptr;
70
62
  }
71
63
  sk_sp<SkImage> image = SkImages::BorrowTextureFrom(
72
- ThreadContextHolder::ThreadSkiaOpenGLContext.directContext.get(),
73
- backendTex, kTopLeft_GrSurfaceOrigin, kRGBA_8888_SkColorType,
74
- kOpaque_SkAlphaType, nullptr, deleteImageProc, deleteImageCtx);
64
+ context->directContext.get(), backendTex, kTopLeft_GrSurfaceOrigin,
65
+ kRGBA_8888_SkColorType, kOpaque_SkAlphaType, nullptr, deleteImageProc,
66
+ deleteImageCtx);
75
67
  return image;
76
68
  #else
77
69
  throw std::runtime_error(
@@ -80,25 +72,15 @@ SkiaOpenGLSurfaceFactory::makeImageFromHardwareBuffer(void *buffer,
80
72
  #endif
81
73
  }
82
74
 
83
- sk_sp<SkSurface> SkiaOpenGLSurfaceFactory::makeOffscreenSurface(int width,
84
- int height) {
85
- // Setup OpenGL and Skia:
86
- if (!SkiaOpenGLHelper::createSkiaDirectContextIfNecessary(
87
- &ThreadContextHolder::ThreadSkiaOpenGLContext)) {
88
-
89
- RNSkLogger::logToConsole(
90
- "Could not create Skia Surface from native window / surface. "
91
- "Failed creating Skia Direct Context");
92
- return nullptr;
93
- }
75
+ sk_sp<SkSurface>
76
+ SkiaOpenGLSurfaceFactory::makeOffscreenSurface(SkiaOpenGLContext *context,
77
+ int width, int height) {
94
78
 
95
79
  auto colorType = kN32_SkColorType;
96
80
 
97
81
  SkSurfaceProps props(0, kUnknown_SkPixelGeometry);
98
82
 
99
- if (!SkiaOpenGLHelper::makeCurrent(
100
- &ThreadContextHolder::ThreadSkiaOpenGLContext,
101
- ThreadContextHolder::ThreadSkiaOpenGLContext.gl1x1Surface)) {
83
+ if (!SkiaOpenGLHelper::makeCurrent(context, context->gl1x1Surface)) {
102
84
  RNSkLogger::logToConsole(
103
85
  "Could not create EGL Surface from native window / surface. Could "
104
86
  "not set new surface as current surface.");
@@ -106,10 +88,8 @@ sk_sp<SkSurface> SkiaOpenGLSurfaceFactory::makeOffscreenSurface(int width,
106
88
  }
107
89
 
108
90
  // Create texture
109
- auto texture =
110
- ThreadContextHolder::ThreadSkiaOpenGLContext.directContext
111
- ->createBackendTexture(width, height, colorType,
112
- skgpu::Mipmapped::kNo, GrRenderable::kYes);
91
+ auto texture = context->directContext->createBackendTexture(
92
+ width, height, colorType, skgpu::Mipmapped::kNo, GrRenderable::kYes);
113
93
 
114
94
  if (!texture.isValid()) {
115
95
  RNSkLogger::logToConsole("couldn't create offscreen texture %dx%d", width,
@@ -121,13 +101,12 @@ sk_sp<SkSurface> SkiaOpenGLSurfaceFactory::makeOffscreenSurface(int width,
121
101
  GrBackendTexture texture;
122
102
  };
123
103
 
124
- auto releaseCtx = new ReleaseContext(
125
- {&ThreadContextHolder::ThreadSkiaOpenGLContext, texture});
104
+ auto releaseCtx = new ReleaseContext({context, texture});
126
105
 
127
106
  // Create a SkSurface from the GrBackendTexture
128
107
  return SkSurfaces::WrapBackendTexture(
129
- ThreadContextHolder::ThreadSkiaOpenGLContext.directContext.get(), texture,
130
- kTopLeft_GrSurfaceOrigin, 0, colorType, nullptr, &props,
108
+ context->directContext.get(), texture, kTopLeft_GrSurfaceOrigin, 0,
109
+ colorType, nullptr, &props,
131
110
  [](void *addr) {
132
111
  auto releaseCtx = reinterpret_cast<ReleaseContext *>(addr);
133
112
 
@@ -137,99 +116,9 @@ sk_sp<SkSurface> SkiaOpenGLSurfaceFactory::makeOffscreenSurface(int width,
137
116
  releaseCtx);
138
117
  }
139
118
 
140
- sk_sp<SkSurface> WindowSurfaceHolder::getSurface() {
141
- if (_skSurface == nullptr) {
142
-
143
- // Setup OpenGL and Skia
144
- if (!SkiaOpenGLHelper::createSkiaDirectContextIfNecessary(
145
- &ThreadContextHolder::ThreadSkiaOpenGLContext)) {
146
- RNSkLogger::logToConsole(
147
- "Could not create Skia Surface from native window / surface. "
148
- "Failed creating Skia Direct Context");
149
- return nullptr;
150
- }
151
-
152
- // Now we can create a surface
153
- _glSurface = SkiaOpenGLHelper::createWindowedSurface(_window);
154
- if (_glSurface == EGL_NO_SURFACE) {
155
- RNSkLogger::logToConsole(
156
- "Could not create EGL Surface from native window / surface.");
157
- return nullptr;
158
- }
159
-
160
- // Now make this one current
161
- if (!SkiaOpenGLHelper::makeCurrent(
162
- &ThreadContextHolder::ThreadSkiaOpenGLContext, _glSurface)) {
163
- RNSkLogger::logToConsole(
164
- "Could not create EGL Surface from native window / surface. Could "
165
- "not set new surface as current surface.");
166
- return nullptr;
167
- }
168
-
169
- // Set up parameters for the render target so that it
170
- // matches the underlying OpenGL context.
171
- GrGLFramebufferInfo fboInfo;
172
-
173
- // We pass 0 as the framebuffer id, since the
174
- // underlying Skia GrGlGpu will read this when wrapping the context in the
175
- // render target and the GrGlGpu object.
176
- fboInfo.fFBOID = 0;
177
- fboInfo.fFormat = 0x8058; // GL_RGBA8
178
-
179
- GLint stencil;
180
- glGetIntegerv(GL_STENCIL_BITS, &stencil);
181
-
182
- GLint samples;
183
- glGetIntegerv(GL_SAMPLES, &samples);
184
-
185
- auto colorType = kN32_SkColorType;
186
-
187
- auto maxSamples =
188
- ThreadContextHolder::ThreadSkiaOpenGLContext.directContext
189
- ->maxSurfaceSampleCountForColorType(colorType);
190
-
191
- if (samples > maxSamples) {
192
- samples = maxSamples;
193
- }
194
-
195
- auto renderTarget = GrBackendRenderTargets::MakeGL(_width, _height, samples,
196
- stencil, fboInfo);
197
-
198
- SkSurfaceProps props(0, kUnknown_SkPixelGeometry);
199
-
200
- struct ReleaseContext {
201
- EGLSurface glSurface;
202
- };
203
-
204
- auto releaseCtx = new ReleaseContext({_glSurface});
205
-
206
- // Create surface object
207
- _skSurface = SkSurfaces::WrapBackendRenderTarget(
208
- ThreadContextHolder::ThreadSkiaOpenGLContext.directContext.get(),
209
- renderTarget, kBottomLeft_GrSurfaceOrigin, colorType, nullptr, &props,
210
- [](void *addr) {
211
- auto releaseCtx = reinterpret_cast<ReleaseContext *>(addr);
212
- SkiaOpenGLHelper::destroySurface(releaseCtx->glSurface);
213
- delete releaseCtx;
214
- },
215
- reinterpret_cast<void *>(releaseCtx));
216
- }
217
-
218
- return _skSurface;
219
- }
220
-
221
119
  sk_sp<SkSurface> AndroidSkiaContext::getSurface() {
222
120
  if (_skSurface == nullptr) {
223
121
 
224
- // Setup OpenGL and Skia
225
- if (!SkiaOpenGLHelper::createSkiaDirectContextIfNecessary(
226
- &ThreadContextHolder::ThreadSkiaOpenGLContext)) {
227
- RNSkLogger::logToConsole(
228
- "Could not create Skia Surface from native window / surface. "
229
- "Failed creating Skia Direct Context");
230
- return nullptr;
231
- }
232
-
233
122
  // Now we can create a surface
234
123
  _glSurface = SkiaOpenGLHelper::createWindowedSurface(_window);
235
124
  if (_glSurface == EGL_NO_SURFACE) {
@@ -239,8 +128,7 @@ sk_sp<SkSurface> AndroidSkiaContext::getSurface() {
239
128
  }
240
129
 
241
130
  // Now make this one current
242
- if (!SkiaOpenGLHelper::makeCurrent(
243
- &ThreadContextHolder::ThreadSkiaOpenGLContext, _glSurface)) {
131
+ if (!SkiaOpenGLHelper::makeCurrent(_context, _glSurface)) {
244
132
  RNSkLogger::logToConsole(
245
133
  "Could not create EGL Surface from native window / surface. Could "
246
134
  "not set new surface as current surface.");
@@ -266,8 +154,7 @@ sk_sp<SkSurface> AndroidSkiaContext::getSurface() {
266
154
  auto colorType = kN32_SkColorType;
267
155
 
268
156
  auto maxSamples =
269
- ThreadContextHolder::ThreadSkiaOpenGLContext.directContext
270
- ->maxSurfaceSampleCountForColorType(colorType);
157
+ _context->directContext->maxSurfaceSampleCountForColorType(colorType);
271
158
 
272
159
  if (samples > maxSamples) {
273
160
  samples = maxSamples;
@@ -286,8 +173,8 @@ sk_sp<SkSurface> AndroidSkiaContext::getSurface() {
286
173
 
287
174
  // Create surface object
288
175
  _skSurface = SkSurfaces::WrapBackendRenderTarget(
289
- ThreadContextHolder::ThreadSkiaOpenGLContext.directContext.get(),
290
- renderTarget, kBottomLeft_GrSurfaceOrigin, colorType, nullptr, &props,
176
+ _context->directContext.get(), renderTarget,
177
+ kBottomLeft_GrSurfaceOrigin, colorType, nullptr, &props,
291
178
  [](void *addr) {
292
179
  auto releaseCtx = reinterpret_cast<ReleaseContext *>(addr);
293
180
  SkiaOpenGLHelper::destroySurface(releaseCtx->glSurface);
@@ -295,7 +182,6 @@ sk_sp<SkSurface> AndroidSkiaContext::getSurface() {
295
182
  },
296
183
  reinterpret_cast<void *>(releaseCtx));
297
184
  }
298
-
299
185
  return _skSurface;
300
186
  }
301
187
 
@@ -13,8 +13,8 @@
13
13
  #include <thread>
14
14
  #include <unordered_map>
15
15
 
16
- #include "SkiaContext.h"
17
16
  #include "SkiaOpenGLHelper.h"
17
+ #include "WindowContext.h"
18
18
 
19
19
  #pragma clang diagnostic push
20
20
  #pragma clang diagnostic ignored "-Wdocumentation"
@@ -31,145 +31,45 @@
31
31
 
32
32
  namespace RNSkia {
33
33
 
34
- /**
35
- * Holder of the thread local SkiaOpenGLContext member
36
- */
37
- class ThreadContextHolder {
34
+ class AndroidSkiaContext : public WindowContext {
38
35
  public:
39
- static thread_local SkiaOpenGLContext ThreadSkiaOpenGLContext;
40
- };
41
-
42
- /**
43
- * Holder of the Windowed SkSurface with support for making current
44
- * and presenting to screen
45
- */
46
- class WindowSurfaceHolder {
47
- public:
48
- WindowSurfaceHolder(jobject jSurfaceTexture, int width, int height)
49
- : _width(width), _height(height) {
50
- JNIEnv *env = facebook::jni::Environment::current();
51
- _jSurfaceTexture = env->NewGlobalRef(jSurfaceTexture);
52
- jclass surfaceClass = env->FindClass("android/view/Surface");
53
- jmethodID surfaceConstructor = env->GetMethodID(
54
- surfaceClass, "<init>", "(Landroid/graphics/SurfaceTexture;)V");
55
- // Create a new Surface instance
56
- jobject jSurface =
57
- env->NewObject(surfaceClass, surfaceConstructor, jSurfaceTexture);
58
-
59
- jclass surfaceTextureClass = env->GetObjectClass(_jSurfaceTexture);
60
- _updateTexImageMethod =
61
- env->GetMethodID(surfaceTextureClass, "updateTexImage", "()V");
62
-
63
- // Acquire the native window from the Surface
64
- _window = ANativeWindow_fromSurface(env, jSurface);
65
- // Clean up local references
66
- env->DeleteLocalRef(jSurface);
67
- env->DeleteLocalRef(surfaceClass);
68
- env->DeleteLocalRef(surfaceTextureClass);
69
- }
70
-
71
- ~WindowSurfaceHolder() {
72
- JNIEnv *env = facebook::jni::Environment::current();
73
- env->DeleteGlobalRef(_jSurfaceTexture);
74
- ANativeWindow_release(_window);
75
- }
76
-
77
- int getWidth() { return _width; }
78
- int getHeight() { return _height; }
79
-
80
- /*
81
- * Ensures that the holder has a valid surface and returns the surface.
82
- */
83
- sk_sp<SkSurface> getSurface();
84
-
85
- void updateTexImage() {
86
- JNIEnv *env = facebook::jni::Environment::current();
87
-
88
- // Call updateTexImage on the SurfaceTexture object
89
- env->CallVoidMethod(_jSurfaceTexture, _updateTexImageMethod);
90
-
91
- // Check for exceptions
92
- if (env->ExceptionCheck()) {
93
- RNSkLogger::logToConsole("updateAndRelease() failed. The exception above "
94
- "can safely be ignored");
95
- env->ExceptionClear();
96
- }
97
- }
98
-
99
- /**
100
- * Resizes the surface
101
- * @param width
102
- * @param height
103
- */
104
- void resize(int width, int height) {
105
- _width = width;
106
- _height = height;
107
- _skSurface = nullptr;
108
- }
109
-
110
- /**
111
- * Sets the current surface as the active surface
112
- * @return true if make current succeeds
113
- */
114
- bool makeCurrent() {
115
- return SkiaOpenGLHelper::makeCurrent(
116
- &ThreadContextHolder::ThreadSkiaOpenGLContext, _glSurface);
117
- }
118
-
119
- /**
120
- * Presents the current drawing operations by swapping buffers
121
- * @return true if make current succeeds
122
- */
123
- bool present() {
124
- // Flush and submit the direct context
125
- ThreadContextHolder::ThreadSkiaOpenGLContext.directContext
126
- ->flushAndSubmit();
127
-
128
- // Swap buffers
129
- return SkiaOpenGLHelper::swapBuffers(
130
- &ThreadContextHolder::ThreadSkiaOpenGLContext, _glSurface);
131
- }
132
-
133
- private:
134
- ANativeWindow *_window;
135
- sk_sp<SkSurface> _skSurface = nullptr;
136
- jobject _jSurfaceTexture = nullptr;
137
- EGLSurface _glSurface = EGL_NO_SURFACE;
138
- jmethodID _updateTexImageMethod = nullptr;
139
- int _width = 0;
140
- int _height = 0;
141
- };
36
+ AndroidSkiaContext(SkiaOpenGLContext *context, ANativeWindow *window,
37
+ int width, int height)
38
+ : _context(context), _window(window), _width(width), _height(height) {}
142
39
 
143
- class AndroidSkiaContext : public SkiaContext {
144
- public:
145
- AndroidSkiaContext(ANativeWindow *window, int width, int height)
146
- : _window(window), _width(width), _height(height) {}
147
-
148
- ~AndroidSkiaContext() {}
40
+ ~AndroidSkiaContext() { ANativeWindow_release(_window); }
149
41
 
150
42
  sk_sp<SkSurface> getSurface() override;
151
43
 
152
44
  void present() override {
153
- if (!SkiaOpenGLHelper::makeCurrent(
154
- &ThreadContextHolder::ThreadSkiaOpenGLContext, _glSurface)) {
45
+ if (!SkiaOpenGLHelper::makeCurrent(_context, _glSurface)) {
155
46
  RNSkLogger::logToConsole(
156
47
  "Could not create EGL Surface from native window / surface. Could "
157
48
  "not set new surface as current surface.");
158
49
  return;
159
50
  }
160
51
  // Flush and submit the direct context
161
- ThreadContextHolder::ThreadSkiaOpenGLContext.directContext
162
- ->flushAndSubmit();
52
+ _context->directContext->flushAndSubmit();
163
53
 
164
54
  // Swap buffers
165
- SkiaOpenGLHelper::swapBuffers(&ThreadContextHolder::ThreadSkiaOpenGLContext,
166
- _glSurface);
55
+ SkiaOpenGLHelper::swapBuffers(_context, _glSurface);
167
56
  }
168
57
 
58
+ void resize(int width, int height) override {
59
+ _skSurface = nullptr;
60
+ _width = width;
61
+ _height = height;
62
+ }
63
+
64
+ int getWidth() override { return _width; };
65
+
66
+ int getHeight() override { return _height; };
67
+
169
68
  private:
170
69
  ANativeWindow *_window;
171
70
  sk_sp<SkSurface> _skSurface = nullptr;
172
71
  EGLSurface _glSurface = EGL_NO_SURFACE;
72
+ SkiaOpenGLContext *_context;
173
73
  int _width = 0;
174
74
  int _height = 0;
175
75
  };
@@ -182,26 +82,18 @@ public:
182
82
  * @param height Height of surface
183
83
  * @return An SkSurface backed by a texture.
184
84
  */
185
- static sk_sp<SkSurface> makeOffscreenSurface(int width, int height);
85
+ static sk_sp<SkSurface> makeOffscreenSurface(SkiaOpenGLContext *context,
86
+ int width, int height);
186
87
 
187
88
  static sk_sp<SkImage>
188
- makeImageFromHardwareBuffer(void *buffer, bool requireKnownFormat = false);
189
-
190
- static std::shared_ptr<AndroidSkiaContext>
191
- makeContext(ANativeWindow *surface, int width, int height) {
192
- return std::make_shared<AndroidSkiaContext>(surface, width, height);
193
- }
194
-
195
- /**
196
- * Creates a windowed Skia Surface holder.
197
- * @param width Initial width of surface
198
- * @param height Initial height of surface
199
- * @param window Window coming from Java
200
- * @return A Surface holder
201
- */
202
- static std::unique_ptr<WindowSurfaceHolder>
203
- makeWindowedSurface(jobject window, int width, int height) {
204
- return std::make_unique<WindowSurfaceHolder>(window, width, height);
89
+ makeImageFromHardwareBuffer(SkiaOpenGLContext *context, void *buffer,
90
+ bool requireKnownFormat = false);
91
+
92
+ static std::unique_ptr<AndroidSkiaContext>
93
+ makeContext(SkiaOpenGLContext *context, ANativeWindow *surface, int width,
94
+ int height) {
95
+ return std::make_unique<AndroidSkiaContext>(context, surface, width,
96
+ height);
205
97
  }
206
98
  };
207
99