diff --git a/ReactAndroid/src/main/java/com/facebook/react/flat/FlatARTSurfaceViewManager.java b/ReactAndroid/src/main/java/com/facebook/react/flat/FlatARTSurfaceViewManager.java index 2c1eec28ad..0ce91a6039 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/flat/FlatARTSurfaceViewManager.java +++ b/ReactAndroid/src/main/java/com/facebook/react/flat/FlatARTSurfaceViewManager.java @@ -9,8 +9,6 @@ package com.facebook.react.flat; -import android.graphics.Bitmap; - import com.facebook.csslayout.CSSMeasureMode; import com.facebook.csslayout.CSSNodeAPI; import com.facebook.csslayout.MeasureOutput; @@ -60,6 +58,6 @@ import com.facebook.react.views.art.ARTSurfaceView; @Override public void updateExtraData(ARTSurfaceView root, Object extraData) { - root.setBitmap((Bitmap) extraData); + root.setSurfaceTextureListener((FlatARTSurfaceViewShadowNode) extraData); } } diff --git a/ReactAndroid/src/main/java/com/facebook/react/flat/FlatARTSurfaceViewShadowNode.java b/ReactAndroid/src/main/java/com/facebook/react/flat/FlatARTSurfaceViewShadowNode.java index 4b139f76b3..8ca4357ce2 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/flat/FlatARTSurfaceViewShadowNode.java +++ b/ReactAndroid/src/main/java/com/facebook/react/flat/FlatARTSurfaceViewShadowNode.java @@ -9,15 +9,26 @@ package com.facebook.react.flat; -import android.graphics.Bitmap; -import android.graphics.Canvas; -import android.graphics.Paint; +import javax.annotation.Nullable; +import android.graphics.Canvas; +import android.graphics.Color; +import android.graphics.Paint; +import android.graphics.PorterDuff; +import android.graphics.SurfaceTexture; +import android.util.Log; +import android.view.Surface; +import android.view.TextureView; + +import com.facebook.react.common.ReactConstants; +import com.facebook.react.uimanager.ReactShadowNode; import com.facebook.react.uimanager.UIViewOperationQueue; import com.facebook.react.views.art.ARTVirtualNode; -/* package */ class FlatARTSurfaceViewShadowNode extends FlatShadowNode implements AndroidView { +/* package */ class FlatARTSurfaceViewShadowNode extends FlatShadowNode + implements AndroidView, TextureView.SurfaceTextureListener { private boolean mPaddingChanged = false; + private @Nullable Surface mSurface; /* package */ FlatARTSurfaceViewShadowNode() { forceMountToView(); @@ -37,24 +48,42 @@ import com.facebook.react.views.art.ARTVirtualNode; @Override public void onCollectExtraUpdates(UIViewOperationQueue uiUpdater) { super.onCollectExtraUpdates(uiUpdater); - uiUpdater.enqueueUpdateExtraData(getReactTag(), drawOutput()); + uiUpdater.enqueueUpdateExtraData(getReactTag(), this); } - private Object drawOutput() { - // TODO(7255985): Use TextureView and pass Surface from the view to draw on it asynchronously - // instead of passing the bitmap (which is inefficient especially in terms of memory usage) - Bitmap bitmap = Bitmap.createBitmap( - (int) getLayoutWidth(), - (int) getLayoutHeight(), - Bitmap.Config.ARGB_8888); - Canvas canvas = new Canvas(bitmap); - Paint paint = new Paint(); - for (int i = 0; i < getChildCount(); i++) { - ARTVirtualNode child = (ARTVirtualNode) getChildAt(i); - child.draw(canvas, paint, 1f); - child.markUpdateSeen(); + private void drawOutput() { + if (mSurface == null || !mSurface.isValid()) { + markChildrenUpdatesSeen(this); + return; + } + + try { + Canvas canvas = mSurface.lockCanvas(null); + canvas.drawColor(Color.TRANSPARENT, PorterDuff.Mode.CLEAR); + + Paint paint = new Paint(); + for (int i = 0; i < getChildCount(); i++) { + ARTVirtualNode child = (ARTVirtualNode) getChildAt(i); + child.draw(canvas, paint, 1f); + child.markUpdateSeen(); + } + + if (mSurface == null) { + return; + } + + mSurface.unlockCanvasAndPost(canvas); + } catch (IllegalArgumentException | IllegalStateException e) { + Log.e(ReactConstants.TAG, e.getClass().getSimpleName() + " in Surface.unlockCanvasAndPost"); + } + } + + private void markChildrenUpdatesSeen(ReactShadowNode shadowNode) { + for (int i = 0; i < shadowNode.getChildCount(); i++) { + ReactShadowNode child = shadowNode.getChildAt(i); + child.markUpdateSeen(); + markChildrenUpdatesSeen(child); } - return bitmap; } @Override @@ -79,4 +108,23 @@ import com.facebook.react.views.art.ARTVirtualNode; dirty(); } } + + @Override + public void onSurfaceTextureAvailable(SurfaceTexture surface, int width, int height) { + mSurface = new Surface(surface); + drawOutput(); + } + + @Override + public boolean onSurfaceTextureDestroyed(SurfaceTexture surface) { + surface.release(); + mSurface = null; + return true; + } + + @Override + public void onSurfaceTextureSizeChanged(SurfaceTexture surface, int width, int height) {} + + @Override + public void onSurfaceTextureUpdated(SurfaceTexture surface) {} }