@shopify/react-native-skia 0.1.201 → 0.1.202
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/cpp/rnskia/RNSkView.h +5 -2
- package/ios/RNSkia-iOS/RNSkMetalCanvasProvider.h +5 -14
- package/ios/RNSkia-iOS/RNSkMetalCanvasProvider.mm +7 -56
- package/ios/RNSkia-iOS/RNSkiOSPlatformContext.mm +2 -2
- package/ios/RNSkia-iOS/SkiaMetalSurfaceFactory.h +31 -0
- package/ios/RNSkia-iOS/SkiaMetalSurfaceFactory.mm +105 -0
- package/package.json +1 -1
- package/ios/RNSkia-iOS/SkiaMetalRenderer.h +0 -5
- package/ios/RNSkia-iOS/SkiaMetalRenderer.mm +0 -55
package/cpp/rnskia/RNSkView.h
CHANGED
@@ -93,6 +93,7 @@ public:
|
|
93
93
|
float height)
|
94
94
|
: RNSkCanvasProvider(requestRedraw), _width(width), _height(height) {
|
95
95
|
_surface = context->makeOffscreenSurface(_width, _height);
|
96
|
+
_pd = context->getPixelDensity();
|
96
97
|
}
|
97
98
|
|
98
99
|
/**
|
@@ -101,8 +102,9 @@ public:
|
|
101
102
|
sk_sp<SkImage> makeSnapshot(SkRect *bounds) {
|
102
103
|
sk_sp<SkImage> image;
|
103
104
|
if (bounds != nullptr) {
|
104
|
-
SkIRect b =
|
105
|
-
|
105
|
+
SkIRect b =
|
106
|
+
SkIRect::MakeXYWH(bounds->x() * _pd, bounds->y() * _pd,
|
107
|
+
bounds->width() * _pd, bounds->height() * _pd);
|
106
108
|
image = _surface->makeImageSnapshot(b);
|
107
109
|
} else {
|
108
110
|
image = _surface->makeImageSnapshot();
|
@@ -131,6 +133,7 @@ public:
|
|
131
133
|
private:
|
132
134
|
float _width;
|
133
135
|
float _height;
|
136
|
+
float _pd = 1.0f;
|
134
137
|
sk_sp<SkSurface> _surface;
|
135
138
|
};
|
136
139
|
|
@@ -6,13 +6,12 @@
|
|
6
6
|
#import <MetalKit/MetalKit.h>
|
7
7
|
#import <QuartzCore/CAMetalLayer.h>
|
8
8
|
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
9
|
+
#pragma clang diagnostic push
|
10
|
+
#pragma clang diagnostic ignored "-Wdocumentation"
|
11
|
+
|
12
|
+
#import <include/gpu/GrDirectContext.h>
|
13
13
|
|
14
|
-
|
15
|
-
renderContexts;
|
14
|
+
#pragma clang diagnostic pop
|
16
15
|
|
17
16
|
class RNSkMetalCanvasProvider : public RNSkia::RNSkCanvasProvider {
|
18
17
|
public:
|
@@ -27,17 +26,9 @@ public:
|
|
27
26
|
bool renderToCanvas(const std::function<void(SkCanvas *)> &cb) override;
|
28
27
|
|
29
28
|
void setSize(int width, int height);
|
30
|
-
|
31
29
|
CALayer *getLayer();
|
32
30
|
|
33
31
|
private:
|
34
|
-
/**
|
35
|
-
* To be able to use static contexts (and avoid reloading the skia context for
|
36
|
-
* each new view, we track the Skia drawing context per thread.
|
37
|
-
* @return The drawing context for the current thread
|
38
|
-
*/
|
39
|
-
static std::shared_ptr<MetalRenderContext> getMetalRenderContext();
|
40
|
-
|
41
32
|
std::shared_ptr<RNSkia::RNSkPlatformContext> _context;
|
42
33
|
float _width = -1;
|
43
34
|
float _height = -1;
|
@@ -1,5 +1,6 @@
|
|
1
1
|
#import <RNSkLog.h>
|
2
2
|
#import <RNSkMetalCanvasProvider.h>
|
3
|
+
#import <SkiaMetalSurfaceFactory.h>
|
3
4
|
|
4
5
|
#pragma clang diagnostic push
|
5
6
|
#pragma clang diagnostic ignored "-Wdocumentation"
|
@@ -14,19 +15,6 @@
|
|
14
15
|
|
15
16
|
#pragma clang diagnostic pop
|
16
17
|
|
17
|
-
/** Static members */
|
18
|
-
std::shared_ptr<MetalRenderContext>
|
19
|
-
RNSkMetalCanvasProvider::getMetalRenderContext() {
|
20
|
-
auto threadId = std::this_thread::get_id();
|
21
|
-
if (renderContexts.count(threadId) == 0) {
|
22
|
-
auto drawingContext = std::make_shared<MetalRenderContext>();
|
23
|
-
drawingContext->commandQueue = nullptr;
|
24
|
-
drawingContext->skContext = nullptr;
|
25
|
-
renderContexts.emplace(threadId, drawingContext);
|
26
|
-
}
|
27
|
-
return renderContexts.at(threadId);
|
28
|
-
}
|
29
|
-
|
30
18
|
RNSkMetalCanvasProvider::RNSkMetalCanvasProvider(
|
31
19
|
std::function<void()> requestRedraw,
|
32
20
|
std::shared_ptr<RNSkia::RNSkPlatformContext> context)
|
@@ -35,11 +23,8 @@ RNSkMetalCanvasProvider::RNSkMetalCanvasProvider(
|
|
35
23
|
#pragma clang diagnostic ignored "-Wunguarded-availability-new"
|
36
24
|
_layer = [CAMetalLayer layer];
|
37
25
|
#pragma clang diagnostic pop
|
38
|
-
|
39
|
-
auto device = MTLCreateSystemDefaultDevice();
|
40
|
-
|
41
26
|
_layer.framebufferOnly = NO;
|
42
|
-
_layer.device =
|
27
|
+
_layer.device = MTLCreateSystemDefaultDevice();
|
43
28
|
_layer.opaque = false;
|
44
29
|
_layer.contentsScale = _context->getPixelDensity();
|
45
30
|
_layer.pixelFormat = MTLPixelFormatBGRA8Unorm;
|
@@ -87,52 +72,18 @@ bool RNSkMetalCanvasProvider::renderToCanvas(
|
|
87
72
|
return false;
|
88
73
|
}
|
89
74
|
}
|
90
|
-
|
91
|
-
// Get render context for current thread
|
92
|
-
auto renderContext = getMetalRenderContext();
|
93
|
-
|
94
|
-
if (renderContext->skContext == nullptr) {
|
95
|
-
auto device = MTLCreateSystemDefaultDevice();
|
96
|
-
renderContext->commandQueue =
|
97
|
-
id<MTLCommandQueue>(CFRetain((GrMTLHandle)[device newCommandQueue]));
|
98
|
-
renderContext->skContext = GrDirectContext::MakeMetal(
|
99
|
-
(__bridge void *)device, (__bridge void *)renderContext->commandQueue);
|
100
|
-
}
|
101
|
-
|
102
75
|
// Wrap in auto release pool since we want the system to clean up after
|
103
76
|
// rendering and not wait until later - we've seen some example of memory
|
104
77
|
// usage growing very fast in the simulator without this.
|
105
78
|
@autoreleasepool {
|
106
|
-
|
107
|
-
/* It is super important that we use the pattern of calling nextDrawable
|
108
|
-
inside this autoreleasepool and not depend on Skia's
|
109
|
-
SkSurface::MakeFromCAMetalLayer to encapsulate since we're seeing a lot of
|
110
|
-
drawables leaking if they're not done this way.
|
111
|
-
|
112
|
-
This is now reverted from:
|
113
|
-
(https://github.com/Shopify/react-native-skia/commit/2e2290f8e6dfc6921f97b79f779d920fbc1acceb)
|
114
|
-
back to the original implementation.
|
115
|
-
*/
|
116
79
|
id<CAMetalDrawable> currentDrawable = [_layer nextDrawable];
|
117
80
|
if (currentDrawable == nullptr) {
|
118
81
|
return false;
|
119
82
|
}
|
120
83
|
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
GrBackendRenderTarget backendRT(_layer.drawableSize.width,
|
125
|
-
_layer.drawableSize.height, 1, fbInfo);
|
126
|
-
|
127
|
-
auto skSurface = SkSurfaces::WrapBackendRenderTarget(
|
128
|
-
renderContext->skContext.get(), backendRT, kTopLeft_GrSurfaceOrigin,
|
129
|
-
kBGRA_8888_SkColorType, nullptr, nullptr);
|
130
|
-
|
131
|
-
if (skSurface == nullptr || skSurface->getCanvas() == nullptr) {
|
132
|
-
RNSkia::RNSkLogger::logToConsole(
|
133
|
-
"Skia surface could not be created from parameters.");
|
134
|
-
return false;
|
135
|
-
}
|
84
|
+
auto skSurface = SkiaMetalSurfaceFactory::makeWindowedSurface(
|
85
|
+
currentDrawable.texture, _layer.drawableSize.width,
|
86
|
+
_layer.drawableSize.height);
|
136
87
|
|
137
88
|
SkCanvas *canvas = skSurface->getCanvas();
|
138
89
|
cb(canvas);
|
@@ -140,11 +91,11 @@ bool RNSkMetalCanvasProvider::renderToCanvas(
|
|
140
91
|
skSurface->flushAndSubmit();
|
141
92
|
|
142
93
|
id<MTLCommandBuffer> commandBuffer(
|
143
|
-
[
|
94
|
+
[ThreadContextHolder::ThreadSkiaMetalContext
|
95
|
+
.commandQueue commandBuffer]);
|
144
96
|
[commandBuffer presentDrawable:currentDrawable];
|
145
97
|
[commandBuffer commit];
|
146
98
|
}
|
147
|
-
|
148
99
|
return true;
|
149
100
|
};
|
150
101
|
|
@@ -4,7 +4,7 @@
|
|
4
4
|
#include <thread>
|
5
5
|
#include <utility>
|
6
6
|
|
7
|
-
#include <
|
7
|
+
#include <SkiaMetalSurfaceFactory.h>
|
8
8
|
|
9
9
|
#pragma clang diagnostic push
|
10
10
|
#pragma clang diagnostic ignored "-Wdocumentation"
|
@@ -59,7 +59,7 @@ void RNSkiOSPlatformContext::raiseError(const std::exception &err) {
|
|
59
59
|
|
60
60
|
sk_sp<SkSurface> RNSkiOSPlatformContext::makeOffscreenSurface(int width,
|
61
61
|
int height) {
|
62
|
-
return
|
62
|
+
return SkiaMetalSurfaceFactory::makeOffscreenSurface(width, height);
|
63
63
|
}
|
64
64
|
|
65
65
|
void RNSkiOSPlatformContext::runOnMainThread(std::function<void()> func) {
|
@@ -0,0 +1,31 @@
|
|
1
|
+
#import <MetalKit/MetalKit.h>
|
2
|
+
|
3
|
+
#pragma clang diagnostic push
|
4
|
+
#pragma clang diagnostic ignored "-Wdocumentation"
|
5
|
+
|
6
|
+
#import "SkCanvas.h"
|
7
|
+
#import <include/gpu/GrDirectContext.h>
|
8
|
+
|
9
|
+
#pragma clang diagnostic pop
|
10
|
+
|
11
|
+
using SkiaMetalContext = struct SkiaMetalContext {
|
12
|
+
id<MTLCommandQueue> commandQueue = nullptr;
|
13
|
+
sk_sp<GrDirectContext> skContext = nullptr;
|
14
|
+
};
|
15
|
+
|
16
|
+
class ThreadContextHolder {
|
17
|
+
public:
|
18
|
+
static thread_local SkiaMetalContext ThreadSkiaMetalContext;
|
19
|
+
};
|
20
|
+
|
21
|
+
class SkiaMetalSurfaceFactory {
|
22
|
+
public:
|
23
|
+
static sk_sp<SkSurface> makeWindowedSurface(id<MTLTexture> texture, int width,
|
24
|
+
int height);
|
25
|
+
static sk_sp<SkSurface> makeOffscreenSurface(int width, int height);
|
26
|
+
|
27
|
+
private:
|
28
|
+
static id<MTLDevice> device;
|
29
|
+
static bool
|
30
|
+
createSkiaDirectContextIfNecessary(SkiaMetalContext *threadContext);
|
31
|
+
};
|
@@ -0,0 +1,105 @@
|
|
1
|
+
#import <RNSkLog.h>
|
2
|
+
|
3
|
+
#include <SkiaMetalSurfaceFactory.h>
|
4
|
+
|
5
|
+
#pragma clang diagnostic push
|
6
|
+
#pragma clang diagnostic ignored "-Wdocumentation"
|
7
|
+
|
8
|
+
#import "SkCanvas.h"
|
9
|
+
#import "SkColorSpace.h"
|
10
|
+
#import "SkSurface.h"
|
11
|
+
|
12
|
+
#import <include/gpu/GrBackendSurface.h>
|
13
|
+
#import <include/gpu/GrDirectContext.h>
|
14
|
+
#import <include/gpu/ganesh/SkSurfaceGanesh.h>
|
15
|
+
|
16
|
+
#pragma clang diagnostic pop
|
17
|
+
|
18
|
+
thread_local SkiaMetalContext ThreadContextHolder::ThreadSkiaMetalContext;
|
19
|
+
|
20
|
+
struct OffscreenRenderContext {
|
21
|
+
id<MTLTexture> texture;
|
22
|
+
|
23
|
+
OffscreenRenderContext(id<MTLDevice> device,
|
24
|
+
sk_sp<GrDirectContext> skiaContext,
|
25
|
+
id<MTLCommandQueue> commandQueue, int width,
|
26
|
+
int height) {
|
27
|
+
// Create a Metal texture descriptor
|
28
|
+
MTLTextureDescriptor *textureDescriptor = [MTLTextureDescriptor
|
29
|
+
texture2DDescriptorWithPixelFormat:MTLPixelFormatBGRA8Unorm
|
30
|
+
width:width
|
31
|
+
height:height
|
32
|
+
mipmapped:NO];
|
33
|
+
textureDescriptor.usage =
|
34
|
+
MTLTextureUsageRenderTarget | MTLTextureUsageShaderRead;
|
35
|
+
texture = [device newTextureWithDescriptor:textureDescriptor];
|
36
|
+
}
|
37
|
+
};
|
38
|
+
|
39
|
+
id<MTLDevice> SkiaMetalSurfaceFactory::device = MTLCreateSystemDefaultDevice();
|
40
|
+
|
41
|
+
bool SkiaMetalSurfaceFactory::createSkiaDirectContextIfNecessary(
|
42
|
+
SkiaMetalContext *skiaMetalContext) {
|
43
|
+
if (skiaMetalContext->skContext == nullptr) {
|
44
|
+
skiaMetalContext->commandQueue =
|
45
|
+
id<MTLCommandQueue>(CFRetain((GrMTLHandle)[device newCommandQueue]));
|
46
|
+
skiaMetalContext->skContext = GrDirectContext::MakeMetal(
|
47
|
+
(__bridge void *)device,
|
48
|
+
(__bridge void *)skiaMetalContext->commandQueue);
|
49
|
+
if (skiaMetalContext->skContext == nullptr) {
|
50
|
+
RNSkia::RNSkLogger::logToConsole("Couldn't create a Skia Metal Context");
|
51
|
+
return false;
|
52
|
+
}
|
53
|
+
}
|
54
|
+
return true;
|
55
|
+
}
|
56
|
+
|
57
|
+
sk_sp<SkSurface>
|
58
|
+
SkiaMetalSurfaceFactory::makeWindowedSurface(id<MTLTexture> texture, int width,
|
59
|
+
int height) {
|
60
|
+
// Get render context for current thread
|
61
|
+
if (!SkiaMetalSurfaceFactory::createSkiaDirectContextIfNecessary(
|
62
|
+
&ThreadContextHolder::ThreadSkiaMetalContext)) {
|
63
|
+
return nullptr;
|
64
|
+
}
|
65
|
+
GrMtlTextureInfo fbInfo;
|
66
|
+
fbInfo.fTexture.retain((__bridge void *)texture);
|
67
|
+
|
68
|
+
GrBackendRenderTarget backendRT(width, height, 1, fbInfo);
|
69
|
+
|
70
|
+
auto skSurface = SkSurfaces::WrapBackendRenderTarget(
|
71
|
+
ThreadContextHolder::ThreadSkiaMetalContext.skContext.get(), backendRT,
|
72
|
+
kTopLeft_GrSurfaceOrigin, kBGRA_8888_SkColorType, nullptr, nullptr);
|
73
|
+
|
74
|
+
if (skSurface == nullptr || skSurface->getCanvas() == nullptr) {
|
75
|
+
RNSkia::RNSkLogger::logToConsole(
|
76
|
+
"Skia surface could not be created from parameters.");
|
77
|
+
return nullptr;
|
78
|
+
}
|
79
|
+
return skSurface;
|
80
|
+
}
|
81
|
+
|
82
|
+
sk_sp<SkSurface> SkiaMetalSurfaceFactory::makeOffscreenSurface(int width,
|
83
|
+
int height) {
|
84
|
+
if (!SkiaMetalSurfaceFactory::createSkiaDirectContextIfNecessary(
|
85
|
+
&ThreadContextHolder::ThreadSkiaMetalContext)) {
|
86
|
+
return nullptr;
|
87
|
+
}
|
88
|
+
auto ctx = new OffscreenRenderContext(
|
89
|
+
device, ThreadContextHolder::ThreadSkiaMetalContext.skContext,
|
90
|
+
ThreadContextHolder::ThreadSkiaMetalContext.commandQueue, width, height);
|
91
|
+
|
92
|
+
// Create a GrBackendTexture from the Metal texture
|
93
|
+
GrMtlTextureInfo info;
|
94
|
+
info.fTexture.retain((__bridge void *)ctx->texture);
|
95
|
+
GrBackendTexture backendTexture(width, height, GrMipMapped::kNo, info);
|
96
|
+
|
97
|
+
// Create a SkSurface from the GrBackendTexture
|
98
|
+
auto surface = SkSurfaces::WrapBackendTexture(
|
99
|
+
ThreadContextHolder::ThreadSkiaMetalContext.skContext.get(),
|
100
|
+
backendTexture, kTopLeft_GrSurfaceOrigin, 0, kBGRA_8888_SkColorType,
|
101
|
+
nullptr, nullptr,
|
102
|
+
[](void *addr) { delete (OffscreenRenderContext *)addr; }, ctx);
|
103
|
+
|
104
|
+
return surface;
|
105
|
+
}
|
package/package.json
CHANGED
@@ -1,55 +0,0 @@
|
|
1
|
-
#pragma clang diagnostic push
|
2
|
-
#pragma clang diagnostic ignored "-Wdocumentation"
|
3
|
-
|
4
|
-
#import "SkCanvas.h"
|
5
|
-
#import "SkColorSpace.h"
|
6
|
-
#import "SkSurface.h"
|
7
|
-
|
8
|
-
#import <include/gpu/GrBackendSurface.h>
|
9
|
-
#import <include/gpu/GrDirectContext.h>
|
10
|
-
#import <include/gpu/ganesh/SkSurfaceGanesh.h>
|
11
|
-
|
12
|
-
#pragma clang diagnostic pop
|
13
|
-
|
14
|
-
#import <MetalKit/MetalKit.h>
|
15
|
-
|
16
|
-
struct OffscreenRenderContext {
|
17
|
-
id<MTLDevice> device;
|
18
|
-
id<MTLCommandQueue> commandQueue;
|
19
|
-
sk_sp<GrDirectContext> skiaContext;
|
20
|
-
id<MTLTexture> texture;
|
21
|
-
|
22
|
-
OffscreenRenderContext(int width, int height) {
|
23
|
-
device = MTLCreateSystemDefaultDevice();
|
24
|
-
commandQueue =
|
25
|
-
id<MTLCommandQueue>(CFRetain((GrMTLHandle)[device newCommandQueue]));
|
26
|
-
skiaContext = GrDirectContext::MakeMetal((__bridge void *)device,
|
27
|
-
(__bridge void *)commandQueue);
|
28
|
-
// Create a Metal texture descriptor
|
29
|
-
MTLTextureDescriptor *textureDescriptor = [MTLTextureDescriptor
|
30
|
-
texture2DDescriptorWithPixelFormat:MTLPixelFormatBGRA8Unorm
|
31
|
-
width:width
|
32
|
-
height:height
|
33
|
-
mipmapped:NO];
|
34
|
-
textureDescriptor.usage =
|
35
|
-
MTLTextureUsageRenderTarget | MTLTextureUsageShaderRead;
|
36
|
-
texture = [device newTextureWithDescriptor:textureDescriptor];
|
37
|
-
}
|
38
|
-
};
|
39
|
-
|
40
|
-
sk_sp<SkSurface> MakeOffscreenMetalSurface(int width, int height) {
|
41
|
-
auto ctx = new OffscreenRenderContext(width, height);
|
42
|
-
|
43
|
-
// Create a GrBackendTexture from the Metal texture
|
44
|
-
GrMtlTextureInfo info;
|
45
|
-
info.fTexture.retain((__bridge void *)ctx->texture);
|
46
|
-
GrBackendTexture backendTexture(width, height, GrMipMapped::kNo, info);
|
47
|
-
|
48
|
-
// Create a SkSurface from the GrBackendTexture
|
49
|
-
auto surface = SkSurfaces::WrapBackendTexture(
|
50
|
-
ctx->skiaContext.get(), backendTexture, kTopLeft_GrSurfaceOrigin, 0,
|
51
|
-
kBGRA_8888_SkColorType, nullptr, nullptr,
|
52
|
-
[](void *addr) { delete (OffscreenRenderContext *)addr; }, ctx);
|
53
|
-
|
54
|
-
return surface;
|
55
|
-
}
|