Commit c75cf213 authored by Gaëtan Renaudeau's avatar Gaëtan Renaudeau

WIP

parent ca1d7889
<manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.projectseptember.RNGL"> <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.projectseptember.RNGL">
<uses-feature android:glEsVersion="0x00020000" android:required="true" /> <uses-feature android:glEsVersion="0x00020000" android:required="true" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
</manifest> </manifest>
...@@ -2,10 +2,11 @@ package com.projectseptember.RNGL; ...@@ -2,10 +2,11 @@ package com.projectseptember.RNGL;
import static android.opengl.GLES20.*; import static android.opengl.GLES20.*;
import android.graphics.Bitmap;
import android.graphics.PixelFormat; import android.graphics.PixelFormat;
import android.opengl.GLSurfaceView; import android.opengl.GLSurfaceView;
import android.util.DisplayMetrics; import android.util.DisplayMetrics;
import android.view.View; import android.util.Log;
import android.view.ViewGroup; import android.view.ViewGroup;
import com.facebook.react.bridge.Arguments; import com.facebook.react.bridge.Arguments;
...@@ -27,21 +28,18 @@ import java.util.LinkedList; ...@@ -27,21 +28,18 @@ import java.util.LinkedList;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Queue; import java.util.Queue;
import java.util.logging.Logger;
import javax.microedition.khronos.egl.EGLConfig; import javax.microedition.khronos.egl.EGLConfig;
import javax.microedition.khronos.opengles.GL10; import javax.microedition.khronos.opengles.GL10;
public class GLCanvas extends GLSurfaceView implements GLSurfaceView.Renderer, RunInGLThread { public class GLCanvas extends GLSurfaceView implements GLSurfaceView.Renderer, RunInGLThread {
private static final Logger logger = Logger.getLogger(GLCanvas.class.getName());
private ReactContext reactContext; private ReactContext reactContext;
private RNGLContext rnglContext; private RNGLContext rnglContext;
private boolean preloadingDone = false; private boolean preloadingDone = false;
private boolean deferredRendering = false; private boolean deferredRendering = false;
private GLRenderData renderData; private GLRenderData renderData;
private int[] defaultFBO; private int defaultFBO;
private int nbContentTextures; private int nbContentTextures;
private int renderId; private int renderId;
...@@ -57,6 +55,7 @@ public class GLCanvas extends GLSurfaceView implements GLSurfaceView.Renderer, R ...@@ -57,6 +55,7 @@ public class GLCanvas extends GLSurfaceView implements GLSurfaceView.Renderer, R
private Map<String, GLImage> images = new HashMap<>(); private Map<String, GLImage> images = new HashMap<>();
private List<GLTexture> contentTextures = new ArrayList<>(); private List<GLTexture> contentTextures = new ArrayList<>();
private List<Bitmap> contentBitmaps = new ArrayList<>();
private Map<Integer, GLShader> shaders = new HashMap<>(); private Map<Integer, GLShader> shaders = new HashMap<>();
private Map<Integer, GLFBO> fbos = new HashMap<>(); private Map<Integer, GLFBO> fbos = new HashMap<>();
...@@ -64,14 +63,21 @@ public class GLCanvas extends GLSurfaceView implements GLSurfaceView.Renderer, R ...@@ -64,14 +63,21 @@ public class GLCanvas extends GLSurfaceView implements GLSurfaceView.Renderer, R
public GLCanvas(ThemedReactContext context) { public GLCanvas(ThemedReactContext context) {
super(context); super(context);
reactContext = context; reactContext = context;
this.rnglContext = context.getNativeModule(RNGLContext.class); rnglContext = context.getNativeModule(RNGLContext.class);
this.setEGLContextClientVersion(2); setEGLContextClientVersion(2);
this.setEGLConfigChooser(8, 8, 8, 8, 16, 0); setEGLConfigChooser(8, 8, 8, 8, 16, 0);
this.getHolder().setFormat(PixelFormat.RGBA_8888); getHolder().setFormat(PixelFormat.RGBA_8888);
this.setRenderer(this); setRenderer(this);
this.setRenderMode(GLSurfaceView.RENDERMODE_WHEN_DIRTY); setRenderMode(GLSurfaceView.RENDERMODE_WHEN_DIRTY);
this.requestRender(); Log.i("GLCanvas", "created");
}
@Override
protected void onAttachedToWindow() {
Log.i("GLCanvas", "onAttachedToWindow");
super.onAttachedToWindow();
syncContentBitmaps();
requestRender();
preloadingDone = true; // TODO preloadingDone = true; // TODO
} }
...@@ -87,6 +93,7 @@ public class GLCanvas extends GLSurfaceView implements GLSurfaceView.Renderer, R ...@@ -87,6 +93,7 @@ public class GLCanvas extends GLSurfaceView implements GLSurfaceView.Renderer, R
@Override @Override
public void onDrawFrame(GL10 gl) { public void onDrawFrame(GL10 gl) {
Log.i("GLCanvas", "onDrawFrame");
runAll(mRunOnDraw); runAll(mRunOnDraw);
syncEventsThrough(); // FIXME, really need to do this ? syncEventsThrough(); // FIXME, really need to do this ?
...@@ -97,33 +104,42 @@ public class GLCanvas extends GLSurfaceView implements GLSurfaceView.Renderer, R ...@@ -97,33 +104,42 @@ public class GLCanvas extends GLSurfaceView implements GLSurfaceView.Renderer, R
return; return;
} }
boolean needsDeferredRendering = nbContentTextures > 0 && !autoRedraw; final boolean shouldRenderNow = deferredRendering || autoRedraw || nbContentTextures == 0;
if (needsDeferredRendering && !deferredRendering) { if (nbContentTextures > 0) {
deferredRendering = true; reactContext.runOnUiQueueThread(new Runnable() {
this.requestRender(); // FIXME is this working correctly? public void run() {
/* syncContentBitmaps();
dispatch_async(dispatch_get_main_queue(), ^{ if (!deferredRendering) {
if (!weakSelf) return;
deferredRendering = true; deferredRendering = true;
[weakSelf setNeedsDisplay]; requestRender();
}
}
}); });
*/
} }
else {
if (shouldRenderNow) {
this.render(); this.render();
deferredRendering = false; deferredRendering = false;
} }
} }
public void setNbContentTextures(int nbContentTextures) { public void setNbContentTextures(int n) {
this.nbContentTextures = n;
runInGLThread(new Runnable() {
@Override
public void run() {
resizeUniformContentTextures(nbContentTextures); resizeUniformContentTextures(nbContentTextures);
this.nbContentTextures = nbContentTextures; if (preloadingDone) syncContentBitmaps();
}
});
} }
public void setRenderId(int renderId) { public void setRenderId(int renderId) {
this.renderId = renderId; this.renderId = renderId;
if (nbContentTextures > 0) if (nbContentTextures > 0) {
this.requestRender(); if (preloadingDone) syncContentBitmaps();
requestRender();
}
} }
public void setOpaque(boolean opaque) { public void setOpaque(boolean opaque) {
...@@ -162,27 +178,30 @@ public class GLCanvas extends GLSurfaceView implements GLSurfaceView.Renderer, R ...@@ -162,27 +178,30 @@ public class GLCanvas extends GLSurfaceView implements GLSurfaceView.Renderer, R
private boolean ensureCompiledShader (List<GLData> data) { private boolean ensureCompiledShader (List<GLData> data) {
for (GLData d: data) { for (GLData d: data) {
if (!ensureCompiledShader(d)); if (!ensureCompiledShader(d)) {
return false; return false;
} }
}
return true; return true;
} }
private boolean ensureCompiledShader (GLData data) { private boolean ensureCompiledShader (GLData data) {
GLShader shader = rnglContext.getShader(data.shader); GLShader shader = rnglContext.getShader(data.shader);
if (shader == null) return false; return shader != null &&
shader.ensureCompile(); shader.ensureCompile() &&
return ensureCompiledShader(data.children) && ensureCompiledShader(data.contextChildren); ensureCompiledShader(data.children) &&
ensureCompiledShader(data.contextChildren);
} }
public void setData (GLData data) { public void setData (GLData data) {
this.data = data; this.data = data;
this.requestSyncData(); if (preloadingDone) syncContentBitmaps();
requestSyncData();
} }
public void setImagesToPreload(ReadableArray imagesToPreload) { public void setImagesToPreload(ReadableArray imagesToPreload) {
logger.info("setImageToPreload, working correctly?"); // TODO // FIXME setImageToPreload, working correctly?
if (preloadingDone) return; if (preloadingDone) return;
if (imagesToPreload.size() == 0) { if (imagesToPreload.size() == 0) {
dispatchOnLoad(); dispatchOnLoad();
...@@ -215,6 +234,7 @@ public class GLCanvas extends GLSurfaceView implements GLSurfaceView.Renderer, R ...@@ -215,6 +234,7 @@ public class GLCanvas extends GLSurfaceView implements GLSurfaceView.Renderer, R
public void requestSyncData () { public void requestSyncData () {
runInGLThread(new Runnable() { runInGLThread(new Runnable() {
public void run() { public void run() {
Log.i("GLCanvas", "requestSyncData");
if (ensureCompiledShader(data)) if (ensureCompiledShader(data))
syncData(); syncData();
else else
...@@ -223,16 +243,35 @@ public class GLCanvas extends GLSurfaceView implements GLSurfaceView.Renderer, R ...@@ -223,16 +243,35 @@ public class GLCanvas extends GLSurfaceView implements GLSurfaceView.Renderer, R
}); });
} }
public void syncContextTextures () { /**
int i = 0; * Snapshot the content views and save to contentBitmaps (must run in UI Thread)
for (GLTexture texture: contentTextures) { */
View view = ((ViewGroup) this.getParent()).getChildAt(i); public int syncContentBitmaps() {
texture.setPixelsWithView(view); List<Bitmap> bitmaps = new ArrayList<>();
i ++; ViewGroup parent = (ViewGroup) this.getParent();
int count = parent == null ? 0 : parent.getChildCount() - 1;
for (int i = 0; i < count; i++) {
bitmaps.add(GLTexture.captureView(parent.getChildAt(i)));
} }
contentBitmaps = bitmaps;
//Log.i("GLCanvas", "syncContentBitmaps "+count+" "+parent);
return count;
}
/**
* Draw contentBitmaps to contentTextures (must run in GL Thread)
*/
public int syncContentTextures() {
int size = Math.min(contentTextures.size(), contentBitmaps.size());
for (int i=0; i<size; i++)
contentTextures.get(i).setPixels(contentBitmaps.get(i));
//Log.i("GLCanvas", "syncContentTextures "+size);
return size;
} }
public void resizeUniformContentTextures (int n) { public void resizeUniformContentTextures (int n) {
//Log.i("GLCanvas", "reiszeUniformContentTextures "+n);
int length = contentTextures.size(); int length = contentTextures.size();
if (length == n) return; if (length == n) return;
if (n < length) { if (n < length) {
...@@ -296,8 +335,6 @@ public class GLCanvas extends GLSurfaceView implements GLSurfaceView.Renderer, R ...@@ -296,8 +335,6 @@ public class GLCanvas extends GLSurfaceView implements GLSurfaceView.Renderer, R
List<GLRenderData> contextChildren = new ArrayList<>(); List<GLRenderData> contextChildren = new ArrayList<>();
List<GLRenderData> children = new ArrayList<>(); List<GLRenderData> children = new ArrayList<>();
shader.bind();
for (GLData child: data.contextChildren) { for (GLData child: data.contextChildren) {
contextChildren.add(recSyncData(child, images)); contextChildren.add(recSyncData(child, images));
} }
...@@ -325,13 +362,12 @@ public class GLCanvas extends GLSurfaceView implements GLSurfaceView.Renderer, R ...@@ -325,13 +362,12 @@ public class GLCanvas extends GLSurfaceView implements GLSurfaceView.Renderer, R
textures.put(uniformName, emptyTexture); textures.put(uniformName, emptyTexture);
} }
else { else {
// FIXME: in case of require() it's now a number...
// TODO: need to support this. as well as on iOS side
ReadableMap value = dataUniforms.getMap(uniformName); ReadableMap value = dataUniforms.getMap(uniformName);
String t = value.getString("type"); String t = value.getString("type");
if (t.equals("content")) { if (t.equals("content")) {
int id = value.getInt("id"); int id = value.getInt("id");
if (id >= contentTextures.size()) {
this.resizeUniformContentTextures(id + 1);
}
textures.put(uniformName, contentTextures.get(id)); textures.put(uniformName, contentTextures.get(id));
} }
else if (t.equals("fbo")) { else if (t.equals("fbo")) {
...@@ -342,7 +378,7 @@ public class GLCanvas extends GLSurfaceView implements GLSurfaceView.Renderer, R ...@@ -342,7 +378,7 @@ public class GLCanvas extends GLSurfaceView implements GLSurfaceView.Renderer, R
else if (t.equals("uri")) { else if (t.equals("uri")) {
final String src = srcResource(value); final String src = srcResource(value);
if (src==null || src.equals("")) { if (src==null || src.equals("")) {
logger.severe("Shader '"+shader.getName()+": texture uniform '"+uniformName+"': Invalid uri format '"+value+"'"); shader.runtimeException("texture uniform '"+uniformName+"': Invalid uri format '"+value+"'");
} }
GLImage image = images.get(src); GLImage image = images.get(src);
...@@ -363,7 +399,7 @@ public class GLCanvas extends GLSurfaceView implements GLSurfaceView.Renderer, R ...@@ -363,7 +399,7 @@ public class GLCanvas extends GLSurfaceView implements GLSurfaceView.Renderer, R
textures.put(uniformName, image.getTexture()); textures.put(uniformName, image.getTexture());
} }
else { else {
logger.severe("Shader '"+shader.getName()+": texture uniform '"+uniformName+"': Unexpected type '"+type+"'"); shader.runtimeException("texture uniform '" + uniformName + "': Unexpected type '" + type + "'");
} }
} }
} }
...@@ -389,8 +425,8 @@ public class GLCanvas extends GLSurfaceView implements GLSurfaceView.Renderer, R ...@@ -389,8 +425,8 @@ public class GLCanvas extends GLSurfaceView implements GLSurfaceView.Renderer, R
case GL_FLOAT_MAT4: case GL_FLOAT_MAT4:
ReadableArray arr = dataUniforms.getArray(uniformName); ReadableArray arr = dataUniforms.getArray(uniformName);
if (arraySizeForType(type) != arr.size()) { if (arraySizeForType(type) != arr.size()) {
throw new Error("Shader '"+shader.getName()+ shader.runtimeException(
"' uniform '"+uniformName+ "uniform '"+uniformName+
"': Invalid array size: "+arr.size()+ "': Invalid array size: "+arr.size()+
". Expected: "+arraySizeForType(type)); ". Expected: "+arraySizeForType(type));
} }
...@@ -405,8 +441,8 @@ public class GLCanvas extends GLSurfaceView implements GLSurfaceView.Renderer, R ...@@ -405,8 +441,8 @@ public class GLCanvas extends GLSurfaceView implements GLSurfaceView.Renderer, R
case GL_BOOL_VEC4: case GL_BOOL_VEC4:
ReadableArray arr2 = dataUniforms.getArray(uniformName); ReadableArray arr2 = dataUniforms.getArray(uniformName);
if (arraySizeForType(type) != arr2.size()) { if (arraySizeForType(type) != arr2.size()) {
throw new Error("Shader '"+shader.getName()+ shader.runtimeException(
"' uniform '"+uniformName+ "uniform '"+uniformName+
"': Invalid array size: "+arr2.size()+ "': Invalid array size: "+arr2.size()+
". Expected: "+arraySizeForType(type)); ". Expected: "+arraySizeForType(type));
} }
...@@ -414,8 +450,8 @@ public class GLCanvas extends GLSurfaceView implements GLSurfaceView.Renderer, R ...@@ -414,8 +450,8 @@ public class GLCanvas extends GLSurfaceView implements GLSurfaceView.Renderer, R
break; break;
default: default:
throw new Error("Shader '"+shader.getName()+ shader.runtimeException(
"' uniform '"+uniformName+ "uniform '"+uniformName+
"': type not supported: "+type); "': type not supported: "+type);
} }
...@@ -425,7 +461,7 @@ public class GLCanvas extends GLSurfaceView implements GLSurfaceView.Renderer, R ...@@ -425,7 +461,7 @@ public class GLCanvas extends GLSurfaceView implements GLSurfaceView.Renderer, R
int[] maxTextureUnits = new int[1]; int[] maxTextureUnits = new int[1];
glGetIntegerv(GL_MAX_TEXTURE_IMAGE_UNITS, maxTextureUnits, 0); glGetIntegerv(GL_MAX_TEXTURE_IMAGE_UNITS, maxTextureUnits, 0);
if (units > maxTextureUnits[0]) { if (units > maxTextureUnits[0]) {
logger.severe("Shader '"+shader.getName()+": Maximum number of texture reach. got "+units+" >= max "+maxTextureUnits); shader.runtimeException("Maximum number of texture reach. got " + units + " >= max " + maxTextureUnits);
} }
for (String uniformName: uniformTypes.keySet()) { for (String uniformName: uniformTypes.keySet()) {
...@@ -433,7 +469,7 @@ public class GLCanvas extends GLSurfaceView implements GLSurfaceView.Renderer, R ...@@ -433,7 +469,7 @@ public class GLCanvas extends GLSurfaceView implements GLSurfaceView.Renderer, R
!uniformsInteger.containsKey(uniformName) && !uniformsInteger.containsKey(uniformName) &&
!uniformsFloatBuffer.containsKey(uniformName) && !uniformsFloatBuffer.containsKey(uniformName) &&
!uniformsIntBuffer.containsKey(uniformName)) { !uniformsIntBuffer.containsKey(uniformName)) {
logger.severe("Shader '"+shader.getName()+": All defined uniforms must be provided. Missing '"+uniformName+"'"); shader.runtimeException("All defined uniforms must be provided. Missing '"+uniformName+"'");
} }
} }
...@@ -503,6 +539,7 @@ public class GLCanvas extends GLSurfaceView implements GLSurfaceView.Renderer, R ...@@ -503,6 +539,7 @@ public class GLCanvas extends GLSurfaceView implements GLSurfaceView.Renderer, R
} }
public void syncData () { public void syncData () {
Log.i("GLCanvas", "syncData "+data);
if (data == null) return; if (data == null) return;
HashMap<String, GLImage> images = new HashMap<>(); HashMap<String, GLImage> images = new HashMap<>();
renderData = recSyncData(data, images); renderData = recSyncData(data, images);
...@@ -511,10 +548,11 @@ public class GLCanvas extends GLSurfaceView implements GLSurfaceView.Renderer, R ...@@ -511,10 +548,11 @@ public class GLCanvas extends GLSurfaceView implements GLSurfaceView.Renderer, R
} }
public void recRender (GLRenderData renderData) { public void recRender (GLRenderData renderData) {
Log.i("GLCanvas", "recRender "+renderData.fboId);
DisplayMetrics dm = reactContext.getResources().getDisplayMetrics(); DisplayMetrics dm = reactContext.getResources().getDisplayMetrics();
int w = new Float(renderData.width.floatValue() * dm.density).intValue(); int w = Float.valueOf(renderData.width.floatValue() * dm.density).intValue();
int h = new Float(renderData.height.floatValue() * dm.density).intValue(); int h = Float.valueOf(renderData.height.floatValue() * dm.density).intValue();
for (GLRenderData child: renderData.contextChildren) for (GLRenderData child: renderData.contextChildren)
recRender(child); recRender(child);
...@@ -523,7 +561,7 @@ public class GLCanvas extends GLSurfaceView implements GLSurfaceView.Renderer, R ...@@ -523,7 +561,7 @@ public class GLCanvas extends GLSurfaceView implements GLSurfaceView.Renderer, R
recRender(child); recRender(child);
if (renderData.fboId == -1) { if (renderData.fboId == -1) {
glBindFramebuffer(GL_FRAMEBUFFER, defaultFBO[0]); glBindFramebuffer(GL_FRAMEBUFFER, defaultFBO);
glViewport(0, 0, w, h); glViewport(0, 0, w, h);
} }
else { else {
...@@ -538,6 +576,7 @@ public class GLCanvas extends GLSurfaceView implements GLSurfaceView.Renderer, R ...@@ -538,6 +576,7 @@ public class GLCanvas extends GLSurfaceView implements GLSurfaceView.Renderer, R
GLTexture texture = renderData.textures.get(uniformName); GLTexture texture = renderData.textures.get(uniformName);
int unit = renderData.uniformsInteger.get(uniformName); int unit = renderData.uniformsInteger.get(uniformName);
texture.bind(unit); texture.bind(unit);
Log.i("GLCanvas", uniformName+" "+unit);
} }
Map<String, Integer> uniformTypes = renderData.shader.getUniformTypes(); Map<String, Integer> uniformTypes = renderData.shader.getUniformTypes();
...@@ -562,14 +601,16 @@ public class GLCanvas extends GLSurfaceView implements GLSurfaceView.Renderer, R ...@@ -562,14 +601,16 @@ public class GLCanvas extends GLSurfaceView implements GLSurfaceView.Renderer, R
public void render () { public void render () {
if (renderData == null) return; if (renderData == null) return;
syncContextTextures(); syncContentTextures();
Log.i("GLCanvas", "render");
defaultFBO = new int[1]; int[] defaultFBOArr = new int[1];
glGetIntegerv(GL_FRAMEBUFFER_BINDING, defaultFBO, 0); glGetIntegerv(GL_FRAMEBUFFER_BINDING, defaultFBOArr, 0);
defaultFBO = defaultFBOArr[0];
glEnable(GL_BLEND); glEnable(GL_BLEND);
recRender(renderData); recRender(renderData);
glDisable(GL_BLEND); glDisable(GL_BLEND);
glBindFramebuffer(GL_FRAMEBUFFER, defaultFBO[0]); glBindFramebuffer(GL_FRAMEBUFFER, defaultFBO);
} }
public void syncEventsThrough () { public void syncEventsThrough () {
......
package com.projectseptember.RNGL; package com.projectseptember.RNGL;
import android.app.ActivityManager;
import android.content.Context;
import android.content.pm.ConfigurationInfo;
import android.support.annotation.Nullable; import android.support.annotation.Nullable;
import android.util.Log; import android.util.Log;
...@@ -27,37 +24,37 @@ public class GLCanvasManager extends SimpleViewManager<GLCanvas> { ...@@ -27,37 +24,37 @@ public class GLCanvasManager extends SimpleViewManager<GLCanvas> {
} }
@ReactProp(name="opaque") @ReactProp(name="opaque")
public void setOpaque(GLCanvas view, boolean opaque) { public void setOpaque (GLCanvas view, boolean opaque) {
view.setOpaque(opaque); view.setOpaque(opaque);
} }
@ReactProp(name="autoRedraw") @ReactProp(name="autoRedraw")
public void setAutoRedraw(GLCanvas view, boolean autoRedraw) { public void setAutoRedraw (GLCanvas view, boolean autoRedraw) {
view.setAutoRedraw(autoRedraw); view.setAutoRedraw(autoRedraw);
} }
@ReactProp(name="eventsThrough") @ReactProp(name="eventsThrough")
public void setEventsThrough(GLCanvas view, boolean eventsThrough) { public void setEventsThrough (GLCanvas view, boolean eventsThrough) {
view.setEventsThrough(eventsThrough); view.setEventsThrough(eventsThrough);
} }
@ReactProp(name="visibleContent") @ReactProp(name="visibleContent")
public void setVisibleContent(GLCanvas view, boolean visibleContent) { public void setVisibleContent (GLCanvas view, boolean visibleContent) {
view.setVisibleContent(visibleContent); view.setVisibleContent(visibleContent);
} }
@ReactProp(name="captureNextFrameId") @ReactProp(name="captureNextFrameId")
public void setCaptureNextFrameId(GLCanvas view, int captureNextFrameId) { public void setCaptureNextFrameId (GLCanvas view, int captureNextFrameId) {
view.setCaptureNextFrameId(captureNextFrameId); view.setCaptureNextFrameId(captureNextFrameId);
} }
@ReactProp(name="data") @ReactProp(name="data")
public void setData(GLCanvas view, @Nullable ReadableMap glData) { public void setData (GLCanvas view, @Nullable ReadableMap data) {
view.setData(glData == null ? null : GLData.fromMap(glData)); view.setData(data == null ? null : GLData.fromMap(data));
} }
@ReactProp(name="imagesToPreload") @ReactProp(name="imagesToPreload")
public void setImagesToPreload(GLCanvas view, @Nullable ReadableArray imageToPreload) { public void setImagesToPreload (GLCanvas view, @Nullable ReadableArray imageToPreload) {
view.setImagesToPreload(imageToPreload); view.setImagesToPreload(imageToPreload);
} }
...@@ -67,7 +64,8 @@ public class GLCanvasManager extends SimpleViewManager<GLCanvas> { ...@@ -67,7 +64,8 @@ public class GLCanvasManager extends SimpleViewManager<GLCanvas> {
} }
@Override @Override
public GLCanvas createViewInstance(ThemedReactContext context) { public GLCanvas createViewInstance (ThemedReactContext context) {
Log.i("GLCanvas", "createViewInstance...");
return new GLCanvas(context); return new GLCanvas(context);
} }
} }
package com.projectseptember.RNGL; package com.projectseptember.RNGL;
import android.util.Log;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import java.util.logging.Logger;
import static android.opengl.GLES20.*; import static android.opengl.GLES20.*;
public class GLFBO { public class GLFBO {
private static final Logger logger = Logger.getLogger(GLFBO.class.getName());
public final List<GLTexture> color = new ArrayList<>(); public final List<GLTexture> color = new ArrayList<>();
private int handle; private int handle;
private int width = 0; private int width = 0;
...@@ -18,10 +17,11 @@ public class GLFBO { ...@@ -18,10 +17,11 @@ public class GLFBO {
GLTexture texture = new GLTexture(); GLTexture texture = new GLTexture();
texture.bind(); texture.bind();
texture.setShape(width, height); texture.setShape(width, height);
glFramebufferTexture2D(GL_FRAMEBUFFER, attachment, GL_TEXTURE_2D, texture.handle, 0); glFramebufferTexture2D(GL_FRAMEBUFFER, attachment, GL_TEXTURE_2D, texture.getHandle(), 0);
return texture; return texture;
} }
/*
int initRenderBuffer (int width, int height, int component, int attachment) int initRenderBuffer (int width, int height, int component, int attachment)
{ {
int[] handleArr = new int[1]; int[] handleArr = new int[1];
...@@ -32,7 +32,9 @@ public class GLFBO { ...@@ -32,7 +32,9 @@ public class GLFBO {
glFramebufferRenderbuffer(GL_FRAMEBUFFER, attachment, GL_RENDERBUFFER, handle); glFramebufferRenderbuffer(GL_FRAMEBUFFER, attachment, GL_RENDERBUFFER, handle);
return handle; return handle;
} }
*/
/*
class FBOState { class FBOState {
private int fbo; private int fbo;
...@@ -55,9 +57,11 @@ public class GLFBO { ...@@ -55,9 +57,11 @@ public class GLFBO {
glBindTexture(GL_FRAMEBUFFER, tex); glBindTexture(GL_FRAMEBUFFER, tex);
} }
} }
*/
public GLFBO() { public GLFBO() {
FBOState state = new FBOState(); Log.i("GLFBO", "new");
//FBOState state = new FBOState();
int[] handleArr = new int[1]; int[] handleArr = new int[1];
glGenFramebuffers(1, handleArr, 0); glGenFramebuffers(1, handleArr, 0);
...@@ -70,12 +74,12 @@ public class GLFBO { ...@@ -70,12 +74,12 @@ public class GLFBO {
for(int i=0; i<numColors; ++i) { for(int i=0; i<numColors; ++i) {
color.add(initTexture(width, height, GL_COLOR_ATTACHMENT0 + i)); color.add(initTexture(width, height, GL_COLOR_ATTACHMENT0 + i));
} }
// state.restore();
state.restore();
} }
@Override @Override
protected void finalize() throws Throwable { protected void finalize() throws Throwable {
Log.i("GLFBO", "finalize");
super.finalize(); super.finalize();
int[] handleArr = new int[] { handle }; int[] handleArr = new int[] { handle };
glDeleteFramebuffers(1, handleArr, 0); glDeleteFramebuffers(1, handleArr, 0);
...@@ -87,40 +91,37 @@ public class GLFBO { ...@@ -87,40 +91,37 @@ public class GLFBO {
if(status != GL_FRAMEBUFFER_COMPLETE) { if(status != GL_FRAMEBUFFER_COMPLETE) {
switch (status) { switch (status) {
case GL_FRAMEBUFFER_UNSUPPORTED: case GL_FRAMEBUFFER_UNSUPPORTED:
logger.severe("Framebuffer unsupported"); throw new RuntimeException("Framebuffer unsupported");
break;
case GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT: case GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT:
logger.severe("Framebuffer incomplete attachment"); throw new RuntimeException("Framebuffer incomplete attachment");
break;
case GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS: case GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS:
logger.severe("Framebuffer incomplete dimensions"); throw new RuntimeException("Framebuffer incomplete dimensions");
break;
case GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT: case GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT:
logger.severe("Framebuffer incomplete missing attachment"); throw new RuntimeException("Framebuffer incomplete missing attachment");
break;
default: default:
logger.severe("Failed to create framebuffer: " + status); throw new RuntimeException("Failed to create framebuffer: " + status);
} }
} }
} }
public void bind () { public void bind () {
Log.i("GLFBO", "bind");
glBindFramebuffer(GL_FRAMEBUFFER, handle); glBindFramebuffer(GL_FRAMEBUFFER, handle);
glViewport(0, 0, width, height); glViewport(0, 0, width, height);
} }
public void setShape(int w, int h) { public void setShape(int w, int h) {
Log.i("GLFBO", "setShape "+w+" "+h);
if (w == width && h == height) return; if (w == width && h == height) return;
int[] maxFBOSize = new int[1]; int[] maxFBOSize = new int[1];
glGetIntegerv(GL_MAX_RENDERBUFFER_SIZE, maxFBOSize, 0); glGetIntegerv(GL_MAX_RENDERBUFFER_SIZE, maxFBOSize, 0);
if( w < 0 || w > maxFBOSize[0] || h < 0 || h > maxFBOSize[0]) { if( w < 0 || w > maxFBOSize[0] || h < 0 || h > maxFBOSize[0]) {
logger.severe("Can't resize framebuffer. Invalid dimensions"); throw new IllegalArgumentException("Can't resize framebuffer. Invalid dimensions");
return;
} }
width = w; width = w;
height = h; height = h;
FBOState state = new FBOState(); //FBOState state = new FBOState();
for (GLTexture clr: color) { for (GLTexture clr: color) {
clr.setShape(w, h); clr.setShape(w, h);
...@@ -129,6 +130,6 @@ public class GLFBO { ...@@ -129,6 +130,6 @@ public class GLFBO {
glBindFramebuffer(GL_FRAMEBUFFER, handle); glBindFramebuffer(GL_FRAMEBUFFER, handle);
checkStatus(); checkStatus();
state.restore(); //state.restore();
} }
} }
...@@ -5,18 +5,13 @@ import android.database.Cursor; ...@@ -5,18 +5,13 @@ import android.database.Cursor;
import android.graphics.Bitmap; import android.graphics.Bitmap;
import android.graphics.BitmapFactory; import android.graphics.BitmapFactory;
import android.graphics.Matrix; import android.graphics.Matrix;
import android.media.ExifInterface;
import android.net.Uri; import android.net.Uri;
import android.os.AsyncTask; import android.os.AsyncTask;
import android.provider.MediaStore; import android.provider.MediaStore;
import android.support.annotation.Nullable; import android.support.annotation.Nullable;
import com.facebook.common.util.UriUtil; import com.facebook.common.util.UriUtil;
import com.facebook.drawee.interfaces.DraweeController;
import com.facebook.imagepipeline.request.ImageRequest;
import com.facebook.imagepipeline.request.ImageRequestBuilder;
import java.io.File;
import java.io.IOException; import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
import java.net.URL; import java.net.URL;
...@@ -216,29 +211,25 @@ public class GLImage { ...@@ -216,29 +211,25 @@ public class GLImage {
if (bitmap == null) { if (bitmap == null) {
return null; return null;
} }
bitmap = rotateImage(bitmap);
return bitmap;
}
Bitmap transformedBitmap;
Matrix matrix = new Matrix();
private Bitmap rotateImage(final Bitmap bitmap) {
if (bitmap == null) {
return null;
}
Bitmap rotatedBitmap = bitmap;
try { try {
int orientation = getImageOrientation(); int orientation = getImageOrientation();
if (orientation != 0) { if (orientation != 0) {
Matrix matrix = new Matrix();
matrix.postRotate(orientation); matrix.postRotate(orientation);
rotatedBitmap = Bitmap.createBitmap(bitmap, 0, 0, bitmap.getWidth(),
bitmap.getHeight(), matrix, true);
bitmap.recycle();
} }
} catch (IOException e) { } catch (IOException e) {
e.printStackTrace(); e.printStackTrace();
} }
return rotatedBitmap;
matrix.postScale(1, -1);
transformedBitmap = Bitmap.createBitmap(bitmap, 0, 0, bitmap.getWidth(), bitmap.getHeight(), matrix, true);
bitmap.recycle();
return transformedBitmap;
} }
protected abstract int getImageOrientation() throws IOException; protected abstract int getImageOrientation() throws IOException;
......
package com.projectseptember.RNGL; package com.projectseptember.RNGL;
import static android.opengl.GLES20.*; import static android.opengl.GLES20.*;
import java.nio.ByteBuffer; import java.nio.ByteBuffer;
...@@ -8,12 +9,9 @@ import java.nio.FloatBuffer; ...@@ -8,12 +9,9 @@ import java.nio.FloatBuffer;
import java.nio.IntBuffer; import java.nio.IntBuffer;
import java.util.HashMap; import java.util.HashMap;
import java.util.Map; import java.util.Map;
import java.util.logging.Logger;
public class GLShader { public class GLShader {
private static final Logger logger = Logger.getLogger(GLShader.class.getName());
private final String name; private final String name;
private final String vert; private final String vert;
private final String frag; private final String frag;
...@@ -38,10 +36,15 @@ public class GLShader { ...@@ -38,10 +36,15 @@ public class GLShader {
} }
} }
public void runtimeException (String msg) {
throw new RuntimeException("Shader '"+name+"': "+msg);
}
public void bind () { public void bind () {
ensureCompile();
if (!glIsProgram(program)) { if (!glIsProgram(program)) {
logger.severe("Shader '"+name+"': not a program!"); runtimeException("not a program");
return;
} }
glUseProgram(program); glUseProgram(program);
glBindBuffer(GL_ARRAY_BUFFER, buffer[0]); glBindBuffer(GL_ARRAY_BUFFER, buffer[0]);
...@@ -55,7 +58,7 @@ public class GLShader { ...@@ -55,7 +58,7 @@ public class GLShader {
glGetProgramiv(program, GL_VALIDATE_STATUS, validSuccess, 0); glGetProgramiv(program, GL_VALIDATE_STATUS, validSuccess, 0);
if (validSuccess[0] == GL_FALSE) { if (validSuccess[0] == GL_FALSE) {
glGetProgramInfoLog(program); glGetProgramInfoLog(program);
logger.severe("Shader '" + name + "': Validation failed " + glGetProgramInfoLog(program)); runtimeException("Validation failed " + glGetProgramInfoLog(program));
} }
} }
...@@ -86,7 +89,7 @@ public class GLShader { ...@@ -86,7 +89,7 @@ public class GLShader {
glUniformMatrix4fv(uniformLocations.get(name), 1, false, buf); glUniformMatrix4fv(uniformLocations.get(name), 1, false, buf);
break; break;
default: default:
throw new Error("Unsupported case: uniform '" + name + "' type: " + type); runtimeException("Unsupported case: uniform '" + name + "' type: " + type);
} }
} }
public void setUniform (String name, IntBuffer buf, int type) { public void setUniform (String name, IntBuffer buf, int type) {
...@@ -104,7 +107,7 @@ public class GLShader { ...@@ -104,7 +107,7 @@ public class GLShader {
glUniform4iv(uniformLocations.get(name), 1, buf); glUniform4iv(uniformLocations.get(name), 1, buf);
break; break;
default: default:
throw new Error("Unsupported case: uniform '"+name+"' type: "+type); runtimeException("Unsupported case: uniform '"+name+"' type: "+type);
} }
} }
...@@ -117,14 +120,14 @@ public class GLShader { ...@@ -117,14 +120,14 @@ public class GLShader {
} }
private static int compileShader (String name, String code, int shaderType) { private int compileShader (String code, int shaderType) {
int shaderHandle = glCreateShader(shaderType); int shaderHandle = glCreateShader(shaderType);
glShaderSource(shaderHandle, code); glShaderSource(shaderHandle, code);
glCompileShader(shaderHandle); glCompileShader(shaderHandle);
int compileSuccess[] = new int[1]; int compileSuccess[] = new int[1];
glGetShaderiv(shaderHandle, GL_COMPILE_STATUS, compileSuccess, 0); glGetShaderiv(shaderHandle, GL_COMPILE_STATUS, compileSuccess, 0);
if (compileSuccess[0] == GL_FALSE) { if (compileSuccess[0] == GL_FALSE) {
logger.severe("Shader '"+name+"' failed to compile: "+glGetShaderInfoLog(shaderHandle)); runtimeException("failed to compile: " + glGetShaderInfoLog(shaderHandle));
return -1; return -1;
} }
return shaderHandle; return shaderHandle;
...@@ -149,10 +152,10 @@ public class GLShader { ...@@ -149,10 +152,10 @@ public class GLShader {
} }
private void makeProgram () { private void makeProgram () {
int vertex = compileShader(name, vert, GL_VERTEX_SHADER); int vertex = compileShader(vert, GL_VERTEX_SHADER);
if (vertex == -1) return; if (vertex == -1) return;
int fragment = compileShader(name, frag, GL_FRAGMENT_SHADER); int fragment = compileShader(frag, GL_FRAGMENT_SHADER);
if (fragment == -1) return; if (fragment == -1) return;
program = glCreateProgram(); program = glCreateProgram();
...@@ -163,12 +166,13 @@ public class GLShader { ...@@ -163,12 +166,13 @@ public class GLShader {
int[] linkSuccess = new int[1]; int[] linkSuccess = new int[1];
glGetProgramiv(program, GL_LINK_STATUS, linkSuccess, 0); glGetProgramiv(program, GL_LINK_STATUS, linkSuccess, 0);
if (linkSuccess[0] == GL_FALSE) { if (linkSuccess[0] == GL_FALSE) {
logger.severe("Shader '"+name+"': Linking failed "+glGetProgramInfoLog(program)); runtimeException("Linking failed "+glGetProgramInfoLog(program));
return;
} }
glUseProgram(program); glUseProgram(program);
validate();
computeMeta(); computeMeta();
pointerLoc = glGetAttribLocation(program, "position"); pointerLoc = glGetAttribLocation(program, "position");
......
...@@ -3,16 +3,23 @@ package com.projectseptember.RNGL; ...@@ -3,16 +3,23 @@ package com.projectseptember.RNGL;
import android.graphics.Bitmap; import android.graphics.Bitmap;
import android.graphics.Canvas; import android.graphics.Canvas;
import android.graphics.Color; import android.graphics.Color;
import android.graphics.Matrix;
import android.opengl.GLUtils; import android.opengl.GLUtils;
import android.view.View; import android.view.View;
import static android.opengl.GLES20.*; import static android.opengl.GLES20.*;
public class GLTexture { public class GLTexture {
public int handle; private int handle;
public Bitmap bitmapCurrentlyUploaded = null; private Bitmap bitmapCurrentlyUploaded = null;
private void dealloc () { public GLTexture () {
makeTexture();
}
@Override
protected void finalize() throws Throwable {
super.finalize();
int[] handleArr = new int[] { handle }; int[] handleArr = new int[] { handle };
glDeleteTextures(1, handleArr, 0); glDeleteTextures(1, handleArr, 0);
bitmapCurrentlyUploaded = null; bitmapCurrentlyUploaded = null;
...@@ -66,16 +73,27 @@ public class GLTexture { ...@@ -66,16 +73,27 @@ public class GLTexture {
setPixels(bitmap); setPixels(bitmap);
} }
public void setPixelsWithView (View view) { public void setShape (int width, int height) {
Bitmap bitmap = Bitmap.createBitmap( view.getLayoutParams().width, view.getLayoutParams().height, Bitmap.Config.ARGB_8888); bind();
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, null);
}
public static Bitmap captureView (View view) {
int w = view.getWidth();
int h = view.getHeight();
if (w <= 0 || h <= 0) return Bitmap.createBitmap(2, 2, Bitmap.Config.ARGB_8888);
Bitmap bitmap = Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_8888);
Canvas canvas = new Canvas(bitmap); Canvas canvas = new Canvas(bitmap);
view.layout(view.getLeft(), view.getTop(), view.getRight(), view.getBottom()); view.layout(0, 0, view.getWidth(), view.getHeight());
view.draw(canvas); view.draw(canvas);
setPixels(bitmap); Matrix matrix = new Matrix();
matrix.postScale(1, -1);
Bitmap transformedBitmap = Bitmap.createBitmap(bitmap, 0, 0, bitmap.getWidth(), bitmap.getHeight(), matrix, true);
bitmap.recycle();
return transformedBitmap;
} }
public void setShape (int width, int height) { public int getHandle() {
bind(); return handle;
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, null);
} }
} }
package com.projectseptember.RNGL; package com.projectseptember.RNGL;
import android.opengl.GLSurfaceView;
import com.facebook.react.bridge.ReactApplicationContext; import com.facebook.react.bridge.ReactApplicationContext;
import com.facebook.react.bridge.ReactContextBaseJavaModule; import com.facebook.react.bridge.ReactContextBaseJavaModule;
import com.facebook.react.bridge.ReactMethod; import com.facebook.react.bridge.ReactMethod;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment