Browse Source

Android GL work.

tags/2021-05-28
jules 13 years ago
parent
commit
1804b983a0
8 changed files with 321 additions and 52 deletions
  1. +43
    -12
      extras/JuceDemo/Builds/Android/src/com/juce/JuceDemo.java
  2. +84
    -28
      modules/juce_core/native/java/JuceAppActivity.java
  3. +2
    -2
      modules/juce_core/native/juce_android_SystemStats.cpp
  4. +1
    -1
      modules/juce_graphics/geometry/juce_Point.h
  5. +6
    -0
      modules/juce_gui_basics/native/juce_android_Windowing.cpp
  6. +171
    -6
      modules/juce_opengl/native/juce_android_OpenGLComponent.cpp
  7. +4
    -0
      modules/juce_opengl/opengl/juce_OpenGLComponent.cpp
  8. +10
    -3
      modules/juce_opengl/opengl/juce_OpenGLComponent.h

+ 43
- 12
extras/JuceDemo/Builds/Android/src/com/juce/JuceDemo.java View File

@@ -114,7 +114,10 @@ public final class JuceDemo extends Activity
public final void deleteView (ComponentPeerView view)
{
viewHolder.removeView (view);
ViewGroup group = (ViewGroup) (view.getParent());
if (group != null)
group.removeView (view);
}
final class ViewHolder extends ViewGroup
@@ -246,6 +249,7 @@ public final class JuceDemo extends Activity
public ComponentPeerView (Context context, boolean opaque_)
{
super (context);
setWillNotDraw (false);
opaque = opaque_;
setFocusable (true);
@@ -260,6 +264,7 @@ public final class JuceDemo extends Activity
@Override
public void draw (Canvas canvas)
{
super.draw (canvas);
handlePaint (canvas);
}
@@ -295,11 +300,16 @@ public final class JuceDemo extends Activity
@Override
protected void onSizeChanged (int w, int h, int oldw, int oldh)
{
super.onSizeChanged (w, h, oldw, oldh);
viewSizeChanged();
}
@Override
protected void onLayout (boolean changed, int left, int top, int right, int bottom) {}
protected void onLayout (boolean changed, int left, int top, int right, int bottom)
{
for (int i = getChildCount(); --i >= 0;)
requestTransparentRegion (getChildAt (i));
}
private native void viewSizeChanged();
@@ -321,38 +331,59 @@ public final class JuceDemo extends Activity
{
return true; //xxx needs to check overlapping views
}
public OpenGLView createGLView()
{
OpenGLView glView = new OpenGLView (getContext());
addView (glView);
return glView;
}
}
//==============================================================================
public final class OpenGLView extends GLSurfaceView
implements GLSurfaceView.Renderer
public final class OpenGLView extends GLSurfaceView
implements GLSurfaceView.Renderer
{
public OpenGLView (ComponentPeerView parent)
OpenGLView (Context context)
{
super (parent.getContext());
super (context);
setEGLContextClientVersion (2);
getHolder().setFormat(PixelFormat.TRANSLUCENT);
setVisibility (VISIBLE);
setRenderer (this);
parent.addView (this);
//setRenderMode (RENDERMODE_CONTINUOUSLY);
//requestRender();
}
@Override
public void onSurfaceCreated (GL10 unused, EGLConfig config)
{
contextCreated();
// contextCreated();
}
@Override
public void onDrawFrame (GL10 unused)
{
GLES20.glClearColor (1.0f, 0.5f, 0.0f, 1.0f);
GLES20.glClear (GLES20.GL_COLOR_BUFFER_BIT | GLES20.GL_DEPTH_BUFFER_BIT);
//GLES20.glClearColor (1.0f, 0.5f, 0.0f, 1.0f);
//GLES20.glClear (GLES20.GL_COLOR_BUFFER_BIT | GLES20.GL_DEPTH_BUFFER_BIT);
render();
// render();
}
@Override
public void onSurfaceChanged (GL10 unused, int width, int height)
{
GLES20.glViewport (0, 0, width, height);
//GLES20.glViewport (0, 0, width, height);
}
@Override
protected void onLayout (boolean changed, int left, int top, int right, int bottom)
{
super.onLayout (changed, left, top, right, bottom);
requestLayout();
((ViewGroup) getParent()).requestTransparentRegion (this);
}
private native void contextCreated();


+ 84
- 28
modules/juce_core/native/java/JuceAppActivity.java View File

@@ -32,6 +32,7 @@ import android.content.Context;
import android.os.Bundle;
import android.view.*;
import android.graphics.*;
import android.opengl.*;
import android.text.ClipboardManager;
import java.io.BufferedInputStream;
import java.io.IOException;
@@ -39,6 +40,8 @@ import java.io.InputStream;
import java.io.OutputStream;
import java.net.URL;
import java.net.HttpURLConnection;
import javax.microedition.khronos.egl.EGLConfig;
import javax.microedition.khronos.opengles.GL10;
//==============================================================================
public final class JuceAppActivity extends Activity
@@ -72,9 +75,9 @@ public final class JuceAppActivity extends Activity
}
//==============================================================================
public native void launchApp (String appFile, String appDataDir);
public native void quitApp();
public native void setScreenSize (int screenWidth, int screenHeight);
private native void launchApp (String appFile, String appDataDir);
private native void quitApp();
private native void setScreenSize (int screenWidth, int screenHeight);
//==============================================================================
public static final void printToConsole (String s)
@@ -111,7 +114,10 @@ public final class JuceAppActivity extends Activity
public final void deleteView (ComponentPeerView view)
{
viewHolder.removeView (view);
ViewGroup group = (ViewGroup) (view.getParent());
if (group != null)
group.removeView (view);
}
final class ViewHolder extends ViewGroup
@@ -237,12 +243,13 @@ public final class JuceAppActivity extends Activity
public native void alertDismissed (long callback, int id);
//==============================================================================
public class ComponentPeerView extends View
implements View.OnFocusChangeListener
public final class ComponentPeerView extends ViewGroup
implements View.OnFocusChangeListener
{
public ComponentPeerView (Context context, boolean opaque_)
{
super (context);
setWillNotDraw (false);
opaque = opaque_;
setFocusable (true);
@@ -257,6 +264,7 @@ public final class JuceAppActivity extends Activity
@Override
public void draw (Canvas canvas)
{
super.draw (canvas);
handlePaint (canvas);
}
@@ -292,11 +300,16 @@ public final class JuceAppActivity extends Activity
@Override
protected void onSizeChanged (int w, int h, int oldw, int oldh)
{
super.onSizeChanged (w, h, oldw, oldh);
viewSizeChanged();
}
@Override
protected void onLayout (boolean changed, int left, int top, int right, int bottom) {}
protected void onLayout (boolean changed, int left, int top, int right, int bottom)
{
for (int i = getChildCount(); --i >= 0;)
requestTransparentRegion (getChildAt (i));
}
private native void viewSizeChanged();
@@ -318,6 +331,63 @@ public final class JuceAppActivity extends Activity
{
return true; //xxx needs to check overlapping views
}
public OpenGLView createGLView()
{
OpenGLView glView = new OpenGLView (getContext());
addView (glView);
return glView;
}
}
//==============================================================================
public final class OpenGLView extends GLSurfaceView
implements GLSurfaceView.Renderer
{
OpenGLView (Context context)
{
super (context);
setEGLContextClientVersion (2);
getHolder().setFormat(PixelFormat.TRANSLUCENT);
setVisibility (VISIBLE);
setRenderer (this);
//setRenderMode (RENDERMODE_CONTINUOUSLY);
//requestRender();
}
@Override
public void onSurfaceCreated (GL10 unused, EGLConfig config)
{
// contextCreated();
}
@Override
public void onDrawFrame (GL10 unused)
{
//GLES20.glClearColor (1.0f, 0.5f, 0.0f, 1.0f);
//GLES20.glClear (GLES20.GL_COLOR_BUFFER_BIT | GLES20.GL_DEPTH_BUFFER_BIT);
// render();
}
@Override
public void onSurfaceChanged (GL10 unused, int width, int height)
{
//GLES20.glViewport (0, 0, width, height);
}
@Override
protected void onLayout (boolean changed, int left, int top, int right, int bottom)
{
super.onLayout (changed, left, top, right, bottom);
requestLayout();
((ViewGroup) getParent()).requestTransparentRegion (this);
}
private native void contextCreated();
private native void render();
}
//==============================================================================
@@ -344,7 +414,7 @@ public final class JuceAppActivity extends Activity
c.setMatrix (matrix);
c.drawPath (p, paint);
int sizeNeeded = w * h;
final int sizeNeeded = w * h;
if (cachedRenderArray.length < sizeNeeded)
cachedRenderArray = new int [sizeNeeded];
@@ -393,25 +463,10 @@ public final class JuceAppActivity extends Activity
return num;
}
public final long getPosition()
{
return position;
}
public final long getTotalLength()
{
return -1;
}
public final boolean isExhausted()
{
return false;
}
public final boolean setPosition (long newPos)
{
return false;
}
public final long getPosition() { return position; }
public final long getTotalLength() { return -1; }
public final boolean isExhausted() { return false; }
public final boolean setPosition (long newPos) { return false; }
private HttpURLConnection connection;
private InputStream inputStream;
@@ -419,7 +474,8 @@ public final class JuceAppActivity extends Activity
}
public static final HTTPStream createHTTPStream (String address, boolean isPost, byte[] postData,
String headers, int timeOutMs, java.lang.StringBuffer responseHeaders)
String headers, int timeOutMs,
java.lang.StringBuffer responseHeaders)
{
try
{


+ 2
- 2
modules/juce_core/native/juce_android_SystemStats.cpp View File

@@ -55,14 +55,14 @@ void JNIClassBase::release (JNIEnv* env)
void JNIClassBase::initialiseAllClasses (JNIEnv* env)
{
Array<JNIClassBase*>& classes = getClasses();
const Array<JNIClassBase*>& classes = getClasses();
for (int i = classes.size(); --i >= 0;)
classes.getUnchecked(i)->initialise (env);
}
void JNIClassBase::releaseAllClasses (JNIEnv* env)
{
Array<JNIClassBase*>& classes = getClasses();
const Array<JNIClassBase*>& classes = getClasses();
for (int i = classes.size(); --i >= 0;)
classes.getUnchecked(i)->release (env);
}


+ 1
- 1
modules/juce_graphics/geometry/juce_Point.h View File

@@ -119,7 +119,7 @@ public:
/** Returns the inverse of this point. */
Point operator-() const noexcept { return Point (-x, -y); }
/** Returns the straight-line distance between this point and another one. */
/** Returns the straight-line distance between this point and the origin. */
ValueType getDistanceFromOrigin() const noexcept { return juce_hypot (x, y); }
/** Returns the straight-line distance between this point and another one. */


+ 6
- 0
modules/juce_gui_basics/native/juce_android_Windowing.cpp View File

@@ -78,6 +78,7 @@ DECLARE_JNI_CLASS (CanvasMinimal, "android/graphics/Canvas");
METHOD (hasFocus, "hasFocus", "()Z") \
METHOD (invalidate, "invalidate", "(IIII)V") \
METHOD (containsPoint, "containsPoint", "(II)Z") \
METHOD (createGLView, "createGLView", "()L" JUCE_ANDROID_ACTIVITY_CLASSPATH "$OpenGLView;") \
DECLARE_JNI_CLASS (ComponentPeerView, JUCE_ANDROID_ACTIVITY_CLASSPATH "$ComponentPeerView");
#undef JNI_CLASS_MEMBERS
@@ -585,6 +586,11 @@ ComponentPeer* Component::createNewPeer (int styleFlags, void*)
return new AndroidComponentPeer (this, styleFlags);
}
jobject createOpenGLView (ComponentPeer* peer)
{
jobject parentView = static_cast <jobject> (peer->getNativeHandle());
return getEnv()->CallObjectMethod (parentView, ComponentPeerView.createGLView);
}
//==============================================================================
bool Desktop::canUseSemiTransparentWindows() noexcept


+ 171
- 6
modules/juce_opengl/native/juce_android_OpenGLComponent.cpp View File

@@ -23,22 +23,187 @@
==============================================================================
*/
// TODO
#define JNI_CLASS_MEMBERS(METHOD, STATICMETHOD, FIELD, STATICFIELD) \
METHOD (layout, "layout", "(IIII)V") \
METHOD (invalidate, "invalidate", "(IIII)V") \
DECLARE_JNI_CLASS (OpenGLView, JUCE_ANDROID_ACTIVITY_CLASSPATH "$OpenGLView");
#undef JNI_CLASS_MEMBERS
jobject createOpenGLView (ComponentPeer*);
//==============================================================================
class AndroidGLContext : public OpenGLContext
{
public:
AndroidGLContext (OpenGLComponent* const component_,
ComponentPeer* peer,
const OpenGLPixelFormat& pixelFormat,
const AndroidGLContext* const sharedContext,
const bool isGLES2_)
: component (component_),
lastWidth (0), lastHeight (0),
isGLES2 (isGLES2_),
isInsideGLCallback (false)
{
getContextList().add (this);
jassert (peer != nullptr);
glView = GlobalRef (createOpenGLView (peer));
}
~AndroidGLContext()
{
properties.clear(); // to release any stored programs, etc that may be held in properties.
android.activity.callVoidMethod (JuceAppActivity.deleteView, glView.get());
glView.clear();
getContextList().removeValue (this);
}
//==============================================================================
bool makeActive() const noexcept { return isInsideGLCallback; }
bool makeInactive() const noexcept { return true; }
bool isActive() const noexcept { return isInsideGLCallback; }
void swapBuffers() {}
void* getRawContext() const noexcept { return 0; }
unsigned int getFrameBufferID() const { return 0; }
int getWidth() const { return lastWidth; }
int getHeight() const { return lastHeight; }
bool areShadersAvailable() const { return isGLES2; }
void updateWindowPosition (const Rectangle<int>& bounds)
{
if (lastWidth != bounds.getWidth() || lastHeight != bounds.getHeight())
{
lastWidth = bounds.getWidth();
lastHeight = bounds.getHeight();
glView.callVoidMethod (OpenGLView.layout,
bounds.getX(), bounds.getY(),
lastWidth, lastHeight);
}
}
bool setSwapInterval (const int /*numFramesPerSwap*/) { return false; }
int getSwapInterval() const { return 0; }
//==============================================================================
void contextCreatedCallback()
{
isInsideGLCallback = true;
if (component != nullptr)
dynamic_cast <OpenGLComponent*> (component.get())->newOpenGLContextCreated();
isInsideGLCallback = false;
}
void renderCallback()
{
isInsideGLCallback = true;
if (component != nullptr)
dynamic_cast <OpenGLComponent*> (component.get())->performRender();
isInsideGLCallback = false;
}
//==============================================================================
static Array<AndroidGLContext*>& getContextList()
{
static Array <AndroidGLContext*> contexts;
return contexts;
}
static AndroidGLContext* findContextFor (JNIEnv* env, jobject glView)
{
const Array<AndroidGLContext*>& contexts = getContextList();
for (int i = contexts.size(); --i >= 0;)
{
AndroidGLContext* const c = contexts.getUnchecked(i);
if (env->IsSameObject (c->glView.get(), glView))
return c;
}
return nullptr;
}
static bool isAnyContextActive()
{
const Array<AndroidGLContext*>& contexts = getContextList();
for (int i = contexts.size(); --i >= 0;)
{
const AndroidGLContext* const c = contexts.getUnchecked(i);
if (c->isInsideGLCallback)
return true;
}
return false;
}
//==============================================================================
GlobalRef glView;
private:
WeakReference<Component> component;
int lastWidth, lastHeight;
bool isGLES2;
bool isInsideGLCallback;
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (AndroidGLContext);
};
//==============================================================================
OpenGLContext* OpenGLComponent::createContext()
{
ComponentPeer* peer = getTopLevelComponent()->getPeer();
if (peer != nullptr)
return new AndroidGLContext (this, peer, preferredPixelFormat,
dynamic_cast <const AndroidGLContext*> (contextToShareListsWith),
(flags & openGLES2) != 0);
return nullptr;
}
void* OpenGLComponent::getNativeWindowHandle() const
void OpenGLComponent::updateEmbeddedPosition (const Rectangle<int>& bounds)
{
return nullptr;
const ScopedLock sl (contextLock);
if (context != nullptr)
static_cast <AndroidGLContext*> (context.get())->updateWindowPosition (bounds);
}
bool OpenGLHelpers::isContextActive()
{
return AndroidGLContext::isAnyContextActive();
}
void OpenGLComponent::updateEmbeddedPosition (const Rectangle<int>&)
//==============================================================================
JUCE_JNI_CALLBACK (JUCE_JOIN_MACRO (JUCE_ANDROID_ACTIVITY_CLASSNAME, _00024OpenGLView), contextCreated, void, (JNIEnv* env, jobject view))
{
AndroidGLContext* const context = AndroidGLContext::findContextFor (env, view);
if (context != nullptr)
context->contextCreatedCallback();
}
bool OpenGLHelpers::isContextActive()
JUCE_JNI_CALLBACK (JUCE_JOIN_MACRO (JUCE_ANDROID_ACTIVITY_CLASSNAME, _00024OpenGLView), render, void, (JNIEnv* env, jobject view))
{
return false;
AndroidGLContext* const context = AndroidGLContext::findContextFor (env, view);
if (context != nullptr)
context->renderCallback();
}

+ 4
- 0
modules/juce_opengl/opengl/juce_OpenGLComponent.cpp View File

@@ -220,7 +220,11 @@ void OpenGLComponent::stopRenderThread()
//==============================================================================
OpenGLComponent::OpenGLComponent (const int flags_)
#if JUCE_ANDROID
: flags (flags_ & ~useBackgroundThread),
#else
: flags (flags_),
#endif
contextToShareListsWith (nullptr),
needToUpdateViewport (true),
needToDeleteContext (false),


+ 10
- 3
modules/juce_opengl/opengl/juce_OpenGLComponent.h View File

@@ -35,6 +35,9 @@
#endif
class OpenGLGraphicsContext;
#if JUCE_ANDROID
class AndroidGLContext;
#endif
//==============================================================================
/**
@@ -61,9 +64,9 @@ public:
*/
openGLDefault = 8,
#if JUCE_IOS
openGLES1 = 1, /**< On the iPhone, this selects openGL ES 1.0 */
openGLES2 = 2, /**< On the iPhone, this selects openGL ES 2.0 */
#if JUCE_IOS || JUCE_ANDROID
openGLES1 = 1, /**< This selects openGL ES 1.0 */
openGLES2 = 2, /**< This selects openGL ES 2.0 */
#endif
/** If this flag is enabled, the component will launch a background thread to
@@ -290,6 +293,10 @@ private:
int renderAndSwapBuffers(); // (This method has been deprecated)
#if JUCE_ANDROID
friend class AndroidGLContext;
#endif
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (OpenGLComponent);
};


Loading…
Cancel
Save