Skip to content

Commit 95d98b1

Browse files
authored
Update rendering logic on Android (#1980)
1 parent 80911b0 commit 95d98b1

File tree

8 files changed

+65
-28
lines changed

8 files changed

+65
-28
lines changed

example/android/build.gradle

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ buildscript {
1515
mavenCentral()
1616
}
1717
dependencies {
18-
classpath("com.android.tools.build:gradle:7.3.1")
18+
classpath('com.android.tools.build:gradle:7.3.1')
1919
classpath("com.facebook.react:react-native-gradle-plugin")
2020
}
2121
}

package/android/cpp/rnskia-android/RNSkAndroidView.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,9 @@ class RNSkAndroidView : public T, public RNSkBaseAndroidView {
5656
void surfaceSizeChanged(int width, int height) override {
5757
std::static_pointer_cast<RNSkOpenGLCanvasProvider>(T::getCanvasProvider())
5858
->surfaceSizeChanged(width, height);
59+
// This is only need for the first time to frame, this renderImmediate call
60+
// will invoke updateTexImage for the previous frame
61+
RNSkView::renderImmediate();
5962
}
6063

6164
float getPixelDensity() override {

package/android/cpp/rnskia-android/RNSkOpenGLCanvasProvider.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@ bool RNSkOpenGLCanvasProvider::renderToCanvas(
3939
if (!_surfaceHolder->makeCurrent()) {
4040
return false;
4141
}
42+
_surfaceHolder->updateTexImage();
4243

4344
// Draw into canvas using callback
4445
cb(surface->getCanvas());

package/android/cpp/rnskia-android/SkiaOpenGLHelper.h

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -187,7 +187,6 @@ class SkiaOpenGLHelper {
187187
RNSkLogger::logToConsole("eglMakeCurrent failed: %d\n", eglGetError());
188188
return false;
189189
}
190-
return true;
191190
}
192191
return true;
193192
}

package/android/cpp/rnskia-android/SkiaOpenGLSurfaceFactory.h

Lines changed: 46 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@
66
#include <jni.h>
77

88
#include <android/native_window_jni.h>
9+
#include <android/surface_texture.h>
10+
#include <android/surface_texture_jni.h>
911
#include <condition_variable>
1012
#include <memory>
1113
#include <thread>
@@ -42,12 +44,34 @@ class ThreadContextHolder {
4244
*/
4345
class WindowSurfaceHolder {
4446
public:
45-
WindowSurfaceHolder(jobject surface, int width, int height)
46-
: _width(width), _height(height),
47-
_window(ANativeWindow_fromSurface(facebook::jni::Environment::current(),
48-
surface)) {}
47+
WindowSurfaceHolder(jobject jSurfaceTexture, int width, int height)
48+
: _width(width), _height(height) {
49+
JNIEnv *env = facebook::jni::Environment::current();
50+
_jSurfaceTexture = env->NewGlobalRef(jSurfaceTexture);
51+
jclass surfaceClass = env->FindClass("android/view/Surface");
52+
jmethodID surfaceConstructor = env->GetMethodID(
53+
surfaceClass, "<init>", "(Landroid/graphics/SurfaceTexture;)V");
54+
// Create a new Surface instance
55+
jobject jSurface =
56+
env->NewObject(surfaceClass, surfaceConstructor, jSurfaceTexture);
57+
58+
jclass surfaceTextureClass = env->GetObjectClass(_jSurfaceTexture);
59+
_updateTexImageMethod =
60+
env->GetMethodID(surfaceTextureClass, "updateTexImage", "()V");
61+
62+
// Acquire the native window from the Surface
63+
_window = ANativeWindow_fromSurface(env, jSurface);
64+
// Clean up local references
65+
env->DeleteLocalRef(jSurface);
66+
env->DeleteLocalRef(surfaceClass);
67+
env->DeleteLocalRef(surfaceTextureClass);
68+
}
4969

50-
~WindowSurfaceHolder() { ANativeWindow_release(_window); }
70+
~WindowSurfaceHolder() {
71+
JNIEnv *env = facebook::jni::Environment::current();
72+
env->DeleteGlobalRef(_jSurfaceTexture);
73+
ANativeWindow_release(_window);
74+
}
5175

5276
int getWidth() { return _width; }
5377
int getHeight() { return _height; }
@@ -57,6 +81,20 @@ class WindowSurfaceHolder {
5781
*/
5882
sk_sp<SkSurface> getSurface();
5983

84+
void updateTexImage() {
85+
JNIEnv *env = facebook::jni::Environment::current();
86+
87+
// Call updateTexImage on the SurfaceTexture object
88+
env->CallVoidMethod(_jSurfaceTexture, _updateTexImageMethod);
89+
90+
// Check for exceptions
91+
if (env->ExceptionCheck()) {
92+
RNSkLogger::logToConsole(
93+
"updateTexImage() failed. The exception above can safely be ignored");
94+
env->ExceptionClear();
95+
}
96+
}
97+
6098
/**
6199
* Resizes the surface
62100
* @param width
@@ -92,9 +130,11 @@ class WindowSurfaceHolder {
92130
}
93131

94132
private:
95-
ANativeWindow *_window = nullptr;
133+
ANativeWindow *_window;
96134
sk_sp<SkSurface> _skSurface = nullptr;
135+
jobject _jSurfaceTexture = nullptr;
97136
EGLSurface _glSurface = EGL_NO_SURFACE;
137+
jmethodID _updateTexImageMethod = nullptr;
98138
int _width = 0;
99139
int _height = 0;
100140
};

package/android/src/main/java/com/shopify/reactnative/skia/PlatformContext.java

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -52,13 +52,13 @@ private void postFrameLoop() {
5252
Choreographer.FrameCallback frameCallback = new Choreographer.FrameCallback() {
5353
@Override
5454
public void doFrame(long frameTimeNanos) {
55+
if (_drawLoopActive) {
56+
Choreographer.getInstance().postFrameCallback(this);
57+
}
5558
if (_isPaused) {
5659
return;
5760
}
5861
notifyDrawLoop();
59-
if (_drawLoopActive) {
60-
postFrameLoop();
61-
}
6262
}
6363
};
6464
Choreographer.getInstance().postFrameCallback(frameCallback);

package/android/src/main/java/com/shopify/reactnative/skia/SkiaBaseView.java

Lines changed: 8 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -4,16 +4,11 @@
44
import android.graphics.SurfaceTexture;
55
import android.util.Log;
66
import android.view.MotionEvent;
7-
import android.view.Surface;
87
import android.view.TextureView;
98

10-
import com.facebook.jni.annotations.DoNotStrip;
119
import com.facebook.react.views.view.ReactViewGroup;
1210

1311
public abstract class SkiaBaseView extends ReactViewGroup implements TextureView.SurfaceTextureListener {
14-
15-
@DoNotStrip
16-
private Surface mSurface;
1712
private TextureView mTexture;
1813

1914
private String tag = "SkiaView";
@@ -30,12 +25,8 @@ public SkiaBaseView(Context context, boolean manageTexture) {
3025
}
3126

3227
public void destroySurface() {
33-
if (mSurface != null) {
34-
Log.i(tag, "destroySurface");
35-
surfaceDestroyed();
36-
mSurface.release();
37-
mSurface = null;
38-
}
28+
Log.i(tag, "destroySurface");
29+
surfaceDestroyed();
3930
}
4031

4132
private void createSurfaceTexture() {
@@ -138,8 +129,7 @@ private static int motionActionToType(int action) {
138129
@Override
139130
public void onSurfaceTextureAvailable(SurfaceTexture surface, int width, int height) {
140131
Log.i(tag, "onSurfaceTextureAvailable " + width + "/" + height);
141-
mSurface = new Surface(surface);
142-
surfaceAvailable(mSurface, width, height);
132+
surfaceAvailable(surface, width, height);
143133
}
144134

145135
@Override
@@ -153,6 +143,10 @@ public boolean onSurfaceTextureDestroyed(SurfaceTexture surface) {
153143
Log.i(tag, "onSurfaceTextureDestroyed");
154144
// https://developer.android.com/reference/android/view/TextureView.SurfaceTextureListener#onSurfaceTextureDestroyed(android.graphics.SurfaceTexture)
155145
destroySurface();
146+
// Because of React Native Screens (which dettach the view), we always keep the surface alive.
147+
// If not, Texture view will recreate the texture surface by itself and
148+
// we will lose the fast first time to frame.
149+
// We only delete the surface when the view is dropped (destroySurface invoked by SkiaBaseViewManager);
156150
createSurfaceTexture();
157151
return false;
158152
}
@@ -181,4 +175,4 @@ public void onSurfaceTextureUpdated(SurfaceTexture surface) {
181175
protected abstract void registerView(int nativeId);
182176

183177
protected abstract void unregisterView();
184-
}
178+
}

package/cpp/utils/RNSkLog.h

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
#include <jsi/jsi.h>
88
#include <string>
99

10-
#ifdef ANDROID
10+
#if defined(ANDROID) || defined(__ANDROID__)
1111
#include <android/log.h>
1212
#endif
1313

@@ -26,7 +26,7 @@ class RNSkLogger {
2626
* @param message Message to be written out
2727
*/
2828
static void logToConsole(std::string message) {
29-
#ifdef ANDROID
29+
#if defined(ANDROID) || defined(__ANDROID__)
3030
__android_log_write(ANDROID_LOG_INFO, "RNSkia", message.c_str());
3131
#endif
3232

@@ -46,7 +46,7 @@ class RNSkLogger {
4646

4747
static char buffer[512];
4848
vsnprintf(buffer, sizeof(buffer), fmt, args);
49-
#ifdef ANDROID
49+
#if defined(ANDROID) || defined(__ANDROID__)
5050
__android_log_write(ANDROID_LOG_INFO, "RNSkia", buffer);
5151
#endif
5252
#ifdef TARGET_OS_IPHONE

0 commit comments

Comments
 (0)