@shopify/react-native-skia 1.5.1 → 1.5.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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 = 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
|
-
|
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.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",
|