@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.
@@ -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 = SkIRect::MakeXYWH(bounds->x(), bounds->y(), bounds->width(),
105
- bounds->height());
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
- using MetalRenderContext = struct {
10
- id<MTLCommandQueue> commandQueue;
11
- sk_sp<GrDirectContext> skContext;
12
- };
9
+ #pragma clang diagnostic push
10
+ #pragma clang diagnostic ignored "-Wdocumentation"
11
+
12
+ #import <include/gpu/GrDirectContext.h>
13
13
 
14
- static std::unordered_map<std::thread::id, std::shared_ptr<MetalRenderContext>>
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 = 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
- GrMtlTextureInfo fbInfo;
122
- fbInfo.fTexture.retain((__bridge void *)currentDrawable.texture);
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
- [renderContext->commandQueue commandBuffer]);
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 <SkiaMetalRenderer.h>
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 MakeOffscreenMetalSurface(width, height);
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
@@ -7,7 +7,7 @@
7
7
  "setup-skia-web": "./scripts/setup-canvaskit.js"
8
8
  },
9
9
  "title": "React Native Skia",
10
- "version": "0.1.201",
10
+ "version": "0.1.202",
11
11
  "description": "High-performance React Native Graphics using Skia",
12
12
  "main": "lib/module/index.js",
13
13
  "files": [
@@ -1,5 +0,0 @@
1
- #pragma once
2
-
3
- #include "SkSurface.h"
4
-
5
- sk_sp<SkSurface> MakeOffscreenMetalSurface(int width, int height);
@@ -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
- }