@shopify/react-native-skia 1.5.1 → 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.
@@ -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
 
@@ -40,7 +40,7 @@ public:
40
40
  sk_sp<SkTypeface> typeface =
41
41
  JsiSkTypeface::fromValue(runtime, arguments[0]);
42
42
  SkString familyName(arguments[1].asString(runtime).utf8(runtime).c_str());
43
- auto result = getObject()->registerTypeface(typeface, familyName);
43
+ getObject()->registerTypeface(typeface, familyName);
44
44
  return jsi::Value::undefined();
45
45
  }
46
46
 
@@ -14,7 +14,7 @@
14
14
  #include "JsiSkRect.h"
15
15
  #include "JsiSkTypeface.h"
16
16
 
17
- #include "SkiaContext.h"
17
+ #include "WindowContext.h"
18
18
 
19
19
  #pragma clang diagnostic push
20
20
  #pragma clang diagnostic ignored "-Wdocumentation"
@@ -28,12 +28,15 @@ namespace RNSkia {
28
28
 
29
29
  namespace jsi = facebook::jsi;
30
30
 
31
- class JsiSkiaContext : public JsiSkWrappingSharedPtrHostObject<SkiaContext> {
31
+ class JsiSkiaContext : public JsiSkWrappingSharedPtrHostObject<WindowContext> {
32
32
  public:
33
33
  EXPORT_JSI_API_TYPENAME(JsiSkiaContext, SkiaContext)
34
34
 
35
35
  JSI_HOST_FUNCTION(getSurface) {
36
36
  auto surface = getObject()->getSurface();
37
+ if (surface == nullptr) {
38
+ return jsi::Value::null();
39
+ }
37
40
  return jsi::Object::createFromHostObject(
38
41
  runtime,
39
42
  std::make_shared<JsiSkSurface>(getContext(), std::move(surface)));
@@ -48,7 +51,7 @@ public:
48
51
  JSI_EXPORT_FUNC(JsiSkiaContext, present))
49
52
 
50
53
  JsiSkiaContext(std::shared_ptr<RNSkPlatformContext> context,
51
- std::shared_ptr<SkiaContext> ctx)
54
+ std::shared_ptr<WindowContext> ctx)
52
55
  : JsiSkWrappingSharedPtrHostObject(std::move(context), std::move(ctx)) {}
53
56
 
54
57
  /**
@@ -55,9 +55,8 @@ double JsiValue::getAsNumber() const {
55
55
 
56
56
  const std::string &JsiValue::getAsString() const {
57
57
  if (_type == PropType::Number) {
58
- return std::move(std::to_string(_numberValue));
58
+ return std::to_string(_numberValue);
59
59
  }
60
-
61
60
  if (_type != PropType::String) {
62
61
  throw std::runtime_error("Expected type string, got " +
63
62
  getTypeAsString(_type));
@@ -11,7 +11,7 @@
11
11
 
12
12
  #include "RNSkDispatchQueue.h"
13
13
  #include "RNSkVideo.h"
14
- #include "SkiaContext.h"
14
+ #include "WindowContext.h"
15
15
 
16
16
  #pragma clang diagnostic push
17
17
  #pragma clang diagnostic ignored "-Wdocumentation"
@@ -135,7 +135,7 @@ public:
135
135
  */
136
136
  virtual sk_sp<SkSurface> makeOffscreenSurface(int width, int height) = 0;
137
137
 
138
- virtual std::shared_ptr<SkiaContext>
138
+ virtual std::shared_ptr<WindowContext>
139
139
  makeContextFromNativeSurface(void *surface, int width, int height) = 0;
140
140
 
141
141
  /**
@@ -12,11 +12,14 @@
12
12
 
13
13
  namespace RNSkia {
14
14
 
15
- class SkiaContext {
15
+ class WindowContext {
16
16
  public:
17
- virtual ~SkiaContext() = default;
17
+ virtual ~WindowContext() = default;
18
18
  virtual sk_sp<SkSurface> getSurface() = 0;
19
19
  virtual void present() = 0;
20
+ virtual void resize(int width, int height) = 0;
21
+ virtual int getWidth() = 0;
22
+ virtual int getHeight() = 0;
20
23
  };
21
24
 
22
25
  } // namespace RNSkia
@@ -0,0 +1,46 @@
1
+ #pragma once
2
+
3
+ #include "SkiaMetalSurfaceFactory.h"
4
+ #include "WindowContext.h"
5
+
6
+ #include "include/core/SkSurface.h"
7
+
8
+ namespace RNSkia {
9
+ class RNSkiOSPlatformContext;
10
+ }
11
+
12
+ class MetalContext {
13
+
14
+ public:
15
+ MetalContext(const MetalContext &) = delete;
16
+ MetalContext &operator=(const MetalContext &) = delete;
17
+
18
+ static MetalContext &getInstance() {
19
+ static thread_local MetalContext instance;
20
+ return instance;
21
+ }
22
+
23
+ sk_sp<SkSurface> MakeOffscreen(int width, int height) {
24
+ return SkiaMetalSurfaceFactory::makeOffscreenSurface(_device, &_context,
25
+ width, height);
26
+ }
27
+
28
+ sk_sp<SkImage> MakeImageFromBuffer(void *buffer) {
29
+ CVPixelBufferRef sampleBuffer = (CVPixelBufferRef)buffer;
30
+ return SkiaMetalSurfaceFactory::makeTextureFromCVPixelBuffer(&_context,
31
+ sampleBuffer);
32
+ }
33
+
34
+ std::unique_ptr<RNSkia::WindowContext> MakeWindow(CALayer *window, int width,
35
+ int height) {
36
+ return SkiaMetalSurfaceFactory::makeContext(&_context, window, width,
37
+ height);
38
+ }
39
+
40
+ private:
41
+ friend class RNSkia::RNSkiOSPlatformContext;
42
+ id<MTLDevice> _device;
43
+ SkiaMetalContext _context;
44
+
45
+ MetalContext();
46
+ };
@@ -0,0 +1,33 @@
1
+ #include "MetalContext.h"
2
+
3
+ #import <MetalKit/MetalKit.h>
4
+
5
+ #pragma clang diagnostic push
6
+ #pragma clang diagnostic ignored "-Wdocumentation"
7
+
8
+ #import <include/gpu/ganesh/GrBackendSurface.h>
9
+ #import <include/gpu/ganesh/SkImageGanesh.h>
10
+ #import <include/gpu/ganesh/mtl/GrMtlBackendContext.h>
11
+ #import <include/gpu/ganesh/mtl/GrMtlBackendSurface.h>
12
+ #import <include/gpu/ganesh/mtl/GrMtlDirectContext.h>
13
+ #import <include/gpu/ganesh/mtl/GrMtlTypes.h>
14
+ #import <include/gpu/ganesh/mtl/SkSurfaceMetal.h>
15
+
16
+ #pragma clang diagnostic pop
17
+
18
+ MetalContext::MetalContext() {
19
+ _device = MTLCreateSystemDefaultDevice();
20
+ _context.commandQueue =
21
+ id<MTLCommandQueue>(CFRetain((GrMTLHandle)[_device newCommandQueue]));
22
+
23
+ GrMtlBackendContext backendContext = {};
24
+ backendContext.fDevice.reset((__bridge void *)_device);
25
+ backendContext.fQueue.reset((__bridge void *)_context.commandQueue);
26
+ GrContextOptions grContextOptions; // set different options here.
27
+
28
+ // Create the Skia Direct Context
29
+ _context.skContext = GrDirectContexts::MakeMetal(backendContext);
30
+ if (_context.skContext == nullptr) {
31
+ RNSkia::RNSkLogger::logToConsole("Couldn't create a Skia Metal Context");
32
+ }
33
+ }
@@ -1,6 +1,6 @@
1
1
  #import "RNSkMetalCanvasProvider.h"
2
+ #include "MetalContext.h"
2
3
  #import "RNSkLog.h"
3
- #import "SkiaMetalSurfaceFactory.h"
4
4
 
5
5
  #pragma clang diagnostic push
6
6
  #pragma clang diagnostic ignored "-Wdocumentation"
@@ -23,12 +23,6 @@ RNSkMetalCanvasProvider::RNSkMetalCanvasProvider(
23
23
  #pragma clang diagnostic ignored "-Wunguarded-availability-new"
24
24
  _layer = [CAMetalLayer layer];
25
25
  #pragma clang diagnostic pop
26
- _layer.framebufferOnly = NO;
27
- _layer.device = MTLCreateSystemDefaultDevice();
28
- _layer.opaque = false;
29
- _layer.contentsScale = _context->getPixelDensity();
30
- _layer.pixelFormat = MTLPixelFormatBGRA8Unorm;
31
- _layer.contentsGravity = kCAGravityBottomLeft;
32
26
  }
33
27
 
34
28
  RNSkMetalCanvasProvider::~RNSkMetalCanvasProvider() {}
@@ -36,16 +30,12 @@ RNSkMetalCanvasProvider::~RNSkMetalCanvasProvider() {}
36
30
  /**
37
31
  Returns the scaled width of the view
38
32
  */
39
- float RNSkMetalCanvasProvider::getScaledWidth() {
40
- return _width * _context->getPixelDensity();
41
- };
33
+ float RNSkMetalCanvasProvider::getScaledWidth() { return _width; };
42
34
 
43
35
  /**
44
36
  Returns the scaled height of the view
45
37
  */
46
- float RNSkMetalCanvasProvider::getScaledHeight() {
47
- return _height * _context->getPixelDensity();
48
- };
38
+ float RNSkMetalCanvasProvider::getScaledHeight() { return _height; };
49
39
 
50
40
  /**
51
41
  Render to a canvas
@@ -80,11 +70,8 @@ bool RNSkMetalCanvasProvider::renderToCanvas(
80
70
  if (currentDrawable == nullptr) {
81
71
  return false;
82
72
  }
83
-
84
- auto skSurface = SkiaMetalSurfaceFactory::makeWindowedSurface(
85
- currentDrawable.texture, _layer.drawableSize.width,
86
- _layer.drawableSize.height);
87
-
73
+ auto ctx = MetalContext::getInstance().MakeWindow(_layer, _width, _height);
74
+ auto skSurface = ctx->getSurface();
88
75
  SkCanvas *canvas = skSurface->getCanvas();
89
76
  cb(canvas);
90
77
 
@@ -92,22 +79,15 @@ bool RNSkMetalCanvasProvider::renderToCanvas(
92
79
  dContext->flushAndSubmit();
93
80
  }
94
81
 
95
- id<MTLCommandBuffer> commandBuffer(
96
- [ThreadContextHolder::ThreadSkiaMetalContext
97
- .commandQueue commandBuffer]);
98
- [commandBuffer presentDrawable:currentDrawable];
99
- [commandBuffer commit];
82
+ ctx->present();
100
83
  }
101
84
  return true;
102
85
  };
103
86
 
104
87
  void RNSkMetalCanvasProvider::setSize(int width, int height) {
105
- _width = width;
106
- _height = height;
107
88
  _layer.frame = CGRectMake(0, 0, width, height);
108
- _layer.drawableSize = CGSizeMake(width * _context->getPixelDensity(),
109
- height * _context->getPixelDensity());
110
-
89
+ _width = width * _context->getPixelDensity();
90
+ _height = height * _context->getPixelDensity();
111
91
  _requestRedraw();
112
92
  }
113
93
 
@@ -67,7 +67,7 @@ public:
67
67
 
68
68
  std::shared_ptr<RNSkVideo> createVideo(const std::string &url) override;
69
69
 
70
- std::shared_ptr<SkiaContext>
70
+ std::shared_ptr<WindowContext>
71
71
  makeContextFromNativeSurface(void *surface, int width, int height) override;
72
72
 
73
73
  virtual void performStreamOperation(
@@ -5,13 +5,13 @@
5
5
  #include <thread>
6
6
  #include <utility>
7
7
 
8
+ #include "MetalContext.h"
8
9
  #include "RNSkiOSVideo.h"
9
- #import "SkiaCVPixelBufferUtils.h"
10
- #import "SkiaMetalSurfaceFactory.h"
11
10
 
12
11
  #pragma clang diagnostic push
13
12
  #pragma clang diagnostic ignored "-Wdocumentation"
14
13
 
14
+ #import "include/core/SkColorSpace.h"
15
15
  #include "include/core/SkFontMgr.h"
16
16
  #include "include/core/SkSurface.h"
17
17
 
@@ -71,7 +71,7 @@ uint64_t RNSkiOSPlatformContext::makeNativeBuffer(sk_sp<SkImage> image) {
71
71
  if (image->colorType() != kBGRA_8888_SkColorType) {
72
72
  // on iOS, 32_BGRA is the only supported RGB format for CVPixelBuffers.
73
73
  image = image->makeColorTypeAndColorSpace(
74
- ThreadContextHolder::ThreadSkiaMetalContext.skContext.get(),
74
+ MetalContext::getInstance()._context.skContext.get(),
75
75
  kBGRA_8888_SkColorType, SkColorSpace::MakeSRGB());
76
76
  if (image == nullptr) {
77
77
  throw std::runtime_error(
@@ -149,11 +149,11 @@ RNSkiOSPlatformContext::createVideo(const std::string &url) {
149
149
  return std::make_shared<RNSkiOSVideo>(url, this);
150
150
  }
151
151
 
152
- std::shared_ptr<SkiaContext>
152
+ std::shared_ptr<WindowContext>
153
153
  RNSkiOSPlatformContext::makeContextFromNativeSurface(void *surface, int width,
154
154
  int height) {
155
- return SkiaMetalSurfaceFactory::makeContext((__bridge CALayer *)surface,
156
- width, height);
155
+ return MetalContext::getInstance().MakeWindow((__bridge CALayer *)surface,
156
+ width, height);
157
157
  }
158
158
 
159
159
  void RNSkiOSPlatformContext::raiseError(const std::exception &err) {
@@ -162,12 +162,11 @@ void RNSkiOSPlatformContext::raiseError(const std::exception &err) {
162
162
 
163
163
  sk_sp<SkSurface> RNSkiOSPlatformContext::makeOffscreenSurface(int width,
164
164
  int height) {
165
- return SkiaMetalSurfaceFactory::makeOffscreenSurface(width, height);
165
+ return MetalContext::getInstance().MakeOffscreen(width, height);
166
166
  }
167
167
 
168
168
  sk_sp<SkImage> RNSkiOSPlatformContext::makeImageFromNativeBuffer(void *buffer) {
169
- CVPixelBufferRef sampleBuffer = (CVPixelBufferRef)buffer;
170
- return SkiaMetalSurfaceFactory::makeTextureFromCVPixelBuffer(sampleBuffer);
169
+ return MetalContext::getInstance().MakeImageFromBuffer(buffer);
171
170
  }
172
171
 
173
172
  sk_sp<SkFontMgr> RNSkiOSPlatformContext::createFontMgr() {
@@ -1,5 +1,3 @@
1
- #pragma once
2
-
3
1
  #import <memory>
4
2
 
5
3
  #import "RNSkMetalCanvasProvider.h"
@@ -1,9 +1,11 @@
1
+ #pragma once
2
+
1
3
  #import <MetalKit/MetalKit.h>
2
4
 
3
5
  #include <memory>
4
6
 
5
7
  #include "RNSkLog.h"
6
- #include "SkiaContext.h"
8
+ #include "WindowContext.h"
7
9
 
8
10
  #pragma clang diagnostic push
9
11
  #pragma clang diagnostic ignored "-Wdocumentation"
@@ -20,35 +22,31 @@ using SkiaMetalContext = struct SkiaMetalContext {
20
22
  sk_sp<GrDirectContext> skContext = nullptr;
21
23
  };
22
24
 
23
- class ThreadContextHolder {
24
- public:
25
- static thread_local SkiaMetalContext ThreadSkiaMetalContext;
26
- };
27
-
28
25
  class SkiaMetalSurfaceFactory {
29
26
  friend class IOSSkiaContext;
30
27
 
31
28
  public:
32
- static sk_sp<SkSurface> makeWindowedSurface(id<MTLTexture> texture, int width,
29
+ static sk_sp<SkSurface> makeWindowedSurface(SkiaMetalContext *context,
30
+ id<MTLTexture> texture, int width,
33
31
  int height);
34
- static sk_sp<SkSurface> makeOffscreenSurface(int width, int height);
32
+ static sk_sp<SkSurface> makeOffscreenSurface(id<MTLDevice> device,
33
+ SkiaMetalContext *context,
34
+ int width, int height);
35
35
 
36
36
  static sk_sp<SkImage>
37
- makeTextureFromCVPixelBuffer(CVPixelBufferRef pixelBuffer);
38
-
39
- static std::shared_ptr<RNSkia::SkiaContext>
40
- makeContext(CALayer *texture, int width, int height);
37
+ makeTextureFromCVPixelBuffer(SkiaMetalContext *context,
38
+ CVPixelBufferRef pixelBuffer);
41
39
 
42
- private:
43
- static id<MTLDevice> device;
44
- static bool
45
- createSkiaDirectContextIfNecessary(SkiaMetalContext *threadContext);
40
+ static std::unique_ptr<RNSkia::WindowContext>
41
+ makeContext(SkiaMetalContext *context, CALayer *texture, int width,
42
+ int height);
46
43
  };
47
44
 
48
- class IOSSkiaContext : public RNSkia::SkiaContext {
45
+ class IOSSkiaContext : public RNSkia::WindowContext {
49
46
  public:
50
- IOSSkiaContext(CALayer *layer, int width, int height) {
51
- auto pd = 3;
47
+ IOSSkiaContext(SkiaMetalContext *context, CALayer *layer, int width,
48
+ int height)
49
+ : _context(context) {
52
50
  #pragma clang diagnostic push
53
51
  #pragma clang diagnostic ignored "-Wunguarded-availability-new"
54
52
  _layer = (CAMetalLayer *)layer;
@@ -56,12 +54,10 @@ public:
56
54
  _layer.framebufferOnly = NO;
57
55
  _layer.device = MTLCreateSystemDefaultDevice();
58
56
  _layer.opaque = false;
59
- _layer.contentsScale = pd;
57
+ _layer.contentsScale = 3;
60
58
  _layer.pixelFormat = MTLPixelFormatBGRA8Unorm;
61
59
  _layer.contentsGravity = kCAGravityBottomLeft;
62
-
63
- _layer.frame = CGRectMake(0, 0, width, height);
64
- _layer.drawableSize = CGSizeMake(width * pd, height * pd);
60
+ _layer.drawableSize = CGSizeMake(width, height);
65
61
  }
66
62
 
67
63
  ~IOSSkiaContext() {}
@@ -70,11 +66,6 @@ public:
70
66
  if (_skSurface) {
71
67
  return _skSurface;
72
68
  }
73
- // Create the Skia Direct Context if it doesn't exist
74
- if (!SkiaMetalSurfaceFactory::createSkiaDirectContextIfNecessary(
75
- &ThreadContextHolder::ThreadSkiaMetalContext)) {
76
- return nullptr;
77
- }
78
69
 
79
70
  // Get the next drawable from the CAMetalLayer
80
71
  _currentDrawable = [_layer nextDrawable];
@@ -86,7 +77,7 @@ public:
86
77
 
87
78
  // Get the texture from the drawable
88
79
  _skSurface = SkiaMetalSurfaceFactory::makeWindowedSurface(
89
- _currentDrawable.texture, _layer.drawableSize.width,
80
+ _context, _currentDrawable.texture, _layer.drawableSize.width,
90
81
  _layer.drawableSize.height);
91
82
  return _skSurface;
92
83
  }
@@ -96,15 +87,20 @@ public:
96
87
  dContext->flushAndSubmit();
97
88
  }
98
89
 
99
- id<MTLCommandBuffer> commandBuffer(
100
- [ThreadContextHolder::ThreadSkiaMetalContext
101
- .commandQueue commandBuffer]);
90
+ id<MTLCommandBuffer> commandBuffer([_context->commandQueue commandBuffer]);
102
91
  [commandBuffer presentDrawable:_currentDrawable];
103
92
  [commandBuffer commit];
104
93
  _skSurface = nullptr;
105
94
  }
106
95
 
96
+ void resize(int width, int height) override { _skSurface = nullptr; }
97
+
98
+ int getWidth() override { return _layer.frame.size.width; };
99
+
100
+ int getHeight() override { return _layer.frame.size.height; };
101
+
107
102
  private:
103
+ SkiaMetalContext *_context;
108
104
  sk_sp<SkSurface> _skSurface = nullptr;
109
105
  #pragma clang diagnostic push
110
106
  #pragma clang diagnostic ignored "-Wunguarded-availability-new"
@@ -21,8 +21,6 @@
21
21
 
22
22
  #pragma clang diagnostic pop
23
23
 
24
- thread_local SkiaMetalContext ThreadContextHolder::ThreadSkiaMetalContext;
25
-
26
24
  struct OffscreenRenderContext {
27
25
  id<MTLTexture> texture;
28
26
 
@@ -42,43 +40,14 @@ struct OffscreenRenderContext {
42
40
  }
43
41
  };
44
42
 
45
- id<MTLDevice> SkiaMetalSurfaceFactory::device = MTLCreateSystemDefaultDevice();
46
-
47
- bool SkiaMetalSurfaceFactory::createSkiaDirectContextIfNecessary(
48
- SkiaMetalContext *skiaMetalContext) {
49
- if (skiaMetalContext->skContext == nullptr) {
50
- skiaMetalContext->commandQueue =
51
- id<MTLCommandQueue>(CFRetain((GrMTLHandle)[device newCommandQueue]));
52
-
53
- GrMtlBackendContext backendContext = {};
54
- backendContext.fDevice.reset((__bridge void *)device);
55
- backendContext.fQueue.reset(
56
- (__bridge void *)skiaMetalContext->commandQueue);
57
- GrContextOptions grContextOptions; // set different options here.
58
-
59
- // Create the Skia Direct Context
60
- skiaMetalContext->skContext = GrDirectContexts::MakeMetal(backendContext);
61
- if (skiaMetalContext->skContext == nullptr) {
62
- RNSkia::RNSkLogger::logToConsole("Couldn't create a Skia Metal Context");
63
- return false;
64
- }
65
- }
66
- return true;
67
- }
68
-
69
- std::shared_ptr<RNSkia::SkiaContext>
70
- SkiaMetalSurfaceFactory::makeContext(CALayer *texture, int width, int height) {
71
- return std::make_shared<IOSSkiaContext>(texture, width, height);
43
+ std::unique_ptr<RNSkia::WindowContext>
44
+ SkiaMetalSurfaceFactory::makeContext(SkiaMetalContext *context,
45
+ CALayer *texture, int width, int height) {
46
+ return std::make_unique<IOSSkiaContext>(context, texture, width, height);
72
47
  }
73
48
 
74
- sk_sp<SkSurface>
75
- SkiaMetalSurfaceFactory::makeWindowedSurface(id<MTLTexture> texture, int width,
76
- int height) {
77
- // Get render context for current thread
78
- if (!SkiaMetalSurfaceFactory::createSkiaDirectContextIfNecessary(
79
- &ThreadContextHolder::ThreadSkiaMetalContext)) {
80
- return nullptr;
81
- }
49
+ sk_sp<SkSurface> SkiaMetalSurfaceFactory::makeWindowedSurface(
50
+ SkiaMetalContext *context, id<MTLTexture> texture, int width, int height) {
82
51
  GrMtlTextureInfo fbInfo;
83
52
  fbInfo.fTexture.retain((__bridge void *)texture);
84
53
 
@@ -86,8 +55,8 @@ SkiaMetalSurfaceFactory::makeWindowedSurface(id<MTLTexture> texture, int width,
86
55
  GrBackendRenderTargets::MakeMtl(width, height, fbInfo);
87
56
 
88
57
  auto skSurface = SkSurfaces::WrapBackendRenderTarget(
89
- ThreadContextHolder::ThreadSkiaMetalContext.skContext.get(), backendRT,
90
- kTopLeft_GrSurfaceOrigin, kBGRA_8888_SkColorType, nullptr, nullptr);
58
+ context->skContext.get(), backendRT, kTopLeft_GrSurfaceOrigin,
59
+ kBGRA_8888_SkColorType, nullptr, nullptr);
91
60
 
92
61
  if (skSurface == nullptr || skSurface->getCanvas() == nullptr) {
93
62
  RNSkia::RNSkLogger::logToConsole(
@@ -97,15 +66,11 @@ SkiaMetalSurfaceFactory::makeWindowedSurface(id<MTLTexture> texture, int width,
97
66
  return skSurface;
98
67
  }
99
68
 
100
- sk_sp<SkSurface> SkiaMetalSurfaceFactory::makeOffscreenSurface(int width,
101
- int height) {
102
- if (!SkiaMetalSurfaceFactory::createSkiaDirectContextIfNecessary(
103
- &ThreadContextHolder::ThreadSkiaMetalContext)) {
104
- return nullptr;
105
- }
106
- auto ctx = new OffscreenRenderContext(
107
- device, ThreadContextHolder::ThreadSkiaMetalContext.skContext,
108
- ThreadContextHolder::ThreadSkiaMetalContext.commandQueue, width, height);
69
+ sk_sp<SkSurface> SkiaMetalSurfaceFactory::makeOffscreenSurface(
70
+ id<MTLDevice> device, SkiaMetalContext *context, int width, int height) {
71
+
72
+ auto ctx = new OffscreenRenderContext(device, context->skContext,
73
+ context->commandQueue, width, height);
109
74
 
110
75
  // Create a GrBackendTexture from the Metal texture
111
76
  GrMtlTextureInfo info;
@@ -115,34 +80,27 @@ sk_sp<SkSurface> SkiaMetalSurfaceFactory::makeOffscreenSurface(int width,
115
80
 
116
81
  // Create a SkSurface from the GrBackendTexture
117
82
  auto surface = SkSurfaces::WrapBackendTexture(
118
- ThreadContextHolder::ThreadSkiaMetalContext.skContext.get(),
119
- backendTexture, kTopLeft_GrSurfaceOrigin, 0, kBGRA_8888_SkColorType,
120
- nullptr, nullptr,
83
+ context->skContext.get(), backendTexture, kTopLeft_GrSurfaceOrigin, 0,
84
+ kBGRA_8888_SkColorType, nullptr, nullptr,
121
85
  [](void *addr) { delete (OffscreenRenderContext *)addr; }, ctx);
122
86
 
123
87
  return surface;
124
88
  }
125
89
 
126
90
  sk_sp<SkImage> SkiaMetalSurfaceFactory::makeTextureFromCVPixelBuffer(
127
- CVPixelBufferRef pixelBuffer) {
128
- if (!SkiaMetalSurfaceFactory::createSkiaDirectContextIfNecessary(
129
- &ThreadContextHolder::ThreadSkiaMetalContext)) [[unlikely]] {
130
- throw std::runtime_error("Failed to create Skia Context for this Thread!");
131
- }
132
- const SkiaMetalContext &context = ThreadContextHolder::ThreadSkiaMetalContext;
133
-
91
+ SkiaMetalContext *context, CVPixelBufferRef pixelBuffer) {
134
92
  SkiaCVPixelBufferUtils::CVPixelBufferBaseFormat format =
135
93
  SkiaCVPixelBufferUtils::getCVPixelBufferBaseFormat(pixelBuffer);
136
94
  switch (format) {
137
95
  case SkiaCVPixelBufferUtils::CVPixelBufferBaseFormat::rgb: {
138
96
  // CVPixelBuffer is in any RGB format, single-plane
139
97
  return SkiaCVPixelBufferUtils::RGB::makeSkImageFromCVPixelBuffer(
140
- context.skContext.get(), pixelBuffer);
98
+ context->skContext.get(), pixelBuffer);
141
99
  }
142
100
  case SkiaCVPixelBufferUtils::CVPixelBufferBaseFormat::yuv: {
143
101
  // CVPixelBuffer is in any YUV format, multi-plane
144
102
  return SkiaCVPixelBufferUtils::YUV::makeSkImageFromCVPixelBuffer(
145
- context.skContext.get(), pixelBuffer);
103
+ context->skContext.get(), pixelBuffer);
146
104
  }
147
105
  default:
148
106
  [[unlikely]] {
@@ -14,8 +14,6 @@
14
14
  #import <React/RCTViewComponentView.h>
15
15
  #endif // RCT_NEW_ARCH_ENABLED
16
16
 
17
- class RNSkiOSJsView;
18
-
19
17
  @interface SkiaUIView :
20
18
  #if RCT_NEW_ARCH_ENABLED
21
19
  RCTViewComponentView
@@ -34,14 +34,7 @@
34
34
  UIGraphicsImageRendererFormat *format =
35
35
  [UIGraphicsImageRendererFormat defaultFormat];
36
36
  format.opaque = NO;
37
-
38
- // Explicitly ask for the standard format to get ARGB 32bits and not 64bits.
39
- if (@available(iOS 12.0, *)) {
40
- format.preferredRange = UIGraphicsImageRendererFormatRangeStandard;
41
- } else {
42
- // Fallback on earlier versions
43
- format.prefersExtendedRange = false;
44
- }
37
+ format.preferredRange = UIGraphicsImageRendererFormatRangeStandard;
45
38
 
46
39
  UIGraphicsImageRenderer *renderer =
47
40
  [[UIGraphicsImageRenderer alloc] initWithSize:size format:format];
package/package.json CHANGED
@@ -7,7 +7,7 @@
7
7
  "setup-skia-web": "./scripts/setup-canvaskit.js"
8
8
  },
9
9
  "title": "React Native Skia",
10
- "version": "1.5.1",
10
+ "version": "1.5.2",
11
11
  "description": "High-performance React Native Graphics using Skia",
12
12
  "main": "lib/module/index.js",
13
13
  "react-native": "src/index.ts",