@shopify/react-native-skia 0.1.193 → 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;
@@ -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": [