@shopify/react-native-skia 0.1.201 → 0.1.202

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