Skip to content

Commit

Permalink
Update rendering logic on Android (#1980)
Browse files Browse the repository at this point in the history
  • Loading branch information
wcandillon authored Nov 24, 2023
1 parent 80911b0 commit 95d98b1
Show file tree
Hide file tree
Showing 8 changed files with 65 additions and 28 deletions.
2 changes: 1 addition & 1 deletion example/android/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ buildscript {
mavenCentral()
}
dependencies {
classpath("com.android.tools.build:gradle:7.3.1")
classpath('com.android.tools.build:gradle:7.3.1')
classpath("com.facebook.react:react-native-gradle-plugin")
}
}
3 changes: 3 additions & 0 deletions package/android/cpp/rnskia-android/RNSkAndroidView.h
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,9 @@ class RNSkAndroidView : public T, public RNSkBaseAndroidView {
void surfaceSizeChanged(int width, int height) override {
std::static_pointer_cast<RNSkOpenGLCanvasProvider>(T::getCanvasProvider())
->surfaceSizeChanged(width, height);
// This is only need for the first time to frame, this renderImmediate call
// will invoke updateTexImage for the previous frame
RNSkView::renderImmediate();
}

float getPixelDensity() override {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ bool RNSkOpenGLCanvasProvider::renderToCanvas(
if (!_surfaceHolder->makeCurrent()) {
return false;
}
_surfaceHolder->updateTexImage();

// Draw into canvas using callback
cb(surface->getCanvas());
Expand Down
1 change: 0 additions & 1 deletion package/android/cpp/rnskia-android/SkiaOpenGLHelper.h
Original file line number Diff line number Diff line change
Expand Up @@ -187,7 +187,6 @@ class SkiaOpenGLHelper {
RNSkLogger::logToConsole("eglMakeCurrent failed: %d\n", eglGetError());
return false;
}
return true;
}
return true;
}
Expand Down
52 changes: 46 additions & 6 deletions package/android/cpp/rnskia-android/SkiaOpenGLSurfaceFactory.h
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@
#include <jni.h>

#include <android/native_window_jni.h>
#include <android/surface_texture.h>
#include <android/surface_texture_jni.h>
#include <condition_variable>
#include <memory>
#include <thread>
Expand Down Expand Up @@ -42,12 +44,34 @@ class ThreadContextHolder {
*/
class WindowSurfaceHolder {
public:
WindowSurfaceHolder(jobject surface, int width, int height)
: _width(width), _height(height),
_window(ANativeWindow_fromSurface(facebook::jni::Environment::current(),
surface)) {}
WindowSurfaceHolder(jobject jSurfaceTexture, int width, int height)
: _width(width), _height(height) {
JNIEnv *env = facebook::jni::Environment::current();
_jSurfaceTexture = env->NewGlobalRef(jSurfaceTexture);
jclass surfaceClass = env->FindClass("android/view/Surface");
jmethodID surfaceConstructor = env->GetMethodID(
surfaceClass, "<init>", "(Landroid/graphics/SurfaceTexture;)V");
// Create a new Surface instance
jobject jSurface =
env->NewObject(surfaceClass, surfaceConstructor, jSurfaceTexture);

jclass surfaceTextureClass = env->GetObjectClass(_jSurfaceTexture);
_updateTexImageMethod =
env->GetMethodID(surfaceTextureClass, "updateTexImage", "()V");

// Acquire the native window from the Surface
_window = ANativeWindow_fromSurface(env, jSurface);
// Clean up local references
env->DeleteLocalRef(jSurface);
env->DeleteLocalRef(surfaceClass);
env->DeleteLocalRef(surfaceTextureClass);
}

~WindowSurfaceHolder() { ANativeWindow_release(_window); }
~WindowSurfaceHolder() {
JNIEnv *env = facebook::jni::Environment::current();
env->DeleteGlobalRef(_jSurfaceTexture);
ANativeWindow_release(_window);
}

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

void updateTexImage() {
JNIEnv *env = facebook::jni::Environment::current();

// Call updateTexImage on the SurfaceTexture object
env->CallVoidMethod(_jSurfaceTexture, _updateTexImageMethod);

// Check for exceptions
if (env->ExceptionCheck()) {
RNSkLogger::logToConsole(
"updateTexImage() failed. The exception above can safely be ignored");
env->ExceptionClear();
}
}

/**
* Resizes the surface
* @param width
Expand Down Expand Up @@ -92,9 +130,11 @@ class WindowSurfaceHolder {
}

private:
ANativeWindow *_window = nullptr;
ANativeWindow *_window;
sk_sp<SkSurface> _skSurface = nullptr;
jobject _jSurfaceTexture = nullptr;
EGLSurface _glSurface = EGL_NO_SURFACE;
jmethodID _updateTexImageMethod = nullptr;
int _width = 0;
int _height = 0;
};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -52,13 +52,13 @@ private void postFrameLoop() {
Choreographer.FrameCallback frameCallback = new Choreographer.FrameCallback() {
@Override
public void doFrame(long frameTimeNanos) {
if (_drawLoopActive) {
Choreographer.getInstance().postFrameCallback(this);
}
if (_isPaused) {
return;
}
notifyDrawLoop();
if (_drawLoopActive) {
postFrameLoop();
}
}
};
Choreographer.getInstance().postFrameCallback(frameCallback);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,16 +4,11 @@
import android.graphics.SurfaceTexture;
import android.util.Log;
import android.view.MotionEvent;
import android.view.Surface;
import android.view.TextureView;

import com.facebook.jni.annotations.DoNotStrip;
import com.facebook.react.views.view.ReactViewGroup;

public abstract class SkiaBaseView extends ReactViewGroup implements TextureView.SurfaceTextureListener {

@DoNotStrip
private Surface mSurface;
private TextureView mTexture;

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

public void destroySurface() {
if (mSurface != null) {
Log.i(tag, "destroySurface");
surfaceDestroyed();
mSurface.release();
mSurface = null;
}
Log.i(tag, "destroySurface");
surfaceDestroyed();
}

private void createSurfaceTexture() {
Expand Down Expand Up @@ -138,8 +129,7 @@ private static int motionActionToType(int action) {
@Override
public void onSurfaceTextureAvailable(SurfaceTexture surface, int width, int height) {
Log.i(tag, "onSurfaceTextureAvailable " + width + "/" + height);
mSurface = new Surface(surface);
surfaceAvailable(mSurface, width, height);
surfaceAvailable(surface, width, height);
}

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

protected abstract void unregisterView();
}
}
6 changes: 3 additions & 3 deletions package/cpp/utils/RNSkLog.h
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
#include <jsi/jsi.h>
#include <string>

#ifdef ANDROID
#if defined(ANDROID) || defined(__ANDROID__)
#include <android/log.h>
#endif

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

Expand All @@ -46,7 +46,7 @@ class RNSkLogger {

static char buffer[512];
vsnprintf(buffer, sizeof(buffer), fmt, args);
#ifdef ANDROID
#if defined(ANDROID) || defined(__ANDROID__)
__android_log_write(ANDROID_LOG_INFO, "RNSkia", buffer);
#endif
#ifdef TARGET_OS_IPHONE
Expand Down

0 comments on commit 95d98b1

Please sign in to comment.