@shopify/react-native-skia 0.1.194 → 0.1.195

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