@shopify/react-native-skia 1.5.1 → 1.5.2

Sign up to get free protection for your applications and to get access to all the features.
@@ -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",