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) 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 final class ViewHolder extends ViewGroup
@@ -246,6 +249,7 @@ public final class JuceDemo extends Activity
public ComponentPeerView (Context context, boolean opaque_) public ComponentPeerView (Context context, boolean opaque_)
{ {
super (context); super (context);
setWillNotDraw (false);
opaque = opaque_; opaque = opaque_;
setFocusable (true); setFocusable (true);
@@ -260,6 +264,7 @@ public final class JuceDemo extends Activity
@Override @Override
public void draw (Canvas canvas) public void draw (Canvas canvas)
{ {
super.draw (canvas);
handlePaint (canvas); handlePaint (canvas);
} }
@@ -295,11 +300,16 @@ public final class JuceDemo extends Activity
@Override @Override
protected void onSizeChanged (int w, int h, int oldw, int oldh) protected void onSizeChanged (int w, int h, int oldw, int oldh)
{ {
super.onSizeChanged (w, h, oldw, oldh);
viewSizeChanged(); viewSizeChanged();
} }
@Override @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(); private native void viewSizeChanged();
@@ -321,38 +331,59 @@ public final class JuceDemo extends Activity
{ {
return true; //xxx needs to check overlapping views 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); setEGLContextClientVersion (2);
getHolder().setFormat(PixelFormat.TRANSLUCENT);
setVisibility (VISIBLE);
setRenderer (this); setRenderer (this);
parent.addView (this);
//setRenderMode (RENDERMODE_CONTINUOUSLY);
//requestRender();
} }
@Override
public void onSurfaceCreated (GL10 unused, EGLConfig config) public void onSurfaceCreated (GL10 unused, EGLConfig config)
{ {
contextCreated();
// contextCreated();
} }
@Override
public void onDrawFrame (GL10 unused) 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) 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(); 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.os.Bundle;
import android.view.*; import android.view.*;
import android.graphics.*; import android.graphics.*;
import android.opengl.*;
import android.text.ClipboardManager; import android.text.ClipboardManager;
import java.io.BufferedInputStream; import java.io.BufferedInputStream;
import java.io.IOException; import java.io.IOException;
@@ -39,6 +40,8 @@ import java.io.InputStream;
import java.io.OutputStream; import java.io.OutputStream;
import java.net.URL; import java.net.URL;
import java.net.HttpURLConnection; import java.net.HttpURLConnection;
import javax.microedition.khronos.egl.EGLConfig;
import javax.microedition.khronos.opengles.GL10;
//============================================================================== //==============================================================================
public final class JuceAppActivity extends Activity 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) public static final void printToConsole (String s)
@@ -111,7 +114,10 @@ public final class JuceAppActivity extends Activity
public final void deleteView (ComponentPeerView view) 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 final class ViewHolder extends ViewGroup
@@ -237,12 +243,13 @@ public final class JuceAppActivity extends Activity
public native void alertDismissed (long callback, int id); 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_) public ComponentPeerView (Context context, boolean opaque_)
{ {
super (context); super (context);
setWillNotDraw (false);
opaque = opaque_; opaque = opaque_;
setFocusable (true); setFocusable (true);
@@ -257,6 +264,7 @@ public final class JuceAppActivity extends Activity
@Override @Override
public void draw (Canvas canvas) public void draw (Canvas canvas)
{ {
super.draw (canvas);
handlePaint (canvas); handlePaint (canvas);
} }
@@ -292,11 +300,16 @@ public final class JuceAppActivity extends Activity
@Override @Override
protected void onSizeChanged (int w, int h, int oldw, int oldh) protected void onSizeChanged (int w, int h, int oldw, int oldh)
{ {
super.onSizeChanged (w, h, oldw, oldh);
viewSizeChanged(); viewSizeChanged();
} }
@Override @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(); private native void viewSizeChanged();
@@ -318,6 +331,63 @@ public final class JuceAppActivity extends Activity
{ {
return true; //xxx needs to check overlapping views 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.setMatrix (matrix);
c.drawPath (p, paint); c.drawPath (p, paint);
int sizeNeeded = w * h;
final int sizeNeeded = w * h;
if (cachedRenderArray.length < sizeNeeded) if (cachedRenderArray.length < sizeNeeded)
cachedRenderArray = new int [sizeNeeded]; cachedRenderArray = new int [sizeNeeded];
@@ -393,25 +463,10 @@ public final class JuceAppActivity extends Activity
return num; 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 HttpURLConnection connection;
private InputStream inputStream; private InputStream inputStream;
@@ -419,7 +474,8 @@ public final class JuceAppActivity extends Activity
} }
public static final HTTPStream createHTTPStream (String address, boolean isPost, byte[] postData, 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 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) void JNIClassBase::initialiseAllClasses (JNIEnv* env)
{ {
Array<JNIClassBase*>& classes = getClasses();
const Array<JNIClassBase*>& classes = getClasses();
for (int i = classes.size(); --i >= 0;) for (int i = classes.size(); --i >= 0;)
classes.getUnchecked(i)->initialise (env); classes.getUnchecked(i)->initialise (env);
} }
void JNIClassBase::releaseAllClasses (JNIEnv* env) void JNIClassBase::releaseAllClasses (JNIEnv* env)
{ {
Array<JNIClassBase*>& classes = getClasses();
const Array<JNIClassBase*>& classes = getClasses();
for (int i = classes.size(); --i >= 0;) for (int i = classes.size(); --i >= 0;)
classes.getUnchecked(i)->release (env); 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. */ /** Returns the inverse of this point. */
Point operator-() const noexcept { return Point (-x, -y); } 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); } ValueType getDistanceFromOrigin() const noexcept { return juce_hypot (x, y); }
/** Returns the straight-line distance between this point and another one. */ /** 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 (hasFocus, "hasFocus", "()Z") \
METHOD (invalidate, "invalidate", "(IIII)V") \ METHOD (invalidate, "invalidate", "(IIII)V") \
METHOD (containsPoint, "containsPoint", "(II)Z") \ METHOD (containsPoint, "containsPoint", "(II)Z") \
METHOD (createGLView, "createGLView", "()L" JUCE_ANDROID_ACTIVITY_CLASSPATH "$OpenGLView;") \
DECLARE_JNI_CLASS (ComponentPeerView, JUCE_ANDROID_ACTIVITY_CLASSPATH "$ComponentPeerView"); DECLARE_JNI_CLASS (ComponentPeerView, JUCE_ANDROID_ACTIVITY_CLASSPATH "$ComponentPeerView");
#undef JNI_CLASS_MEMBERS #undef JNI_CLASS_MEMBERS
@@ -585,6 +586,11 @@ ComponentPeer* Component::createNewPeer (int styleFlags, void*)
return new AndroidComponentPeer (this, styleFlags); 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 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() 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; 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_) OpenGLComponent::OpenGLComponent (const int flags_)
#if JUCE_ANDROID
: flags (flags_ & ~useBackgroundThread),
#else
: flags (flags_), : flags (flags_),
#endif
contextToShareListsWith (nullptr), contextToShareListsWith (nullptr),
needToUpdateViewport (true), needToUpdateViewport (true),
needToDeleteContext (false), needToDeleteContext (false),


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

@@ -35,6 +35,9 @@
#endif #endif
class OpenGLGraphicsContext; class OpenGLGraphicsContext;
#if JUCE_ANDROID
class AndroidGLContext;
#endif
//============================================================================== //==============================================================================
/** /**
@@ -61,9 +64,9 @@ public:
*/ */
openGLDefault = 8, 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 #endif
/** If this flag is enabled, the component will launch a background thread to /** 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) int renderAndSwapBuffers(); // (This method has been deprecated)
#if JUCE_ANDROID
friend class AndroidGLContext;
#endif
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (OpenGLComponent); JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (OpenGLComponent);
}; };


Loading…
Cancel
Save