@shopify/react-native-skia 0.1.194 → 0.1.195

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.
@@ -42,6 +42,10 @@ public:
42
42
  void surfaceAvailable(jobject surface, int width, int height) override {
43
43
  std::static_pointer_cast<RNSkOpenGLCanvasProvider>(T::getCanvasProvider())
44
44
  ->surfaceAvailable(surface, width, height);
45
+
46
+ // Try to render directly when the surface has been set so that
47
+ // we don't have to wait until the draw loop returns.
48
+ RNSkView::renderImmediate();
45
49
  }
46
50
 
47
51
  void surfaceDestroyed() override {
@@ -23,11 +23,12 @@ float RNSkOpenGLCanvasProvider::getScaledWidth() { return _width; }
23
23
 
24
24
  float RNSkOpenGLCanvasProvider::getScaledHeight() { return _height; }
25
25
 
26
- void RNSkOpenGLCanvasProvider::renderToCanvas(
26
+ bool RNSkOpenGLCanvasProvider::renderToCanvas(
27
27
  const std::function<void(SkCanvas *)> &cb) {
28
28
  if (_renderer != nullptr) {
29
- _renderer->run(cb, _width, _height);
29
+ return _renderer->run(cb, _width, _height);
30
30
  }
31
+ return false;
31
32
  }
32
33
 
33
34
  void RNSkOpenGLCanvasProvider::surfaceAvailable(jobject surface, int width,
@@ -25,7 +25,7 @@ public:
25
25
 
26
26
  float getScaledHeight() override;
27
27
 
28
- void renderToCanvas(const std::function<void(SkCanvas *)> &cb) override;
28
+ bool renderToCanvas(const std::function<void(SkCanvas *)> &cb) override;
29
29
 
30
30
  void surfaceAvailable(jobject surface, int width, int height);
31
31
 
@@ -4,6 +4,8 @@
4
4
  #include <android/native_window.h>
5
5
  #include <android/native_window_jni.h>
6
6
 
7
+ #define STENCIL_BUFFER_SIZE 8
8
+
7
9
  namespace RNSkia {
8
10
  /** Static members */
9
11
  sk_sp<SkSurface> MakeOffscreenGLSurface(int width, int height) {
@@ -137,7 +139,7 @@ SkiaOpenGLRenderer::~SkiaOpenGLRenderer() {
137
139
  _nativeWindow = nullptr;
138
140
  }
139
141
 
140
- void SkiaOpenGLRenderer::run(const std::function<void(SkCanvas *)> &cb,
142
+ bool SkiaOpenGLRenderer::run(const std::function<void(SkCanvas *)> &cb,
141
143
  int width, int height) {
142
144
  switch (_renderState) {
143
145
  case RenderState::Initializing: {
@@ -148,31 +150,48 @@ void SkiaOpenGLRenderer::run(const std::function<void(SkCanvas *)> &cb,
148
150
  case RenderState::Rendering: {
149
151
  // Make sure to initialize the rendering pipeline
150
152
  if (!ensureInitialised()) {
151
- break;
152
- }
153
-
154
- // Ensure we have the Skia surface to draw on. We need to
155
- // pass width and height since the surface will be recreated
156
- // when the view is resized.
157
- if (!ensureSkiaSurface(width, height)) {
158
- return;
153
+ return false;
159
154
  }
160
155
 
161
156
  if (cb != nullptr) {
162
- // Reset Skia Context since it might be modified by another Skia View
163
- // during rendering.
157
+ // RNSkLogger::logToConsole("SKIARENDER - Render begin");
158
+
164
159
  getThreadDrawingContext()->skContext->resetContext();
165
160
 
161
+ SkColorType colorType;
162
+ // setup surface for fbo0
163
+ GrGLFramebufferInfo fboInfo;
164
+ fboInfo.fFBOID = 0;
165
+ fboInfo.fFormat = 0x8058;
166
+ colorType = kN32_SkColorType;
167
+
168
+ GrBackendRenderTarget backendRT(width, height, 0, STENCIL_BUFFER_SIZE,
169
+ fboInfo);
170
+
171
+ SkSurfaceProps props(0, kUnknown_SkPixelGeometry);
172
+
173
+ sk_sp<SkSurface> renderTarget(SkSurface::MakeFromBackendRenderTarget(
174
+ getThreadDrawingContext()->skContext.get(), backendRT,
175
+ kBottomLeft_GrSurfaceOrigin, colorType, nullptr, &props));
176
+
177
+ auto canvas = renderTarget->getCanvas();
178
+
166
179
  // Draw picture into surface
167
- cb(_skSurface->getCanvas());
180
+ cb(canvas);
181
+
168
182
  // Flush
169
- _skSurface->flushAndSubmit();
183
+ canvas->flush();
170
184
 
171
185
  if (!eglSwapBuffers(getThreadDrawingContext()->glDisplay, _glSurface)) {
172
186
  RNSkLogger::logToConsole("eglSwapBuffers failed: %d\n", eglGetError());
187
+ return false;
173
188
  }
189
+
190
+ // RNSkLogger::logToConsole("SKIARENDER - render done");
191
+ return true;
174
192
  }
175
- break;
193
+
194
+ return false;
176
195
  }
177
196
  case RenderState::Finishing: {
178
197
  _renderState = RenderState::Done;
@@ -184,14 +203,11 @@ void SkiaOpenGLRenderer::run(const std::function<void(SkCanvas *)> &cb,
184
203
  _glSurface = EGL_NO_SURFACE;
185
204
  }
186
205
 
187
- // Release Skia Surface
188
- _skSurface = nullptr;
189
-
190
- break;
206
+ return true;
191
207
  }
192
208
  case RenderState::Done: {
193
209
  // Do nothing. We're done.
194
- break;
210
+ return true;
195
211
  }
196
212
  }
197
213
  }
@@ -326,54 +342,4 @@ bool SkiaOpenGLRenderer::initGLSurface() {
326
342
 
327
343
  return true;
328
344
  }
329
-
330
- bool SkiaOpenGLRenderer::ensureSkiaSurface(int width, int height) {
331
- if (getThreadDrawingContext()->skContext == nullptr) {
332
- return false;
333
- }
334
-
335
- if (_skSurface == nullptr || !_skRenderTarget.isValid() ||
336
- _prevWidth != width || _prevHeight != height) {
337
- glViewport(0, 0, width, height);
338
-
339
- _prevWidth = width;
340
- _prevHeight = height;
341
-
342
- GLint buffer;
343
- glGetIntegerv(GL_FRAMEBUFFER_BINDING, &buffer);
344
-
345
- GLint stencil;
346
- glGetIntegerv(GL_STENCIL_BITS, &stencil);
347
-
348
- GLint samples;
349
- glGetIntegerv(GL_SAMPLES, &samples);
350
-
351
- auto maxSamples =
352
- getThreadDrawingContext()->skContext->maxSurfaceSampleCountForColorType(
353
- kRGBA_8888_SkColorType);
354
-
355
- if (samples > maxSamples)
356
- samples = maxSamples;
357
-
358
- GrGLFramebufferInfo fbInfo;
359
- fbInfo.fFBOID = buffer;
360
- fbInfo.fFormat = 0x8058;
361
-
362
- _skRenderTarget =
363
- GrBackendRenderTarget(width, height, samples, stencil, fbInfo);
364
-
365
- _skSurface = SkSurface::MakeFromBackendRenderTarget(
366
- getThreadDrawingContext()->skContext.get(), _skRenderTarget,
367
- kBottomLeft_GrSurfaceOrigin, kRGBA_8888_SkColorType, nullptr, nullptr);
368
-
369
- if (!_skSurface) {
370
- RNSkLogger::logToConsole(
371
- "JniSkiaDrawView::setupSurface - skSurface could not be created!");
372
- return false;
373
- }
374
-
375
- return true;
376
- }
377
- return true;
378
- }
379
345
  } // namespace RNSkia
@@ -60,7 +60,7 @@ public:
60
60
  * @param width Width of surface to render if there is a picture
61
61
  * @param height Height of surface to render if there is a picture
62
62
  */
63
- void run(const std::function<void(SkCanvas *)> &cb, int width, int height);
63
+ bool run(const std::function<void(SkCanvas *)> &cb, int width, int height);
64
64
 
65
65
  /**
66
66
  * Sets the state to finishing. Next time the renderer will be called it
@@ -102,15 +102,6 @@ private:
102
102
  */
103
103
  bool initGLSurface();
104
104
 
105
- /**
106
- * Ensures that we have a valid Skia surface to draw to. The surface will
107
- * be recreated if the width/height change.
108
- * @param width Width of the underlying view
109
- * @param height Height of the underlying view
110
- * @return True if initialization went well
111
- */
112
- bool ensureSkiaSurface(int width, int height);
113
-
114
105
  /**
115
106
  * To be able to use static contexts (and avoid reloading the skia context for
116
107
  * each new view, we track the OpenGL and Skia drawing context per thread.
@@ -121,8 +112,6 @@ private:
121
112
  EGLSurface _glSurface = EGL_NO_SURFACE;
122
113
 
123
114
  ANativeWindow *_nativeWindow = nullptr;
124
- GrBackendRenderTarget _skRenderTarget;
125
- sk_sp<SkSurface> _skSurface;
126
115
 
127
116
  int _prevWidth = 0;
128
117
  int _prevHeight = 0;
@@ -36,15 +36,16 @@ bool RNSkDomRenderer::tryRender(
36
36
 
37
37
  // We render on the main thread
38
38
  if (_renderLock->try_lock()) {
39
+ bool result = false;
39
40
  // If we have a Dom Node we can render directly on the main thread
40
41
  if (_root != nullptr) {
41
- canvasProvider->renderToCanvas(std::bind(
42
+ result = canvasProvider->renderToCanvas(std::bind(
42
43
  &RNSkDomRenderer::renderCanvas, this, std::placeholders::_1,
43
44
  canvasProvider->getScaledWidth(), canvasProvider->getScaledHeight()));
44
45
  }
45
46
 
46
47
  _renderLock->unlock();
47
- return true;
48
+ return result;
48
49
  } else {
49
50
  return false;
50
51
  }
@@ -44,8 +44,7 @@ public:
44
44
  : RNSkRenderer(requestRedraw), _platformContext(context) {}
45
45
 
46
46
  bool tryRender(std::shared_ptr<RNSkCanvasProvider> canvasProvider) override {
47
- performDraw(canvasProvider);
48
- return true;
47
+ return performDraw(canvasProvider);
49
48
  }
50
49
 
51
50
  void
@@ -64,11 +63,7 @@ public:
64
63
  }
65
64
 
66
65
  private:
67
- void performDraw(std::shared_ptr<RNSkCanvasProvider> canvasProvider) {
68
- if (_picture == nullptr) {
69
- return;
70
- }
71
-
66
+ bool performDraw(std::shared_ptr<RNSkCanvasProvider> canvasProvider) {
72
67
  canvasProvider->renderToCanvas([=](SkCanvas *canvas) {
73
68
  // Make sure to scale correctly
74
69
  auto pd = _platformContext->getPixelDensity();
@@ -76,10 +71,13 @@ private:
76
71
  canvas->save();
77
72
  canvas->scale(pd, pd);
78
73
 
79
- canvas->drawPicture(_picture->getObject());
74
+ if (_picture != nullptr) {
75
+ canvas->drawPicture(_picture->getObject());
76
+ }
80
77
 
81
78
  canvas->restore();
82
79
  });
80
+ return true;
83
81
  }
84
82
 
85
83
  std::shared_ptr<RNSkPlatformContext> _platformContext;
@@ -44,7 +44,7 @@ public:
44
44
  /**
45
45
  Render to a canvas
46
46
  */
47
- virtual void renderToCanvas(const std::function<void(SkCanvas *)> &) = 0;
47
+ virtual bool renderToCanvas(const std::function<void(SkCanvas *)> &) = 0;
48
48
 
49
49
  protected:
50
50
  std::function<void()> _requestRedraw;
@@ -123,8 +123,9 @@ public:
123
123
  /**
124
124
  Render to a canvas
125
125
  */
126
- void renderToCanvas(const std::function<void(SkCanvas *)> &cb) override {
126
+ bool renderToCanvas(const std::function<void(SkCanvas *)> &cb) override {
127
127
  cb(_surface->getCanvas());
128
+ return true;
128
129
  };
129
130
 
130
131
  private:
@@ -224,6 +225,15 @@ public:
224
225
  */
225
226
  void requestRedraw() { _redrawRequestCounter++; }
226
227
 
228
+ /**
229
+ Renders immediate. Be carefull to not call this method from another thread
230
+ than the UI thread
231
+ */
232
+ void renderImmediate() {
233
+ _renderer->renderImmediate(_canvasProvider);
234
+ _redrawRequestCounter = 0;
235
+ }
236
+
227
237
  /**
228
238
  Sets the native id of the view
229
239
  */
@@ -409,6 +419,7 @@ private:
409
419
 
410
420
  size_t _drawingLoopId = 0;
411
421
  std::atomic<int> _redrawRequestCounter = {1};
422
+ bool _initialDrawingDone = false;
412
423
  };
413
424
 
414
425
  } // namespace RNSkia
@@ -24,7 +24,7 @@ public:
24
24
  float getScaledWidth() override;
25
25
  float getScaledHeight() override;
26
26
 
27
- void renderToCanvas(const std::function<void(SkCanvas *)> &cb) override;
27
+ bool renderToCanvas(const std::function<void(SkCanvas *)> &cb) override;
28
28
 
29
29
  void setSize(int width, int height);
30
30
 
@@ -63,10 +63,10 @@ float RNSkMetalCanvasProvider::getScaledHeight() {
63
63
  /**
64
64
  Render to a canvas
65
65
  */
66
- void RNSkMetalCanvasProvider::renderToCanvas(
66
+ bool RNSkMetalCanvasProvider::renderToCanvas(
67
67
  const std::function<void(SkCanvas *)> &cb) {
68
68
  if (_width <= 0 || _height <= 0) {
69
- return;
69
+ return false;
70
70
  }
71
71
 
72
72
  // Make sure to NOT render or try any render operations while we're in the
@@ -82,7 +82,7 @@ void RNSkMetalCanvasProvider::renderToCanvas(
82
82
  _requestRedraw();
83
83
  // and don't draw now since it might cause errors in the metal renderer if
84
84
  // we try to render while in the background. (see above issue)
85
- return;
85
+ return false;
86
86
  }
87
87
  }
88
88
 
@@ -113,7 +113,7 @@ void RNSkMetalCanvasProvider::renderToCanvas(
113
113
  */
114
114
  id<CAMetalDrawable> currentDrawable = [_layer nextDrawable];
115
115
  if (currentDrawable == nullptr) {
116
- return;
116
+ return false;
117
117
  }
118
118
 
119
119
  GrMtlTextureInfo fbInfo;
@@ -129,7 +129,7 @@ void RNSkMetalCanvasProvider::renderToCanvas(
129
129
  if (skSurface == nullptr || skSurface->getCanvas() == nullptr) {
130
130
  RNSkia::RNSkLogger::logToConsole(
131
131
  "Skia surface could not be created from parameters.");
132
- return;
132
+ return false;
133
133
  }
134
134
 
135
135
  SkCanvas *canvas = skSurface->getCanvas();
@@ -142,6 +142,8 @@ void RNSkMetalCanvasProvider::renderToCanvas(
142
142
  [commandBuffer presentDrawable:currentDrawable];
143
143
  [commandBuffer commit];
144
144
  }
145
+
146
+ return true;
145
147
  };
146
148
 
147
149
  void RNSkMetalCanvasProvider::setSize(int width, int height) {
@@ -93,6 +93,16 @@
93
93
  assert(_impl == nullptr);
94
94
  }
95
95
 
96
+ #pragma Render
97
+
98
+ - (void)drawRect:(CGRect)rect {
99
+ // We override drawRect to ensure we to direct rendering when the
100
+ // underlying OS view needs to render:
101
+ if (_impl != nullptr) {
102
+ _impl->getDrawView()->renderImmediate();
103
+ }
104
+ }
105
+
96
106
  #pragma mark Layout
97
107
 
98
108
  - (void)layoutSubviews {
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.194",
10
+ "version": "0.1.195",
11
11
  "description": "High-performance React Native Graphics using Skia",
12
12
  "main": "lib/module/index.js",
13
13
  "files": [