Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
G
gl-react-native-v2
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Jira
Jira
Merge Requests
0
Merge Requests
0
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
ym
gl-react-native-v2
Commits
216d445a
Commit
216d445a
authored
Nov 13, 2015
by
Gaëtan Renaudeau
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
WIP
parent
76f6b237
Changes
12
Show whitespace changes
Inline
Side-by-side
Showing
12 changed files
with
1458 additions
and
38 deletions
+1458
-38
android/build.gradle
android/build.gradle
+2
-1
android/src/main/java/com/projectseptember/RNGL/GLCanvas.java
...oid/src/main/java/com/projectseptember/RNGL/GLCanvas.java
+605
-0
android/src/main/java/com/projectseptember/RNGL/GLCanvasManager.java
.../main/java/com/projectseptember/RNGL/GLCanvasManager.java
+52
-32
android/src/main/java/com/projectseptember/RNGL/GLData.java
android/src/main/java/com/projectseptember/RNGL/GLData.java
+47
-0
android/src/main/java/com/projectseptember/RNGL/GLFBO.java
android/src/main/java/com/projectseptember/RNGL/GLFBO.java
+134
-0
android/src/main/java/com/projectseptember/RNGL/GLImage.java
android/src/main/java/com/projectseptember/RNGL/GLImage.java
+240
-0
android/src/main/java/com/projectseptember/RNGL/GLRenderData.java
...src/main/java/com/projectseptember/RNGL/GLRenderData.java
+46
-0
android/src/main/java/com/projectseptember/RNGL/GLShader.java
...oid/src/main/java/com/projectseptember/RNGL/GLShader.java
+205
-0
android/src/main/java/com/projectseptember/RNGL/GLTexture.java
...id/src/main/java/com/projectseptember/RNGL/GLTexture.java
+81
-0
android/src/main/java/com/projectseptember/RNGL/RNGLContext.java
.../src/main/java/com/projectseptember/RNGL/RNGLContext.java
+38
-4
android/src/main/java/com/projectseptember/RNGL/RNGLPackage.java
.../src/main/java/com/projectseptember/RNGL/RNGLPackage.java
+1
-1
android/src/main/java/com/projectseptember/RNGL/UniformValue.java
...src/main/java/com/projectseptember/RNGL/UniformValue.java
+7
-0
No files found.
android/build.gradle
View file @
216d445a
...
...
@@ -30,5 +30,6 @@ repositories {
}
dependencies
{
compile
'com.facebook.react:react-native:0.11.+'
// FIXME: version shouldn't be hardcoded? how do to peerDep ?
compile
'com.facebook.react:react-native:0.14.+'
}
android/src/main/java/com/projectseptember/RNGL/GLCanvas.java
0 → 100644
View file @
216d445a
package
com.projectseptember.RNGL
;
import
static
android
.
opengl
.
GLES20
.*;
import
android.graphics.PixelFormat
;
import
android.opengl.GLSurfaceView
;
import
android.util.DisplayMetrics
;
import
android.view.View
;
import
android.view.ViewGroup
;
import
com.facebook.react.bridge.Arguments
;
import
com.facebook.react.bridge.ReactContext
;
import
com.facebook.react.bridge.ReadableArray
;
import
com.facebook.react.bridge.ReadableMap
;
import
com.facebook.react.bridge.ReadableMapKeySetIterator
;
import
com.facebook.react.bridge.WritableMap
;
import
com.facebook.react.uimanager.ThemedReactContext
;
import
com.facebook.react.uimanager.events.RCTEventEmitter
;
import
java.nio.ByteBuffer
;
import
java.nio.ByteOrder
;
import
java.nio.FloatBuffer
;
import
java.nio.IntBuffer
;
import
java.util.ArrayList
;
import
java.util.HashMap
;
import
java.util.LinkedList
;
import
java.util.List
;
import
java.util.Map
;
import
java.util.Queue
;
import
java.util.logging.Logger
;
import
javax.microedition.khronos.egl.EGLConfig
;
import
javax.microedition.khronos.opengles.GL10
;
public
class
GLCanvas
extends
GLSurfaceView
implements
GLSurfaceView
.
Renderer
{
private
static
final
Logger
logger
=
Logger
.
getLogger
(
GLCanvas
.
class
.
getName
());
private
ReactContext
reactContext
;
private
RNGLContext
rnglContext
;
private
boolean
preloadingDone
=
false
;
private
boolean
deferredRendering
=
false
;
private
GLRenderData
renderData
;
private
int
[]
defaultFBO
;
private
int
nbContentTextures
;
private
int
renderId
;
private
boolean
opaque
;
private
boolean
autoRedraw
;
private
boolean
eventsThrough
;
private
boolean
visibleContent
;
private
int
captureNextFrameId
;
private
GLData
data
;
private
ReadableArray
imagesToPreload
;
// TODO we need to make a List<Uri> I guess? probably Uri should be resolved in advance. not in GLImage
List
<
String
>
preloaded
;
// TODO List<Uri>
private
Map
<
String
,
GLImage
>
images
=
new
HashMap
<>();
private
List
<
GLTexture
>
contentTextures
=
new
ArrayList
<>();
public
GLCanvas
(
ThemedReactContext
context
)
{
super
(
context
);
reactContext
=
context
;
this
.
rnglContext
=
context
.
getNativeModule
(
RNGLContext
.
class
);
this
.
setEGLContextClientVersion
(
2
);
this
.
setEGLConfigChooser
(
8
,
8
,
8
,
8
,
16
,
0
);
this
.
getHolder
().
setFormat
(
PixelFormat
.
RGBA_8888
);
this
.
setRenderer
(
this
);
this
.
setRenderMode
(
GLSurfaceView
.
RENDERMODE_WHEN_DIRTY
);
this
.
requestRender
();
preloadingDone
=
true
;
// TODO
}
@Override
public
void
onSurfaceCreated
(
GL10
gl
,
EGLConfig
config
)
{
// FIXME anything to do here?
}
@Override
public
void
onSurfaceChanged
(
GL10
gl
,
int
width
,
int
height
)
{
// FIXME anything to do here?
}
@Override
public
void
onDrawFrame
(
GL10
gl
)
{
runAll
(
mRunOnDraw
);
syncEventsThrough
();
// FIXME, really need to do this ?
if
(!
preloadingDone
)
{
glClearColor
(
0.0f
,
0.0f
,
0.0f
,
0.0f
);
glClear
(
GL_COLOR_BUFFER_BIT
);
return
;
}
boolean
needsDeferredRendering
=
nbContentTextures
>
0
&&
!
autoRedraw
;
if
(
needsDeferredRendering
&&
!
deferredRendering
)
{
deferredRendering
=
true
;
this
.
requestRender
();
// FIXME is this working correctly?
/*
dispatch_async(dispatch_get_main_queue(), ^{
if (!weakSelf) return;
deferredRendering = true;
[weakSelf setNeedsDisplay];
});
*/
}
else
{
this
.
render
();
deferredRendering
=
false
;
}
}
public
void
setNbContentTextures
(
int
nbContentTextures
)
{
this
.
nbContentTextures
=
nbContentTextures
;
// TODO: resize uniform content textures
}
public
void
setRenderId
(
int
renderId
)
{
this
.
renderId
=
renderId
;
if
(
nbContentTextures
>
0
)
this
.
requestRender
();
}
public
void
setOpaque
(
boolean
opaque
)
{
this
.
opaque
=
opaque
;
/* // FIXME: how to do ?
if (opaque) {
this.getHolder().setFormat(PixelFormat.RGB_565);
}
else {
this.getHolder().setFormat(PixelFormat.TRANSLUCENT);
}
*/
this
.
requestRender
();
// FIXME is this required?
}
public
void
setAutoRedraw
(
boolean
autoRedraw
)
{
this
.
autoRedraw
=
autoRedraw
;
this
.
setRenderMode
(
autoRedraw
?
GLSurfaceView
.
RENDERMODE_CONTINUOUSLY
:
GLSurfaceView
.
RENDERMODE_WHEN_DIRTY
);
}
public
void
setEventsThrough
(
boolean
eventsThrough
)
{
this
.
eventsThrough
=
eventsThrough
;
syncEventsThrough
();
}
public
void
setVisibleContent
(
boolean
visibleContent
)
{
this
.
visibleContent
=
visibleContent
;
syncEventsThrough
();
}
public
void
setCaptureNextFrameId
(
int
captureNextFrameId
)
{
// FIXME move away from this pattern. just use a method, same to ObjC impl
this
.
captureNextFrameId
=
captureNextFrameId
;
this
.
requestRender
();
}
private
boolean
ensureCompiledShader
(
List
<
GLData
>
data
)
{
for
(
GLData
d:
data
)
{
if
(!
ensureCompiledShader
(
d
));
return
false
;
}
return
true
;
}
private
boolean
ensureCompiledShader
(
GLData
data
)
{
GLShader
shader
=
rnglContext
.
getShader
(
data
.
shader
);
if
(
shader
==
null
)
return
false
;
shader
.
ensureCompile
();
return
ensureCompiledShader
(
data
.
children
)
&&
ensureCompiledShader
(
data
.
contextChildren
);
}
public
void
setData
(
GLData
data
)
{
this
.
data
=
data
;
this
.
requestSyncData
();
}
public
void
setImagesToPreload
(
ReadableArray
imagesToPreload
)
{
logger
.
info
(
"setImageToPreload, working correctly?"
);
// TODO
if
(
preloadingDone
)
return
;
if
(
imagesToPreload
.
size
()
==
0
)
{
dispatchOnLoad
();
preloadingDone
=
true
;
}
else
{
preloadingDone
=
false
;
}
this
.
imagesToPreload
=
imagesToPreload
;
}
// Sync methods
private
final
Queue
<
Runnable
>
mRunOnDraw
=
new
LinkedList
<>();
protected
void
runOnDraw
(
final
Runnable
runnable
)
{
synchronized
(
mRunOnDraw
)
{
mRunOnDraw
.
add
(
runnable
);
requestRender
();
}
}
private
void
runAll
(
Queue
<
Runnable
>
queue
)
{
synchronized
(
queue
)
{
while
(!
queue
.
isEmpty
())
{
queue
.
poll
().
run
();
}
}
}
public
void
requestSyncData
()
{
runOnDraw
(
new
Runnable
()
{
public
void
run
()
{
if
(
ensureCompiledShader
(
data
))
syncData
();
else
requestSyncData
();
}
});
}
public
void
syncContextTextures
()
{
int
i
=
0
;
for
(
GLTexture
texture:
contentTextures
)
{
View
view
=
((
ViewGroup
)
this
.
getParent
()).
getChildAt
(
i
);
texture
.
setPixelsWithView
(
view
);
i
++;
}
}
public
void
resizeUniformContentTextures
(
int
n
)
{
int
length
=
contentTextures
.
size
();
if
(
length
==
n
)
return
;
if
(
n
<
length
)
{
contentTextures
=
contentTextures
.
subList
(
0
,
n
);
}
else
{
for
(
int
i
=
contentTextures
.
size
();
i
<
n
;
i
++)
{
contentTextures
.
add
(
new
GLTexture
());
}
}
}
private
int
countPreloaded
()
{
int
nb
=
0
;
for
(
int
i
=
0
;
i
<
imagesToPreload
.
size
();
i
++)
{
/*
if ([_preloaded containsObject:srcResource(toload)]) // TODO
nb++;
*/
}
return
nb
;
}
private
void
onImageLoad
(
String
loaded
)
{
if
(!
preloadingDone
)
{
preloaded
.
add
(
loaded
);
int
count
=
countPreloaded
();
int
total
=
imagesToPreload
.
size
();
double
progress
=
((
double
)
count
)
/
((
double
)
total
);
dispatchOnProgress
(
progress
,
count
,
total
);
if
(
count
==
total
)
{
dispatchOnLoad
();
preloadingDone
=
true
;
requestSyncData
();
}
}
else
{
// Any texture image load will trigger a future re-sync of data (if no preloaded)
requestSyncData
();
}
}
public
String
srcResource
(
ReadableMap
res
)
{
String
src
=
null
;
boolean
isStatic
=
res
.
hasKey
(
"isStatic"
)
&&
res
.
getBoolean
(
"isStatic"
);
if
(
res
.
hasKey
(
"path"
))
src
=
res
.
getString
(
"path"
);
if
(
src
==
null
||
isStatic
)
src
=
res
.
getString
(
"uri"
);
return
src
;
}
public
GLRenderData
recSyncData
(
GLData
data
,
HashMap
<
String
,
GLImage
>
images
)
{
Map
<
String
,
GLImage
>
prevImages
=
this
.
images
;
GLShader
shader
=
rnglContext
.
getShader
(
data
.
shader
);
Map
<
String
,
Integer
>
uniformsInteger
=
new
HashMap
<>();
Map
<
String
,
Float
>
uniformsFloat
=
new
HashMap
<>();
Map
<
String
,
IntBuffer
>
uniformsIntBuffer
=
new
HashMap
<>();
Map
<
String
,
FloatBuffer
>
uniformsFloatBuffer
=
new
HashMap
<>();
Map
<
String
,
GLTexture
>
textures
=
new
HashMap
<>();
List
<
GLRenderData
>
contextChildren
=
new
ArrayList
<>();
List
<
GLRenderData
>
children
=
new
ArrayList
<>();
shader
.
bind
();
for
(
GLData
child:
data
.
contextChildren
)
{
contextChildren
.
add
(
recSyncData
(
child
,
images
));
}
for
(
GLData
child:
data
.
children
)
{
children
.
add
(
recSyncData
(
child
,
images
));
}
Map
<
String
,
Integer
>
uniformTypes
=
shader
.
getUniformTypes
();
int
units
=
0
;
ReadableMapKeySetIterator
iterator
=
data
.
uniforms
.
keySetIterator
();
while
(
iterator
.
hasNextKey
())
{
String
uniformName
=
iterator
.
nextKey
();
int
type
=
uniformTypes
.
get
(
uniformName
);
ReadableMap
dataUniforms
=
data
.
uniforms
;
if
(
type
==
GL_SAMPLER_2D
||
type
==
GL_SAMPLER_CUBE
)
{
uniformsInteger
.
put
(
uniformName
,
units
++);
if
(
dataUniforms
.
isNull
(
uniformName
))
{
GLTexture
emptyTexture
=
new
GLTexture
();
emptyTexture
.
setPixelsEmpty
();
textures
.
put
(
uniformName
,
emptyTexture
);
}
else
{
ReadableMap
value
=
dataUniforms
.
getMap
(
uniformName
);
String
t
=
value
.
getString
(
"type"
);
if
(
t
.
equals
(
"content"
))
{
int
id
=
value
.
getInt
(
"id"
);
if
(
id
>=
contentTextures
.
size
())
{
this
.
resizeUniformContentTextures
(
id
+
1
);
}
textures
.
put
(
uniformName
,
contentTextures
.
get
(
id
));
}
else
if
(
t
.
equals
(
"fbo"
))
{
int
id
=
value
.
getInt
(
"id"
);
GLFBO
fbo
=
rnglContext
.
getFBO
(
id
);
textures
.
put
(
uniformName
,
fbo
.
color
.
get
(
0
));
}
else
if
(
t
.
equals
(
"uri"
))
{
final
String
src
=
srcResource
(
value
);
if
(
src
==
null
||
src
.
equals
(
""
))
{
logger
.
severe
(
"Shader '"
+
shader
.
getName
()+
": texture uniform '"
+
uniformName
+
"': Invalid uri format '"
+
value
+
"'"
);
}
GLImage
image
=
images
.
get
(
src
);
if
(
image
==
null
)
{
image
=
prevImages
.
get
(
src
);
if
(
image
!=
null
)
images
.
put
(
src
,
image
);
}
if
(
image
==
null
)
{
image
=
new
GLImage
(
reactContext
.
getApplicationContext
(),
new
Runnable
()
{
public
void
run
()
{
onImageLoad
(
src
);
}
});
// TODO bind on load
/*
[[GLImage alloc] initWithBridge:_bridge withOnLoad:^{
if (weakSelf) [weakSelf onImageLoad:src];
}];
*/
image
.
setSrc
(
src
);
images
.
put
(
src
,
image
);
}
textures
.
put
(
uniformName
,
image
.
getTexture
());
}
else
{
logger
.
severe
(
"Shader '"
+
shader
.
getName
()+
": texture uniform '"
+
uniformName
+
"': Unexpected type '"
+
type
+
"'"
);
}
}
}
else
{
switch
(
type
)
{
case
GL_INT:
uniformsInteger
.
put
(
uniformName
,
dataUniforms
.
getInt
(
uniformName
));
break
;
case
GL_BOOL:
uniformsInteger
.
put
(
uniformName
,
dataUniforms
.
getBoolean
(
uniformName
)
?
1
:
0
);
break
;
case
GL_FLOAT:
uniformsFloat
.
put
(
uniformName
,
(
float
)
dataUniforms
.
getDouble
(
uniformName
));
break
;
case
GL_FLOAT_VEC2:
case
GL_FLOAT_VEC3:
case
GL_FLOAT_VEC4:
case
GL_FLOAT_MAT2:
case
GL_FLOAT_MAT3:
case
GL_FLOAT_MAT4:
ReadableArray
arr
=
dataUniforms
.
getArray
(
uniformName
);
if
(
arraySizeForType
(
type
)
!=
arr
.
size
())
{
throw
new
Error
(
"Shader '"
+
shader
.
getName
()+
"' uniform '"
+
uniformName
+
"': Invalid array size: "
+
arr
.
size
()+
". Expected: "
+
arraySizeForType
(
type
));
}
uniformsFloatBuffer
.
put
(
uniformName
,
parseAsFloatArray
(
arr
));
break
;
case
GL_INT_VEC2:
case
GL_INT_VEC3:
case
GL_INT_VEC4:
case
GL_BOOL_VEC2:
case
GL_BOOL_VEC3:
case
GL_BOOL_VEC4:
ReadableArray
arr2
=
dataUniforms
.
getArray
(
uniformName
);
if
(
arraySizeForType
(
type
)
!=
arr2
.
size
())
{
throw
new
Error
(
"Shader '"
+
shader
.
getName
()+
"' uniform '"
+
uniformName
+
"': Invalid array size: "
+
arr2
.
size
()+
". Expected: "
+
arraySizeForType
(
type
));
}
uniformsIntBuffer
.
put
(
uniformName
,
parseAsIntArray
(
arr2
));
break
;
default
:
throw
new
Error
(
"Shader '"
+
shader
.
getName
()+
"' uniform '"
+
uniformName
+
"': type not supported: "
+
type
);
}
}
}
int
[]
maxTextureUnits
=
new
int
[
1
];
glGetIntegerv
(
GL_MAX_TEXTURE_IMAGE_UNITS
,
maxTextureUnits
,
0
);
if
(
units
>
maxTextureUnits
[
0
])
{
logger
.
severe
(
"Shader '"
+
shader
.
getName
()+
": Maximum number of texture reach. got "
+
units
+
" >= max "
+
maxTextureUnits
);
}
for
(
String
uniformName:
uniformTypes
.
keySet
())
{
if
(!
uniformsFloat
.
containsKey
(
uniformName
)
&&
!
uniformsInteger
.
containsKey
(
uniformName
)
&&
!
uniformsFloatBuffer
.
containsKey
(
uniformName
)
&&
!
uniformsIntBuffer
.
containsKey
(
uniformName
))
{
logger
.
severe
(
"Shader '"
+
shader
.
getName
()+
": All defined uniforms must be provided. Missing '"
+
uniformName
+
"'"
);
}
}
return
new
GLRenderData
(
shader
,
uniformsInteger
,
uniformsFloat
,
uniformsIntBuffer
,
uniformsFloatBuffer
,
textures
,
data
.
width
,
data
.
height
,
data
.
fboId
,
contextChildren
,
children
);
}
private
FloatBuffer
parseAsFloatArray
(
ReadableArray
array
)
{
int
size
=
array
.
size
();
FloatBuffer
buf
=
ByteBuffer
.
allocateDirect
(
size
*
4
)
.
order
(
ByteOrder
.
nativeOrder
())
.
asFloatBuffer
();
for
(
int
i
=
0
;
i
<
size
;
i
++)
buf
.
put
((
float
)
array
.
getDouble
(
i
));
buf
.
position
(
0
);
return
buf
;
}
private
IntBuffer
parseAsIntArray
(
ReadableArray
array
)
{
int
size
=
array
.
size
();
IntBuffer
buf
=
ByteBuffer
.
allocateDirect
(
size
*
4
)
.
order
(
ByteOrder
.
nativeOrder
())
.
asIntBuffer
();
for
(
int
i
=
0
;
i
<
size
;
i
++)
buf
.
put
(
array
.
getInt
(
i
));
buf
.
position
(
0
);
return
buf
;
}
private
int
arraySizeForType
(
int
type
)
{
switch
(
type
)
{
case
GL_FLOAT_VEC2:
case
GL_INT_VEC2:
case
GL_BOOL_VEC2:
return
2
;
case
GL_FLOAT_VEC3:
case
GL_INT_VEC3:
case
GL_BOOL_VEC3:
return
3
;
case
GL_FLOAT_VEC4:
case
GL_INT_VEC4:
case
GL_BOOL_VEC4:
case
GL_FLOAT_MAT2:
return
4
;
case
GL_FLOAT_MAT3:
return
9
;
case
GL_FLOAT_MAT4:
return
16
;
default
:
throw
new
Error
(
"Invalid array type: "
+
type
);
}
}
public
void
syncData
()
{
if
(
data
==
null
)
return
;
HashMap
<
String
,
GLImage
>
images
=
new
HashMap
<>();
renderData
=
recSyncData
(
data
,
images
);
this
.
images
=
images
;
this
.
requestRender
();
// FIXME don't do it here since syncData is called in render phase
}
public
void
recRender
(
GLRenderData
renderData
)
{
DisplayMetrics
dm
=
reactContext
.
getResources
().
getDisplayMetrics
();
int
w
=
new
Float
(
renderData
.
width
.
floatValue
()
*
dm
.
density
).
intValue
();
int
h
=
new
Float
(
renderData
.
height
.
floatValue
()
*
dm
.
density
).
intValue
();
for
(
GLRenderData
child:
renderData
.
contextChildren
)
recRender
(
child
);
for
(
GLRenderData
child:
renderData
.
children
)
recRender
(
child
);
if
(
renderData
.
fboId
==
-
1
)
{
glBindFramebuffer
(
GL_FRAMEBUFFER
,
defaultFBO
[
0
]);
glViewport
(
0
,
0
,
w
,
h
);
}
else
{
GLFBO
fbo
=
rnglContext
.
getFBO
(
renderData
.
fboId
);
fbo
.
setShape
(
w
,
h
);
fbo
.
bind
();
}
renderData
.
shader
.
bind
();
for
(
String
uniformName:
renderData
.
textures
.
keySet
())
{
GLTexture
texture
=
renderData
.
textures
.
get
(
uniformName
);
int
unit
=
renderData
.
uniformsInteger
.
get
(
uniformName
);
texture
.
bind
(
unit
);
}
Map
<
String
,
Integer
>
uniformTypes
=
renderData
.
shader
.
getUniformTypes
();
for
(
String
uniformName:
renderData
.
uniformsInteger
.
keySet
())
{
renderData
.
shader
.
setUniform
(
uniformName
,
renderData
.
uniformsInteger
.
get
(
uniformName
));
}
for
(
String
uniformName:
renderData
.
uniformsFloat
.
keySet
())
{
renderData
.
shader
.
setUniform
(
uniformName
,
renderData
.
uniformsFloat
.
get
(
uniformName
));
}
for
(
String
uniformName:
renderData
.
uniformsFloatBuffer
.
keySet
())
{
renderData
.
shader
.
setUniform
(
uniformName
,
renderData
.
uniformsFloatBuffer
.
get
(
uniformName
),
uniformTypes
.
get
(
uniformName
));
}
for
(
String
uniformName:
renderData
.
uniformsIntBuffer
.
keySet
())
{
renderData
.
shader
.
setUniform
(
uniformName
,
renderData
.
uniformsIntBuffer
.
get
(
uniformName
),
uniformTypes
.
get
(
uniformName
));
}
glBlendFunc
(
GL_SRC_ALPHA
,
GL_ONE_MINUS_SRC_ALPHA
);
glClearColor
(
0.0f
,
0.0f
,
0.0f
,
0.0f
);
glClear
(
GL_COLOR_BUFFER_BIT
);
glDrawArrays
(
GL_TRIANGLES
,
0
,
6
);
}
public
void
render
()
{
if
(
renderData
==
null
)
return
;
syncContextTextures
();
defaultFBO
=
new
int
[
1
];
glGetIntegerv
(
GL_FRAMEBUFFER_BINDING
,
defaultFBO
,
0
);
glEnable
(
GL_BLEND
);
recRender
(
renderData
);
glDisable
(
GL_BLEND
);
glBindFramebuffer
(
GL_FRAMEBUFFER
,
defaultFBO
[
0
]);
}
public
void
syncEventsThrough
()
{
// TODO: figure out how to do this (Obj C code below)
//self.userInteractionEnabled = !(_eventsThrough);
//self.superview.userInteractionEnabled = !(_eventsThrough && !_visibleContent);
}
private
void
dispatchOnProgress
(
double
progress
,
int
count
,
int
total
)
{
WritableMap
event
=
Arguments
.
createMap
();
event
.
putDouble
(
"progress"
,
progress
);
event
.
putInt
(
"count"
,
count
);
event
.
putInt
(
"total"
,
total
);
ReactContext
reactContext
=
(
ReactContext
)
getContext
();
reactContext
.
getJSModule
(
RCTEventEmitter
.
class
).
receiveEvent
(
getId
(),
"progress"
,
event
);
}
public
void
dispatchOnLoad
()
{
WritableMap
event
=
Arguments
.
createMap
();
ReactContext
reactContext
=
(
ReactContext
)
getContext
();
reactContext
.
getJSModule
(
RCTEventEmitter
.
class
).
receiveEvent
(
getId
(),
"load"
,
event
);
}
}
android/src/main/java/com/projectseptember/RNGL/GLCanvasManager.java
View file @
216d445a
package
com.projectseptember.RNGL
;
import
android.opengl.GLSurfaceView
;
import
android.app.ActivityManager
;
import
android.content.Context
;
import
android.content.pm.ConfigurationInfo
;
import
android.support.annotation.Nullable
;
import
android.util.Log
;
import
com.facebook.react.uimanager.CatalystStylesDiffMap
;
import
com.facebook.react.bridge.ReadableArray
;
import
com.facebook.react.bridge.ReadableMap
;
import
com.facebook.react.uimanager.SimpleViewManager
;
import
com.facebook.react.uimanager.ThemedReactContext
;
import
com.facebook.react.uimanager.ReactProp
;
import
javax.microedition.khronos.egl.EGLConfig
;
import
javax.microedition.khronos.opengles.GL10
;
public
class
GLCanvasManager
extends
SimpleViewManager
<
GLSurfaceView
>
{
public
class
GLCanvasManager
extends
SimpleViewManager
<
GLCanvas
>
{
public
static
final
String
REACT_CLASS
=
"GLCanvas"
;
// TODO... props
@ReactProp
(
name
=
"nbContentTextures"
)
public
void
setNbContentTextures
(
GLCanvas
view
,
int
nbContentTextures
)
{
view
.
setNbContentTextures
(
nbContentTextures
);
}
@ReactProp
(
name
=
"renderId"
)
public
void
setRenderId
(
GLCanvas
view
,
int
renderId
)
{
view
.
setRenderId
(
renderId
);
}
@
Override
public
String
getName
(
)
{
return
REACT_CLASS
;
@
ReactProp
(
name
=
"opaque"
)
public
void
setOpaque
(
GLCanvas
view
,
boolean
opaque
)
{
view
.
setOpaque
(
opaque
)
;
}
@Override
public
GLSurfaceView
createViewInstance
(
ThemedReactContext
context
)
{
GLSurfaceView
view
=
new
GLSurfaceView
(
context
);
view
.
setRenderer
(
new
GLSurfaceView
.
Renderer
()
{
@Override
public
void
onSurfaceCreated
(
GL10
gl
,
EGLConfig
config
)
{
@ReactProp
(
name
=
"autoRedraw"
)
public
void
setAutoRedraw
(
GLCanvas
view
,
boolean
autoRedraw
)
{
view
.
setAutoRedraw
(
autoRedraw
);
}
@ReactProp
(
name
=
"eventsThrough"
)
public
void
setEventsThrough
(
GLCanvas
view
,
boolean
eventsThrough
)
{
view
.
setEventsThrough
(
eventsThrough
);
}
@Override
public
void
onSurfaceChanged
(
GL10
gl
,
int
width
,
int
heigh
t
)
{
gl
.
glViewport
(
0
,
0
,
width
,
heigh
t
);
@ReactProp
(
name
=
"visibleContent"
)
public
void
setVisibleContent
(
GLCanvas
view
,
boolean
visibleConten
t
)
{
view
.
setVisibleContent
(
visibleConten
t
);
}
@Override
public
void
onDrawFrame
(
GL10
gl
)
{
gl
.
glClearColor
(
1.0f
,
0.0f
,
0.0f
,
1.0f
);
gl
.
glClear
(
GL10
.
GL_COLOR_BUFFER_BIT
);
@ReactProp
(
name
=
"captureNextFrameId"
)
public
void
setCaptureNextFrameId
(
GLCanvas
view
,
int
captureNextFrameId
)
{
view
.
setCaptureNextFrameId
(
captureNextFrameId
);
}
@ReactProp
(
name
=
"data"
)
public
void
setData
(
GLCanvas
view
,
@Nullable
ReadableMap
glData
)
{
view
.
setData
(
glData
==
null
?
null
:
GLData
.
fromMap
(
glData
));
}
@ReactProp
(
name
=
"imagesToPreload"
)
public
void
setImagesToPreload
(
GLCanvas
view
,
@Nullable
ReadableArray
imageToPreload
)
{
view
.
setImagesToPreload
(
imageToPreload
);
}
});
return
view
;
@Override
public
String
getName
()
{
return
REACT_CLASS
;
}
@Override
public
void
updateView
(
final
GLSurfaceView
view
,
final
CatalystStylesDiffMap
props
)
{
super
.
updateView
(
view
,
props
);
// TODO... call setters with props
// view.requestRender();
public
GLCanvas
createViewInstance
(
ThemedReactContext
context
)
{
return
new
GLCanvas
(
context
);
}
}
android/src/main/java/com/projectseptember/RNGL/GLData.java
0 → 100644
View file @
216d445a
package
com.projectseptember.RNGL
;
import
com.facebook.react.bridge.ReadableArray
;
import
com.facebook.react.bridge.ReadableMap
;
import
java.util.ArrayList
;
import
java.util.List
;
public
class
GLData
{
final
Integer
shader
;
final
ReadableMap
uniforms
;
final
Integer
width
;
final
Integer
height
;
final
Integer
fboId
;
final
List
<
GLData
>
contextChildren
;
final
List
<
GLData
>
children
;
public
GLData
(
Integer
shader
,
ReadableMap
uniforms
,
Integer
width
,
Integer
height
,
Integer
fboId
,
List
<
GLData
>
contextChildren
,
List
<
GLData
>
children
)
{
this
.
shader
=
shader
;
this
.
uniforms
=
uniforms
;
this
.
width
=
width
;
this
.
height
=
height
;
this
.
fboId
=
fboId
;
this
.
contextChildren
=
contextChildren
;
this
.
children
=
children
;
}
public
static
List
<
GLData
>
fromArray
(
ReadableArray
arr
)
{
ArrayList
<
GLData
>
list
=
new
ArrayList
<>();
for
(
int
i
=
0
;
i
<
arr
.
size
();
i
++)
{
list
.
add
(
fromMap
(
arr
.
getMap
(
i
)));
}
return
list
;
}
public
static
GLData
fromMap
(
ReadableMap
map
)
{
Integer
shader
=
map
.
getInt
(
"shader"
);
ReadableMap
uniforms
=
map
.
getMap
(
"uniforms"
);
Integer
width
=
map
.
getInt
(
"width"
);
Integer
height
=
map
.
getInt
(
"height"
);
Integer
fboId
=
map
.
getInt
(
"fboId"
);
List
<
GLData
>
children
=
fromArray
(
map
.
getArray
(
"children"
));
List
<
GLData
>
contextChildren
=
fromArray
(
map
.
getArray
(
"contextChildren"
));
return
new
GLData
(
shader
,
uniforms
,
width
,
height
,
fboId
,
contextChildren
,
children
);
}
}
android/src/main/java/com/projectseptember/RNGL/GLFBO.java
0 → 100644
View file @
216d445a
package
com.projectseptember.RNGL
;
import
java.util.ArrayList
;
import
java.util.List
;
import
java.util.logging.Logger
;
import
static
android
.
opengl
.
GLES20
.*;
public
class
GLFBO
{
// TODO
private
static
final
Logger
logger
=
Logger
.
getLogger
(
GLFBO
.
class
.
getName
());
public
final
List
<
GLTexture
>
color
=
new
ArrayList
<>();
private
int
handle
;
private
int
width
=
0
;
private
int
height
=
0
;
private
static
GLTexture
initTexture
(
int
width
,
int
height
,
int
attachment
)
{
GLTexture
texture
=
new
GLTexture
();
texture
.
bind
();
texture
.
setShape
(
width
,
height
);
glFramebufferTexture2D
(
GL_FRAMEBUFFER
,
attachment
,
GL_TEXTURE_2D
,
texture
.
handle
,
0
);
return
texture
;
}
int
initRenderBuffer
(
int
width
,
int
height
,
int
component
,
int
attachment
)
{
int
[]
handleArr
=
new
int
[
1
];
glGenRenderbuffers
(
1
,
handleArr
,
0
);
int
handle
=
handleArr
[
0
];
glBindRenderbuffer
(
GL_RENDERBUFFER
,
handle
);
glRenderbufferStorage
(
GL_RENDERBUFFER
,
component
,
width
,
height
);
glFramebufferRenderbuffer
(
GL_FRAMEBUFFER
,
attachment
,
GL_RENDERBUFFER
,
handle
);
return
handle
;
}
class
FBOState
{
private
int
fbo
;
private
int
rbo
;
private
int
tex
;
public
FBOState
()
{
int
[]
fbo
=
new
int
[
1
],
rbo
=
new
int
[
1
],
tex
=
new
int
[
1
];
glGetIntegerv
(
GL_FRAMEBUFFER_BINDING
,
fbo
,
0
);
glGetIntegerv
(
GL_RENDERBUFFER_BINDING
,
rbo
,
0
);
glGetIntegerv
(
GL_TEXTURE_BINDING_2D
,
tex
,
0
);
this
.
fbo
=
fbo
[
0
];
this
.
rbo
=
rbo
[
0
];
this
.
tex
=
tex
[
0
];
}
private
void
restore
()
{
glBindFramebuffer
(
GL_FRAMEBUFFER
,
fbo
);
glBindRenderbuffer
(
GL_FRAMEBUFFER
,
rbo
);
glBindTexture
(
GL_FRAMEBUFFER
,
tex
);
}
}
public
GLFBO
()
{
FBOState
state
=
new
FBOState
();
int
[]
handleArr
=
new
int
[
1
];
glGenFramebuffers
(
1
,
handleArr
,
0
);
handle
=
handleArr
[
0
];
int
numColors
=
1
;
glBindFramebuffer
(
GL_FRAMEBUFFER
,
handle
);
for
(
int
i
=
0
;
i
<
numColors
;
++
i
)
{
color
.
add
(
initTexture
(
width
,
height
,
GL_COLOR_ATTACHMENT0
+
i
));
}
state
.
restore
();
}
@Override
protected
void
finalize
()
throws
Throwable
{
super
.
finalize
();
int
[]
handleArr
=
new
int
[]
{
handle
};
glDeleteFramebuffers
(
1
,
handleArr
,
0
);
}
void
checkStatus
()
{
int
status
=
glCheckFramebufferStatus
(
GL_FRAMEBUFFER
);
if
(
status
!=
GL_FRAMEBUFFER_COMPLETE
)
{
switch
(
status
)
{
case
GL_FRAMEBUFFER_UNSUPPORTED:
logger
.
severe
(
"Framebuffer unsupported"
);
break
;
case
GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT:
logger
.
severe
(
"Framebuffer incomplete attachment"
);
break
;
case
GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS:
logger
.
severe
(
"Framebuffer incomplete dimensions"
);
break
;
case
GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT:
logger
.
severe
(
"Framebuffer incomplete missing attachment"
);
break
;
default
:
logger
.
severe
(
"Failed to create framebuffer: "
+
status
);
}
}
}
public
void
bind
()
{
glBindFramebuffer
(
GL_FRAMEBUFFER
,
handle
);
glViewport
(
0
,
0
,
width
,
height
);
}
public
void
setShape
(
int
w
,
int
h
)
{
if
(
w
==
width
&&
h
==
height
)
return
;
int
[]
maxFBOSize
=
new
int
[
1
];
glGetIntegerv
(
GL_MAX_RENDERBUFFER_SIZE
,
maxFBOSize
,
0
);
if
(
w
<
0
||
w
>
maxFBOSize
[
0
]
||
h
<
0
||
h
>
maxFBOSize
[
0
])
{
logger
.
severe
(
"Can't resize framebuffer. Invalid dimensions"
);
return
;
}
width
=
w
;
height
=
h
;
FBOState
state
=
new
FBOState
();
for
(
GLTexture
clr:
color
)
{
clr
.
setShape
(
w
,
h
);
}
glBindFramebuffer
(
GL_FRAMEBUFFER
,
handle
);
checkStatus
();
state
.
restore
();
}
}
android/src/main/java/com/projectseptember/RNGL/GLImage.java
0 → 100644
View file @
216d445a
package
com.projectseptember.RNGL
;
import
android.content.Context
;
import
android.database.Cursor
;
import
android.graphics.Bitmap
;
import
android.graphics.BitmapFactory
;
import
android.graphics.Matrix
;
import
android.media.ExifInterface
;
import
android.net.Uri
;
import
android.os.AsyncTask
;
import
android.provider.MediaStore
;
import
android.support.annotation.Nullable
;
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.InputStream
;
import
java.net.URL
;
/*
This class is maintained and inspired from
https://github.com/facebook/react-native/blob/master/ReactAndroid/src/main/java/com/facebook/react/views/image/ReactImageView.java
also inspired from
https://github.com/CyberAgent/android-gpuimage/blob/master/library/src/jp/co/cyberagent/android/gpuimage/GPUImage.java
*/
public
class
GLImage
{
private
final
Context
context
;
private
String
src
;
private
GLTexture
texture
;
private
Uri
uri
;
private
boolean
isLocalImage
;
private
boolean
isDirty
;
private
AsyncTask
<
Void
,
Void
,
Bitmap
>
task
;
private
Runnable
onload
;
public
GLImage
(
Context
context
,
Runnable
onload
)
{
this
.
context
=
context
;
this
.
onload
=
onload
;
this
.
texture
=
new
GLTexture
();
}
public
void
setSrc
(
String
src
)
{
if
(
this
.
src
==
src
)
return
;
this
.
src
=
src
;
reloadImage
();
}
private
void
reloadImage
()
{
uri
=
null
;
if
(
src
!=
null
)
{
try
{
uri
=
Uri
.
parse
(
src
);
// Verify scheme is set, so that relative uri (used by static resources) are not handled.
if
(
uri
.
getScheme
()
==
null
)
{
uri
=
null
;
}
}
catch
(
Exception
e
)
{
// ignore malformed uri, then attempt to extract resource ID.
}
if
(
uri
==
null
)
{
uri
=
getResourceDrawableUri
(
context
,
src
);
isLocalImage
=
true
;
}
else
{
isLocalImage
=
false
;
}
}
isDirty
=
true
;
}
public
void
onLoad
(
Bitmap
bitmap
)
{
texture
.
setPixels
(
bitmap
);
this
.
onload
.
run
();
}
public
GLTexture
getTexture
()
{
if
(
isDirty
)
{
if
(
task
!=
null
)
task
.
cancel
(
true
);
task
=
new
LoadImageUriTask
(
this
,
uri
).
execute
();
isDirty
=
false
;
}
return
texture
;
}
private
static
@Nullable
Uri
getResourceDrawableUri
(
Context
context
,
@Nullable
String
name
)
{
if
(
name
==
null
||
name
.
isEmpty
())
{
return
null
;
}
name
=
name
.
toLowerCase
().
replace
(
"-"
,
"_"
);
int
resId
=
context
.
getResources
().
getIdentifier
(
name
,
"drawable"
,
context
.
getPackageName
());
return
new
Uri
.
Builder
()
.
scheme
(
UriUtil
.
LOCAL_RESOURCE_SCHEME
)
.
path
(
String
.
valueOf
(
resId
))
.
build
();
}
private
class
LoadImageUriTask
extends
LoadImageTask
{
private
final
Uri
mUri
;
public
LoadImageUriTask
(
GLImage
gpuImage
,
Uri
uri
)
{
super
(
gpuImage
);
mUri
=
uri
;
}
@Override
protected
Bitmap
decode
(
BitmapFactory
.
Options
options
)
{
try
{
InputStream
inputStream
;
if
(
mUri
.
getScheme
().
startsWith
(
"http"
)
||
mUri
.
getScheme
().
startsWith
(
"https"
))
{
inputStream
=
new
URL
(
mUri
.
toString
()).
openStream
();
}
else
{
inputStream
=
context
.
getContentResolver
().
openInputStream
(
mUri
);
}
return
BitmapFactory
.
decodeStream
(
inputStream
,
null
,
options
);
}
catch
(
Exception
e
)
{
e
.
printStackTrace
();
}
return
null
;
}
@Override
protected
int
getImageOrientation
()
throws
IOException
{
Cursor
cursor
=
context
.
getContentResolver
().
query
(
mUri
,
new
String
[]
{
MediaStore
.
Images
.
ImageColumns
.
ORIENTATION
},
null
,
null
,
null
);
if
(
cursor
==
null
||
cursor
.
getCount
()
!=
1
)
{
return
0
;
}
cursor
.
moveToFirst
();
int
orientation
=
cursor
.
getInt
(
0
);
cursor
.
close
();
return
orientation
;
}
}
/*
private class LoadImageFileTask extends LoadImageTask {
private final File mImageFile;
public LoadImageFileTask(GLImage gpuImage, File file) {
super(gpuImage);
mImageFile = file;
}
@Override
protected Bitmap decode(BitmapFactory.Options options) {
return BitmapFactory.decodeFile(mImageFile.getAbsolutePath(), options);
}
@Override
protected int getImageOrientation() throws IOException {
ExifInterface exif = new ExifInterface(mImageFile.getAbsolutePath());
int orientation = exif.getAttributeInt(ExifInterface.TAG_ORIENTATION, 1);
switch (orientation) {
case ExifInterface.ORIENTATION_NORMAL:
return 0;
case ExifInterface.ORIENTATION_ROTATE_90:
return 90;
case ExifInterface.ORIENTATION_ROTATE_180:
return 180;
case ExifInterface.ORIENTATION_ROTATE_270:
return 270;
default:
return 0;
}
}
}
*/
private
abstract
class
LoadImageTask
extends
AsyncTask
<
Void
,
Void
,
Bitmap
>
{
private
GLImage
glImage
;
public
LoadImageTask
(
GLImage
glImage
)
{
this
.
glImage
=
glImage
;
}
@Override
protected
Bitmap
doInBackground
(
Void
...
params
)
{
return
loadResizedImage
();
}
@Override
protected
void
onPostExecute
(
Bitmap
bitmap
)
{
super
.
onPostExecute
(
bitmap
);
glImage
.
onLoad
(
bitmap
);
}
protected
abstract
Bitmap
decode
(
BitmapFactory
.
Options
options
);
private
Bitmap
loadResizedImage
()
{
BitmapFactory
.
Options
options
=
new
BitmapFactory
.
Options
();
options
.
inJustDecodeBounds
=
true
;
decode
(
options
);
options
=
new
BitmapFactory
.
Options
();
options
.
inPreferredConfig
=
Bitmap
.
Config
.
RGB_565
;
options
.
inTempStorage
=
new
byte
[
32
*
1024
];
Bitmap
bitmap
=
decode
(
options
);
if
(
bitmap
==
null
)
{
return
null
;
}
bitmap
=
rotateImage
(
bitmap
);
return
bitmap
;
}
private
Bitmap
rotateImage
(
final
Bitmap
bitmap
)
{
if
(
bitmap
==
null
)
{
return
null
;
}
Bitmap
rotatedBitmap
=
bitmap
;
try
{
int
orientation
=
getImageOrientation
();
if
(
orientation
!=
0
)
{
Matrix
matrix
=
new
Matrix
();
matrix
.
postRotate
(
orientation
);
rotatedBitmap
=
Bitmap
.
createBitmap
(
bitmap
,
0
,
0
,
bitmap
.
getWidth
(),
bitmap
.
getHeight
(),
matrix
,
true
);
bitmap
.
recycle
();
}
}
catch
(
IOException
e
)
{
e
.
printStackTrace
();
}
return
rotatedBitmap
;
}
protected
abstract
int
getImageOrientation
()
throws
IOException
;
}
}
android/src/main/java/com/projectseptember/RNGL/GLRenderData.java
0 → 100644
View file @
216d445a
package
com.projectseptember.RNGL
;
import
java.nio.FloatBuffer
;
import
java.nio.IntBuffer
;
import
java.util.List
;
import
java.util.Map
;
public
class
GLRenderData
{
final
GLShader
shader
;
final
Map
<
String
,
Integer
>
uniformsInteger
;
final
Map
<
String
,
Float
>
uniformsFloat
;
final
Map
<
String
,
IntBuffer
>
uniformsIntBuffer
;
final
Map
<
String
,
FloatBuffer
>
uniformsFloatBuffer
;
final
Map
<
String
,
GLTexture
>
textures
;
final
Integer
width
;
final
Integer
height
;
final
Integer
fboId
;
final
List
<
GLRenderData
>
contextChildren
;
final
List
<
GLRenderData
>
children
;
public
GLRenderData
(
GLShader
shader
,
Map
<
String
,
Integer
>
uniformsInteger
,
Map
<
String
,
Float
>
uniformsFloat
,
Map
<
String
,
IntBuffer
>
uniformsIntBuffer
,
Map
<
String
,
FloatBuffer
>
uniformsFloatBuffer
,
Map
<
String
,
GLTexture
>
textures
,
Integer
width
,
Integer
height
,
Integer
fboId
,
List
<
GLRenderData
>
contextChildren
,
List
<
GLRenderData
>
children
)
{
this
.
shader
=
shader
;
this
.
uniformsInteger
=
uniformsInteger
;
this
.
uniformsFloat
=
uniformsFloat
;
this
.
uniformsIntBuffer
=
uniformsIntBuffer
;
this
.
uniformsFloatBuffer
=
uniformsFloatBuffer
;
this
.
textures
=
textures
;
this
.
width
=
width
;
this
.
height
=
height
;
this
.
fboId
=
fboId
;
this
.
contextChildren
=
contextChildren
;
this
.
children
=
children
;
}
}
android/src/main/java/com/projectseptember/RNGL/GLShader.java
0 → 100644
View file @
216d445a
package
com.projectseptember.RNGL
;
import
static
android
.
opengl
.
GLES20
.*;
import
java.nio.ByteBuffer
;
import
java.nio.ByteOrder
;
import
java.nio.FloatBuffer
;
import
java.nio.IntBuffer
;
import
java.util.HashMap
;
import
java.util.Map
;
import
java.util.logging.Logger
;
public
class
GLShader
{
private
static
final
Logger
logger
=
Logger
.
getLogger
(
GLShader
.
class
.
getName
());
private
final
String
name
;
private
final
String
vert
;
private
final
String
frag
;
private
Map
<
String
,
Integer
>
uniformTypes
;
private
int
program
;
// Program of the shader
private
int
buffer
[];
// the buffer currently contains 2 static triangles covering the surface
private
int
pointerLoc
;
// The "pointer" attribute is used to iterate over vertex
private
Map
<
String
,
Integer
>
uniformLocations
;
// The uniform locations cache
public
GLShader
(
String
name
,
String
vert
,
String
frag
)
{
this
.
name
=
name
;
this
.
vert
=
vert
;
this
.
frag
=
frag
;
makeProgram
();
}
@Override
protected
void
finalize
()
throws
Throwable
{
super
.
finalize
();
if
(
buffer
!=
null
)
{
glDeleteProgram
(
program
);
glDeleteBuffers
(
1
,
buffer
,
0
);
}
}
public
void
bind
()
{
if
(!
glIsProgram
(
program
))
{
logger
.
severe
(
"Shader '"
+
name
+
"': not a program!"
);
return
;
}
glUseProgram
(
program
);
glBindBuffer
(
GL_ARRAY_BUFFER
,
buffer
[
0
]);
glEnableVertexAttribArray
(
pointerLoc
);
glVertexAttribPointer
(
pointerLoc
,
2
,
GL_FLOAT
,
false
,
0
,
0
);
}
public
void
validate
()
{
glValidateProgram
(
program
);
int
[]
validSuccess
=
new
int
[
1
];
glGetProgramiv
(
program
,
GL_VALIDATE_STATUS
,
validSuccess
,
0
);
if
(
validSuccess
[
0
]
==
GL_FALSE
)
{
glGetProgramInfoLog
(
program
);
logger
.
severe
(
"Shader '"
+
name
+
"': Validation failed "
+
glGetProgramInfoLog
(
program
));
}
}
public
void
setUniform
(
String
name
,
Integer
i
)
{
glUniform1i
(
uniformLocations
.
get
(
name
),
i
);
}
public
void
setUniform
(
String
name
,
Float
f
)
{
glUniform1f
(
uniformLocations
.
get
(
name
),
f
);
}
public
void
setUniform
(
String
name
,
FloatBuffer
buf
,
int
type
)
{
switch
(
type
)
{
case
GL_FLOAT_VEC2:
glUniform2fv
(
uniformLocations
.
get
(
name
),
1
,
buf
);
break
;
case
GL_FLOAT_VEC3:
glUniform3fv
(
uniformLocations
.
get
(
name
),
1
,
buf
);
break
;
case
GL_FLOAT_VEC4:
glUniform4fv
(
uniformLocations
.
get
(
name
),
1
,
buf
);
break
;
case
GL_FLOAT_MAT2:
glUniformMatrix2fv
(
uniformLocations
.
get
(
name
),
1
,
false
,
buf
);
break
;
case
GL_FLOAT_MAT3:
glUniformMatrix3fv
(
uniformLocations
.
get
(
name
),
1
,
false
,
buf
);
break
;
case
GL_FLOAT_MAT4:
glUniformMatrix4fv
(
uniformLocations
.
get
(
name
),
1
,
false
,
buf
);
break
;
default
:
throw
new
Error
(
"Unsupported case: uniform '"
+
name
+
"' type: "
+
type
);
}
}
public
void
setUniform
(
String
name
,
IntBuffer
buf
,
int
type
)
{
switch
(
type
)
{
case
GL_INT_VEC2:
case
GL_BOOL_VEC2:
glUniform2iv
(
uniformLocations
.
get
(
name
),
1
,
buf
);
break
;
case
GL_INT_VEC3:
case
GL_BOOL_VEC3:
glUniform3iv
(
uniformLocations
.
get
(
name
),
1
,
buf
);
break
;
case
GL_INT_VEC4:
case
GL_BOOL_VEC4:
glUniform4iv
(
uniformLocations
.
get
(
name
),
1
,
buf
);
break
;
default
:
throw
new
Error
(
"Unsupported case: uniform '"
+
name
+
"' type: "
+
type
);
}
}
public
String
getName
()
{
return
name
;
}
public
Map
<
String
,
Integer
>
getUniformTypes
()
{
return
uniformTypes
;
}
private
static
int
compileShader
(
String
name
,
String
code
,
int
shaderType
)
{
int
shaderHandle
=
glCreateShader
(
shaderType
);
glShaderSource
(
shaderHandle
,
code
);
glCompileShader
(
shaderHandle
);
int
compileSuccess
[]
=
new
int
[
1
];
glGetShaderiv
(
shaderHandle
,
GL_COMPILE_STATUS
,
compileSuccess
,
0
);
if
(
compileSuccess
[
0
]
==
GL_FALSE
)
{
logger
.
severe
(
"Shader '"
+
name
+
"' failed to compile: "
+
glGetShaderInfoLog
(
shaderHandle
));
return
-
1
;
}
return
shaderHandle
;
}
private
void
computeMeta
()
{
Map
<
String
,
Integer
>
uniforms
=
new
HashMap
<>();
Map
<
String
,
Integer
>
locations
=
new
HashMap
<>();
int
[]
nbUniforms
=
new
int
[
1
];
int
[]
type
=
new
int
[
1
];
int
[]
size
=
new
int
[
1
];
glGetProgramiv
(
program
,
GL_ACTIVE_UNIFORMS
,
nbUniforms
,
0
);
for
(
int
i
=
0
;
i
<
nbUniforms
[
0
];
i
++)
{
String
uniformName
=
glGetActiveUniform
(
program
,
i
,
size
,
0
,
type
,
0
);
int
location
=
glGetUniformLocation
(
program
,
uniformName
);
uniforms
.
put
(
uniformName
,
type
[
0
]);
locations
.
put
(
uniformName
,
location
);
}
this
.
uniformTypes
=
uniforms
;
this
.
uniformLocations
=
locations
;
}
private
void
makeProgram
()
{
int
vertex
=
compileShader
(
name
,
vert
,
GL_VERTEX_SHADER
);
if
(
vertex
==
-
1
)
return
;
int
fragment
=
compileShader
(
name
,
frag
,
GL_FRAGMENT_SHADER
);
if
(
fragment
==
-
1
)
return
;
program
=
glCreateProgram
();
glAttachShader
(
program
,
vertex
);
glAttachShader
(
program
,
fragment
);
glLinkProgram
(
program
);
int
[]
linkSuccess
=
new
int
[
1
];
glGetProgramiv
(
program
,
GL_LINK_STATUS
,
linkSuccess
,
0
);
if
(
linkSuccess
[
0
]
==
GL_FALSE
)
{
logger
.
severe
(
"Shader '"
+
name
+
"': Linking failed "
+
glGetProgramInfoLog
(
program
));
return
;
}
glUseProgram
(
program
);
computeMeta
();
pointerLoc
=
glGetAttribLocation
(
program
,
"position"
);
buffer
=
new
int
[
1
];
glGenBuffers
(
1
,
buffer
,
0
);
glBindBuffer
(
GL_ARRAY_BUFFER
,
buffer
[
0
]);
float
buf
[]
=
{
-
1.0f
,
-
1.0f
,
1.0f
,
-
1.0f
,
-
1.0f
,
1.0f
,
-
1.0f
,
1.0f
,
1.0f
,
-
1.0f
,
1.0f
,
1.0f
};
FloatBuffer
bufferData
=
ByteBuffer
.
allocateDirect
(
buf
.
length
*
4
)
.
order
(
ByteOrder
.
nativeOrder
())
.
asFloatBuffer
();
bufferData
.
put
(
buf
).
position
(
0
);
glBufferData
(
GL_ARRAY_BUFFER
,
buf
.
length
*
4
,
bufferData
,
GL_STATIC_DRAW
);
}
public
boolean
isReady
()
{
return
buffer
!=
null
&&
uniformLocations
!=
null
;
}
public
boolean
ensureCompile
()
{
if
(!
isReady
())
makeProgram
();
return
isReady
();
}
}
android/src/main/java/com/projectseptember/RNGL/GLTexture.java
0 → 100644
View file @
216d445a
package
com.projectseptember.RNGL
;
import
android.graphics.Bitmap
;
import
android.graphics.Canvas
;
import
android.graphics.Color
;
import
android.opengl.GLUtils
;
import
android.view.View
;
import
static
android
.
opengl
.
GLES20
.*;
public
class
GLTexture
{
public
int
handle
;
public
Bitmap
bitmapCurrentlyUploaded
=
null
;
private
void
dealloc
()
{
int
[]
handleArr
=
new
int
[]
{
handle
};
glDeleteTextures
(
1
,
handleArr
,
0
);
bitmapCurrentlyUploaded
=
null
;
}
private
void
makeTexture
()
{
int
[]
handleArr
=
new
int
[
1
];
glGenTextures
(
1
,
handleArr
,
0
);
handle
=
handleArr
[
0
];
glBindTexture
(
GL_TEXTURE_2D
,
handle
);
glTexParameteri
(
GL_TEXTURE_2D
,
GL_TEXTURE_MIN_FILTER
,
GL_LINEAR
);
glTexParameteri
(
GL_TEXTURE_2D
,
GL_TEXTURE_MAG_FILTER
,
GL_LINEAR
);
glTexParameteri
(
GL_TEXTURE_2D
,
GL_TEXTURE_WRAP_S
,
GL_CLAMP_TO_EDGE
);
glTexParameteri
(
GL_TEXTURE_2D
,
GL_TEXTURE_WRAP_T
,
GL_CLAMP_TO_EDGE
);
}
public
int
bind
(
int
unit
)
{
glActiveTexture
(
GL_TEXTURE0
+
unit
);
glBindTexture
(
GL_TEXTURE_2D
,
handle
);
return
unit
;
}
public
void
bind
()
{
glBindTexture
(
GL_TEXTURE_2D
,
handle
);
}
public
void
setPixels
(
Bitmap
bitmap
)
{
if
(
bitmap
!=
bitmapCurrentlyUploaded
)
{
bitmapCurrentlyUploaded
=
bitmap
;
bind
();
GLUtils
.
texImage2D
(
GL_TEXTURE_2D
,
0
,
bitmap
,
0
);
}
}
public
void
setPixelsRandom
(
int
width
,
int
height
)
{
Bitmap
bitmap
=
Bitmap
.
createBitmap
(
width
,
height
,
Bitmap
.
Config
.
ARGB_8888
);
for
(
int
x
=
0
;
x
<
width
;
x
++)
{
for
(
int
y
=
0
;
y
<
height
;
y
++)
{
bitmap
.
setPixel
(
x
,
y
,
Color
.
rgb
(
(
int
)(
255.0
*
Math
.
random
()),
(
int
)(
255.0
*
Math
.
random
()),
(
int
)(
255.0
*
Math
.
random
())));
}
}
setPixels
(
bitmap
);
}
public
void
setPixelsEmpty
()
{
Bitmap
bitmap
=
Bitmap
.
createBitmap
(
2
,
2
,
Bitmap
.
Config
.
ARGB_8888
);
setPixels
(
bitmap
);
}
public
void
setPixelsWithView
(
View
view
)
{
Bitmap
bitmap
=
Bitmap
.
createBitmap
(
view
.
getLayoutParams
().
width
,
view
.
getLayoutParams
().
height
,
Bitmap
.
Config
.
ARGB_8888
);
Canvas
canvas
=
new
Canvas
(
bitmap
);
view
.
layout
(
view
.
getLeft
(),
view
.
getTop
(),
view
.
getRight
(),
view
.
getBottom
());
view
.
draw
(
canvas
);
setPixels
(
bitmap
);
}
public
void
setShape
(
int
width
,
int
height
)
{
bind
();
glTexImage2D
(
GL_TEXTURE_2D
,
0
,
GL_RGBA
,
width
,
height
,
0
,
GL_RGBA
,
GL_UNSIGNED_BYTE
,
null
);
}
}
android/src/main/java/com/projectseptember/RNGL/RNGLContext.java
View file @
216d445a
package
com.projectseptember.RNGL
;
import
android.opengl.GLSurfaceView
;
import
com.facebook.react.bridge.ReactApplicationContext
;
import
com.facebook.react.bridge.ReactContextBaseJavaModule
;
import
com.facebook.react.bridge.ReactMethod
;
import
com.facebook.react.bridge.ReadableMap
;
import
java.util.HashMap
;
import
java.util.Map
;
import
javax.microedition.khronos.egl.EGLContext
;
public
class
RNGLContext
extends
ReactContextBaseJavaModule
{
// Share GL Context ?
// http://developer.android.com/training/graphics/opengl/environment.html
// http://stackoverflow.com/questions/8845491/sharing-the-egl2-0-context-between-2-glsurfaceviews-caused-egl-bad-access-on-and
// http://stackoverflow.com/questions/5675355/sharing-the-gles20-context-and-textures-between-different-glsurfaceviews
private
static
String
STATIC_VERT
=
"attribute vec2 position;"
+
"varying vec2 uv;"
+
"void main() {"
+
"gl_Position = vec4(position,0.0,1.0);"
+
"uv = vec2(0.5, 0.5) * (position+vec2(1.0, 1.0));"
+
"}"
;
private
Map
<
Integer
,
GLShader
>
shaders
=
new
HashMap
<>();
private
Map
<
Integer
,
GLFBO
>
fbos
=
new
HashMap
<>();
public
RNGLContext
(
ReactApplicationContext
reactContext
)
{
super
(
reactContext
);
}
...
...
@@ -16,10 +39,21 @@ public class RNGLContext extends ReactContextBaseJavaModule {
return
"RNGLContext"
;
}
public
GLShader
getShader
(
Integer
id
)
{
return
shaders
.
get
(
id
);
}
public
GLFBO
getFBO
(
Integer
id
)
{
if
(!
fbos
.
containsKey
(
id
))
{
fbos
.
put
(
id
,
new
GLFBO
());
}
return
fbos
.
get
(
id
);
}
@ReactMethod
public
void
addShader
(
Integer
id
,
ReadableMap
config
)
{
String
frag
=
config
.
getString
(
"frag"
);
String
name
=
config
.
getString
(
"name"
);
System
.
out
.
println
(
"TODO... addShader: "
+
id
+
" "
+
name
);
public
void
addShader
(
final
Integer
id
,
final
ReadableMap
config
)
{
final
String
frag
=
config
.
getString
(
"frag"
);
final
String
name
=
config
.
getString
(
"name"
);
shaders
.
put
(
id
,
new
GLShader
(
name
,
STATIC_VERT
,
frag
)
);
}
}
android/src/main/java/com/projectseptember/RNGL/RNGLPackage.java
View file @
216d445a
android/src/main/java/com/projectseptember/RNGL/UniformValue.java
0 → 100644
View file @
216d445a
package
com.projectseptember.RNGL
;
import
com.facebook.react.bridge.ReadableMap
;
public
class
UniformValue
{
}
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment