@shopify/react-native-skia 0.1.193 → 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;
@@ -58,123 +58,124 @@ public class ViewScreenshotService {
58
58
  paint.setDither(true);
59
59
 
60
60
  // Render the main view and its children
61
- final Canvas c = new Canvas(bitmap);
62
- view.draw(c);
61
+ final Canvas canvas = new Canvas(bitmap);
63
62
 
64
- // Enumerate children
65
- final List<View> childrenList = getAllChildren(view);
63
+ // Renders view with child views to canvas
64
+ renderViewToCanvas(canvas, view, paint);
66
65
 
67
- for (final View child : childrenList) {
68
- // skip any child that we don't know how to process
69
- if (child instanceof TextureView) {
70
- // skip all invisible to user child views
71
- if (child.getVisibility() != VISIBLE) continue;
66
+ return bitmap;
67
+ }
72
68
 
73
- final TextureView tvChild = (TextureView) child;
74
- tvChild.setOpaque(false); // <-- switch off background fill
75
-
76
- // TextureView should use bitmaps with matching size,
77
- // otherwise content of the TextureView will be scaled to provided bitmap dimensions
78
- final Bitmap childBitmapBuffer = tvChild.getBitmap(Bitmap.createBitmap(child.getWidth(), child.getHeight(), Bitmap.Config.ARGB_8888));
79
-
80
- final int countCanvasSave = c.save();
81
- applyTransformations(c, view, child);
82
-
83
- // due to re-use of bitmaps for screenshot, we can get bitmap that is bigger in size than requested
84
- c.drawBitmap(childBitmapBuffer, 0, 0, paint);
85
-
86
- c.restoreToCount(countCanvasSave);
87
- } else if (child instanceof SurfaceView) {
88
- final SurfaceView svChild = (SurfaceView)child;
89
- final CountDownLatch latch = new CountDownLatch(1);
90
-
91
- if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
92
- final Bitmap childBitmapBuffer = Bitmap.createBitmap(child.getWidth(), child.getHeight(), Bitmap.Config.ARGB_8888);
93
- try {
94
- PixelCopy.request(svChild, childBitmapBuffer, new PixelCopy.OnPixelCopyFinishedListener() {
95
- @Override
96
- public void onPixelCopyFinished(int copyResult) {
97
- final int countCanvasSave = c.save();
98
- applyTransformations(c, view, child);
99
- c.drawBitmap(childBitmapBuffer, 0, 0, paint);
100
- c.restoreToCount(countCanvasSave);
101
- latch.countDown();
102
- }
103
- }, new Handler(Looper.getMainLooper()));
104
- latch.await(SURFACE_VIEW_READ_PIXELS_TIMEOUT, TimeUnit.SECONDS);
105
- } catch (Exception e) {
106
- Log.e(TAG, "Cannot PixelCopy for " + svChild, e);
107
- }
108
- } else {
109
- Bitmap cache = svChild.getDrawingCache();
110
- if (cache != null) {
111
- c.drawBitmap(svChild.getDrawingCache(), 0, 0, paint);
112
- }
69
+ private static void renderViewToCanvas(Canvas canvas, View view, Paint paint) {
70
+ // Apply transformations for the current view
71
+ canvas.save();
72
+ applyTransformations(canvas, view);
73
+
74
+ // Draw children if the view has children
75
+ if ((view instanceof ViewGroup)) {
76
+ // Draw children
77
+ ViewGroup group = (ViewGroup) view;
78
+
79
+ // Hide visible children - this needs to be done because view.draw(canvas)
80
+ // will render all visible non-texture/surface views directly - causing
81
+ // views to be rendered twice - once by view.draw() and once when we
82
+ // enumerate children. We therefore need to turn off rendering of visible
83
+ // children before we call view.draw:
84
+ List<View> visibleChildren = new ArrayList<>();
85
+ for (int i = 0; i < group.getChildCount(); i++) {
86
+ View child = group.getChildAt(i);
87
+ if (child.getVisibility() == VISIBLE) {
88
+ visibleChildren.add(child);
89
+ child.setVisibility(View.INVISIBLE);
113
90
  }
114
91
  }
115
- }
116
-
117
- return bitmap;
118
- }
119
92
 
120
- private static List<View> getAllChildren(@NonNull final View v) {
121
- if (!(v instanceof ViewGroup)) {
122
- final ArrayList<View> viewArrayList = new ArrayList<>();
123
- viewArrayList.add(v);
93
+ // Draw ourselves
94
+ view.draw(canvas);
124
95
 
125
- return viewArrayList;
126
- }
96
+ // Enable children again
97
+ for (int i = 0; i < visibleChildren.size(); i++) {
98
+ View child = visibleChildren.get(i);
99
+ child.setVisibility(VISIBLE);
100
+ }
127
101
 
128
- final ArrayList<View> result = new ArrayList<>();
102
+ // Draw children
103
+ for (int i = 0; i < group.getChildCount(); i++) {
104
+ View child = group.getChildAt(i);
129
105
 
130
- ViewGroup viewGroup = (ViewGroup) v;
131
- for (int i = 0; i < viewGroup.getChildCount(); i++) {
132
- View child = viewGroup.getChildAt(i);
106
+ // skip all invisible to user child views
107
+ if (child.getVisibility() != VISIBLE) continue;
133
108
 
134
- //Do not add any parents, just add child elements
135
- result.addAll(getAllChildren(child));
109
+ // skip any child that we don't know how to process
110
+ if (child instanceof TextureView) {
111
+ final TextureView tvChild = (TextureView) child;
112
+ tvChild.setOpaque(false); // <-- switch off background fill
113
+
114
+ canvas.save();
115
+ applyTransformations(canvas, child);
116
+
117
+ // TextureView should use bitmaps with matching size,
118
+ // otherwise content of the TextureView will be scaled to provided bitmap dimensions
119
+ final Bitmap childBitmapBuffer = tvChild.getBitmap(Bitmap.createBitmap(child.getWidth(), child.getHeight(), Bitmap.Config.ARGB_8888));
120
+ canvas.drawBitmap(childBitmapBuffer, 0, 0, paint);
121
+
122
+ canvas.restore();
123
+
124
+ } else if (child instanceof SurfaceView) {
125
+ final SurfaceView svChild = (SurfaceView) child;
126
+ final CountDownLatch latch = new CountDownLatch(1);
127
+
128
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
129
+ final Bitmap childBitmapBuffer = Bitmap.createBitmap(child.getWidth(), child.getHeight(), Bitmap.Config.ARGB_8888);
130
+ try {
131
+ PixelCopy.request(svChild, childBitmapBuffer, copyResult -> {
132
+ canvas.save();
133
+ applyTransformations(canvas, child);
134
+ canvas.drawBitmap(childBitmapBuffer, 0, 0, paint);
135
+ canvas.restore();
136
+ latch.countDown();
137
+ }, new Handler(Looper.getMainLooper()));
138
+ latch.await(SURFACE_VIEW_READ_PIXELS_TIMEOUT, TimeUnit.SECONDS);
139
+ } catch (Exception e) {
140
+ Log.e(TAG, "Cannot PixelCopy for " + svChild, e);
141
+ }
142
+ } else {
143
+ Bitmap cache = svChild.getDrawingCache();
144
+ if (cache != null) {
145
+ canvas.save();
146
+ applyTransformations(canvas, child);
147
+ canvas.drawBitmap(svChild.getDrawingCache(), 0, 0, paint);
148
+ canvas.restore();
149
+ }
150
+ }
151
+ } else {
152
+ // Regular views needs to be rendered again to ensure correct z-index
153
+ // order with texture views and surface views.
154
+ renderViewToCanvas(canvas, child, paint);
155
+ }
156
+ }
157
+ } else {
158
+ // Draw ourselves
159
+ view.draw(canvas);
136
160
  }
137
161
 
138
- return result;
162
+ // Restore canvas
163
+ canvas.restore();
139
164
  }
140
165
 
141
- /**
142
- * Concat all the transformation matrix's from parent to child.
143
- */
144
166
  @NonNull
145
- @SuppressWarnings("UnusedReturnValue")
146
- private static Matrix applyTransformations(final Canvas c, @NonNull final View root, @NonNull final View child) {
147
- final Matrix transform = new Matrix();
148
- final LinkedList<View> ms = new LinkedList<>();
149
-
150
- // find all parents of the child view
151
- View iterator = child;
152
- do {
153
- ms.add(iterator);
154
-
155
- iterator = (View) iterator.getParent();
156
- } while (iterator != root);
157
-
158
- // apply transformations from parent --> child order
159
- Collections.reverse(ms);
160
-
161
- for (final View v : ms) {
162
- c.save();
163
-
164
- // apply each view transformations, so each child will be affected by them
165
- final float dx = v.getLeft() + ((v != child) ? v.getPaddingLeft() : 0) + v.getTranslationX();
166
- final float dy = v.getTop() + ((v != child) ? v.getPaddingTop() : 0) + v.getTranslationY();
167
- c.translate(dx, dy);
168
- c.rotate(v.getRotation(), v.getPivotX(), v.getPivotY());
169
- c.scale(v.getScaleX(), v.getScaleY());
170
-
171
- // compute the matrix just for any future use
172
- transform.postTranslate(dx, dy);
173
- transform.postRotate(v.getRotation(), v.getPivotX(), v.getPivotY());
174
- transform.postScale(v.getScaleX(), v.getScaleY());
175
- }
176
-
177
- return transform;
167
+ private static void applyTransformations(final Canvas c, @NonNull final View view) {
168
+ // Get the transformation matrix of the view
169
+ final Matrix matrix = view.getMatrix();
170
+
171
+ // Create a new matrix for translation
172
+ final Matrix translateMatrix = new Matrix();
173
+ final float dx = view.getLeft() + view.getPaddingLeft() + view.getTranslationX();
174
+ final float dy = view.getTop() + view.getPaddingTop() + view.getTranslationY();
175
+ translateMatrix.setTranslate(dx, dy);
176
+
177
+ // Pre-concatenate the current matrix of the canvas with the translation and transformation matrices of the view
178
+ c.concat(translateMatrix);
179
+ c.concat(matrix);
178
180
  }
179
-
180
181
  }
@@ -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
@@ -30,7 +30,9 @@ protected:
30
30
  #endif
31
31
  // Save paint if the paint property is set
32
32
  if (_paintProp->isSet()) {
33
- draw(_paintProp->getUnsafeDerivedValue().get());
33
+ auto localCtx = _paintProp->getUnsafeDerivedValue().get();
34
+ localCtx->setCanvas(context->getCanvas());
35
+ draw(localCtx);
34
36
  } else {
35
37
  // Call abstract draw method
36
38
  draw(context);
@@ -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
@@ -77,13 +77,12 @@ void RNSkMetalCanvasProvider::renderToCanvas(
77
77
  // accessed from the main thread so we need to check here.
78
78
  if ([[NSThread currentThread] isMainThread]) {
79
79
  auto state = UIApplication.sharedApplication.applicationState;
80
- if (state == UIApplicationStateBackground ||
81
- state == UIApplicationStateInactive) {
80
+ if (state == UIApplicationStateBackground) {
82
81
  // Request a redraw in the next run loop callback
83
82
  _requestRedraw();
84
83
  // and don't draw now since it might cause errors in the metal renderer if
85
84
  // we try to render while in the background. (see above issue)
86
- return;
85
+ return false;
87
86
  }
88
87
  }
89
88
 
@@ -114,7 +113,7 @@ void RNSkMetalCanvasProvider::renderToCanvas(
114
113
  */
115
114
  id<CAMetalDrawable> currentDrawable = [_layer nextDrawable];
116
115
  if (currentDrawable == nullptr) {
117
- return;
116
+ return false;
118
117
  }
119
118
 
120
119
  GrMtlTextureInfo fbInfo;
@@ -130,7 +129,7 @@ void RNSkMetalCanvasProvider::renderToCanvas(
130
129
  if (skSurface == nullptr || skSurface->getCanvas() == nullptr) {
131
130
  RNSkia::RNSkLogger::logToConsole(
132
131
  "Skia surface could not be created from parameters.");
133
- return;
132
+ return false;
134
133
  }
135
134
 
136
135
  SkCanvas *canvas = skSurface->getCanvas();
@@ -143,6 +142,8 @@ void RNSkMetalCanvasProvider::renderToCanvas(
143
142
  [commandBuffer presentDrawable:currentDrawable];
144
143
  [commandBuffer commit];
145
144
  }
145
+
146
+ return true;
146
147
  };
147
148
 
148
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.193",
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": [