@shopify/react-native-skia 1.5.1 → 1.5.3
Sign up to get free protection for your applications and to get access to all the features.
- package/android/cpp/rnskia-android/OpenGLContext.h +40 -0
- package/android/cpp/rnskia-android/RNSkAndroidPlatformContext.h +5 -5
- package/android/cpp/rnskia-android/RNSkAndroidVideo.cpp +2 -2
- package/android/cpp/rnskia-android/RNSkOpenGLCanvasProvider.cpp +49 -14
- package/android/cpp/rnskia-android/RNSkOpenGLCanvasProvider.h +5 -2
- package/android/cpp/rnskia-android/SkiaOpenGLSurfaceFactory.cpp +19 -133
- package/android/cpp/rnskia-android/SkiaOpenGLSurfaceFactory.h +30 -138
- package/cpp/api/JsiSkTypefaceFontProvider.h +1 -1
- package/cpp/api/JsiSkiaContext.h +6 -3
- package/cpp/jsi/JsiValue.cpp +1 -2
- package/cpp/rnskia/RNSkPlatformContext.h +2 -2
- package/cpp/rnskia/{SkiaContext.h → WindowContext.h} +5 -2
- package/ios/RNSkia-iOS/MetalContext.h +46 -0
- package/ios/RNSkia-iOS/MetalContext.mm +33 -0
- package/ios/RNSkia-iOS/RNSkMetalCanvasProvider.mm +8 -28
- package/ios/RNSkia-iOS/RNSkiOSPlatformContext.h +1 -1
- package/ios/RNSkia-iOS/RNSkiOSPlatformContext.mm +8 -9
- package/ios/RNSkia-iOS/RNSkiOSView.mm +0 -2
- package/ios/RNSkia-iOS/SkiaMetalSurfaceFactory.h +28 -32
- package/ios/RNSkia-iOS/SkiaMetalSurfaceFactory.mm +18 -60
- package/ios/RNSkia-iOS/SkiaUIView.h +0 -2
- package/ios/RNSkia-iOS/ViewScreenshotService.mm +1 -8
- package/package.json +1 -1
@@ -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
|
54
|
+
return OpenGLContext::getInstance().MakeOffscreen(width, height);
|
55
55
|
}
|
56
56
|
|
57
|
-
std::shared_ptr<
|
57
|
+
std::shared_ptr<WindowContext>
|
58
58
|
makeContextFromNativeSurface(void *surface, int width, int height) override {
|
59
|
-
return
|
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
|
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
|
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
|
-
|
25
|
+
if (_surfaceHolder) {
|
26
|
+
return static_cast<float>(_surfaceHolder->getWidth());
|
27
|
+
}
|
28
|
+
return 0;
|
24
29
|
}
|
25
30
|
|
26
31
|
float RNSkOpenGLCanvasProvider::getScaledHeight() {
|
27
|
-
|
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
|
-
|
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
|
-
|
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
|
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
|
-
|
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 "
|
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<
|
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
|
-
|
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
|
-
|
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
|
-
|
73
|
-
|
74
|
-
|
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>
|
84
|
-
|
85
|
-
|
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
|
-
|
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
|
-
|
130
|
-
|
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
|
-
|
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
|
-
|
290
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
162
|
-
->flushAndSubmit();
|
52
|
+
_context->directContext->flushAndSubmit();
|
163
53
|
|
164
54
|
// Swap buffers
|
165
|
-
SkiaOpenGLHelper::swapBuffers(
|
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(
|
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,
|
189
|
-
|
190
|
-
|
191
|
-
|
192
|
-
|
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
|
-
|
43
|
+
getObject()->registerTypeface(typeface, familyName);
|
44
44
|
return jsi::Value::undefined();
|
45
45
|
}
|
46
46
|
|
package/cpp/api/JsiSkiaContext.h
CHANGED
@@ -14,7 +14,7 @@
|
|
14
14
|
#include "JsiSkRect.h"
|
15
15
|
#include "JsiSkTypeface.h"
|
16
16
|
|
17
|
-
#include "
|
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<
|
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<
|
54
|
+
std::shared_ptr<WindowContext> ctx)
|
52
55
|
: JsiSkWrappingSharedPtrHostObject(std::move(context), std::move(ctx)) {}
|
53
56
|
|
54
57
|
/**
|
package/cpp/jsi/JsiValue.cpp
CHANGED
@@ -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::
|
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 "
|
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<
|
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
|
15
|
+
class WindowContext {
|
16
16
|
public:
|
17
|
-
virtual ~
|
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 =
|
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
|
-
|
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
|
-
|
109
|
-
|
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<
|
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
|
-
|
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<
|
152
|
+
std::shared_ptr<WindowContext>
|
153
153
|
RNSkiOSPlatformContext::makeContextFromNativeSurface(void *surface, int width,
|
154
154
|
int height) {
|
155
|
-
return
|
156
|
-
|
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
|
165
|
+
return MetalContext::getInstance().MakeOffscreen(width, height);
|
166
166
|
}
|
167
167
|
|
168
168
|
sk_sp<SkImage> RNSkiOSPlatformContext::makeImageFromNativeBuffer(void *buffer) {
|
169
|
-
|
170
|
-
return SkiaMetalSurfaceFactory::makeTextureFromCVPixelBuffer(sampleBuffer);
|
169
|
+
return MetalContext::getInstance().MakeImageFromBuffer(buffer);
|
171
170
|
}
|
172
171
|
|
173
172
|
sk_sp<SkFontMgr> RNSkiOSPlatformContext::createFontMgr() {
|
@@ -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 "
|
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(
|
29
|
+
static sk_sp<SkSurface> makeWindowedSurface(SkiaMetalContext *context,
|
30
|
+
id<MTLTexture> texture, int width,
|
33
31
|
int height);
|
34
|
-
static sk_sp<SkSurface> makeOffscreenSurface(
|
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(
|
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
|
-
|
43
|
-
|
44
|
-
|
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::
|
45
|
+
class IOSSkiaContext : public RNSkia::WindowContext {
|
49
46
|
public:
|
50
|
-
IOSSkiaContext(CALayer *layer, int width,
|
51
|
-
|
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 =
|
57
|
+
_layer.contentsScale = [UIScreen mainScreen].scale;
|
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
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
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
|
-
|
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
|
-
|
90
|
-
|
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(
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
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
|
-
|
119
|
-
|
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
|
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
|
103
|
+
context->skContext.get(), pixelBuffer);
|
146
104
|
}
|
147
105
|
default:
|
148
106
|
[[unlikely]] {
|
@@ -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.
|
10
|
+
"version": "1.5.3",
|
11
11
|
"description": "High-performance React Native Graphics using Skia",
|
12
12
|
"main": "lib/module/index.js",
|
13
13
|
"react-native": "src/index.ts",
|