| 
							- /*
 -   ==============================================================================
 - 
 -    This file is part of the JUCE library.
 -    Copyright (c) 2017 - ROLI Ltd.
 - 
 -    JUCE is an open source library subject to commercial or open-source
 -    licensing.
 - 
 -    By using JUCE, you agree to the terms of both the JUCE 5 End-User License
 -    Agreement and JUCE 5 Privacy Policy (both updated and effective as of the
 -    27th April 2017).
 - 
 -    End User License Agreement: www.juce.com/juce-5-licence
 -    Privacy Policy: www.juce.com/juce-5-privacy-policy
 - 
 -    Or: You may also use this code under the terms of the GPL v3 (see
 -    www.gnu.org/licenses).
 - 
 -    JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER
 -    EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE
 -    DISCLAIMED.
 - 
 -   ==============================================================================
 - */
 - 
 - namespace juce
 - {
 - 
 - #define JNI_CLASS_MEMBERS(METHOD, STATICMETHOD, FIELD, STATICFIELD) \
 -  METHOD (getParent, "getParent", "()Landroid/view/ViewParent;") \
 -  METHOD (layout, "layout", "(IIII)V" ) \
 -  METHOD (getNativeSurface,     "getNativeSurface",        "()Landroid/view/Surface;") \
 - 
 - DECLARE_JNI_CLASS (NativeSurfaceView, JUCE_ANDROID_ACTIVITY_CLASSPATH "$NativeSurfaceView")
 - #undef JNI_CLASS_MEMBERS
 - 
 - //==============================================================================
 - class OpenGLContext::NativeContext
 - {
 - public:
 -     NativeContext (Component& comp,
 -                    const OpenGLPixelFormat& /*pixelFormat*/,
 -                    void* /*contextToShareWith*/,
 -                    bool /*useMultisampling*/,
 -                    OpenGLVersion)
 -         : component (comp),
 -           hasInitialised (false),
 -           juceContext (nullptr), surface (EGL_NO_SURFACE), context (EGL_NO_CONTEXT)
 -     {
 -         JNIEnv* env = getEnv();
 - 
 -         // Do we have a native peer that we can attach to?
 -         if (component.getPeer()->getNativeHandle() == nullptr)
 -             return;
 - 
 -         // Initialise the EGL display
 -         if (! initEGLDisplay())
 -             return;
 - 
 -         // create a native surface view
 -         surfaceView = GlobalRef (env->CallObjectMethod (android.activity.get(),
 -                                                         JuceAppActivity.createNativeSurfaceView,
 -                                                         reinterpret_cast<jlong> (this)));
 -         if (surfaceView.get() == nullptr)
 -             return;
 - 
 -         // add the view to the view hierarchy
 -         // after this the nativecontext can receive callbacks
 -         env->CallVoidMethod ((jobject) component.getPeer()->getNativeHandle(),
 -                              AndroidViewGroup.addView, surfaceView.get());
 - 
 -         // initialise the geometry of the view
 -         Rectangle<int> bounds = component.getTopLevelComponent()
 -             ->getLocalArea (&component, component.getLocalBounds());
 -         bounds *= component.getDesktopScaleFactor();
 - 
 -         updateWindowPosition (bounds);
 -         hasInitialised = true;
 -     }
 - 
 -     ~NativeContext()
 -     {
 -         JNIEnv* env = getEnv();
 - 
 -         if (jobject viewParent = env->CallObjectMethod (surfaceView.get(), NativeSurfaceView.getParent))
 -             env->CallVoidMethod (viewParent, AndroidViewGroup.removeView, surfaceView.get());
 -     }
 - 
 -     //==============================================================================
 -     bool initialiseOnRenderThread (OpenGLContext& aContext)
 -     {
 -         jassert (hasInitialised);
 - 
 -         // has the context already attached?
 -         jassert (surface == EGL_NO_SURFACE && context == EGL_NO_CONTEXT);
 - 
 -         JNIEnv* env = getEnv();
 - 
 -         // get a pointer to the native window
 -         ANativeWindow* window = nullptr;
 -         if (jobject jSurface = env->CallObjectMethod (surfaceView.get(), NativeSurfaceView.getNativeSurface))
 -         {
 -             window = ANativeWindow_fromSurface(env, jSurface);
 - 
 -             // if we didn't succeed the first time, wait 25ms and try again
 -             if (window == nullptr)
 -             {
 -                 Thread::sleep (25);
 -                 window = ANativeWindow_fromSurface (env, jSurface);
 -             }
 -         }
 - 
 -         if (window == nullptr)
 -         {
 -             // failed to get a pointer to the native window after second try so
 -             // bail out
 -             jassertfalse;
 - 
 -             return false;
 -         }
 - 
 -         // create the surface
 -         surface = eglCreateWindowSurface(display, config, window, 0);
 -         jassert (surface != EGL_NO_SURFACE);
 - 
 -         ANativeWindow_release (window);
 - 
 -         // create the OpenGL context
 -         EGLint contextAttribs[] = { EGL_CONTEXT_CLIENT_VERSION, 2, EGL_NONE};
 -         context = eglCreateContext(display, config, EGL_NO_CONTEXT, contextAttribs);
 -         jassert (context != EGL_NO_CONTEXT);
 - 
 -         juceContext = &aContext;
 - 
 -         return true;
 -     }
 - 
 -     void shutdownOnRenderThread()
 -     {
 -         jassert (hasInitialised);
 - 
 -         // is there a context available to detach?
 -         jassert (surface != EGL_NO_SURFACE && context != EGL_NO_CONTEXT);
 - 
 -         eglDestroyContext (display, context);
 -         context = EGL_NO_CONTEXT;
 - 
 -         eglDestroySurface (display, surface);
 -         surface = EGL_NO_SURFACE;
 -     }
 - 
 -     //==============================================================================
 -     bool makeActive() const noexcept
 -     {
 -         if (! hasInitialised)
 -             return false;
 - 
 -         if (surface == EGL_NO_SURFACE || context == EGL_NO_CONTEXT)
 -             return false;
 - 
 -         if (! eglMakeCurrent (display, surface, surface, context))
 -             return false;
 - 
 -         return true;
 -     }
 - 
 -     bool isActive() const noexcept              { return eglGetCurrentContext() == context; }
 - 
 -     static void deactivateCurrentContext()
 -     {
 -         eglMakeCurrent (display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
 -     }
 - 
 -     //==============================================================================
 -     void swapBuffers() const noexcept           { eglSwapBuffers (display, surface); }
 -     bool setSwapInterval (const int)            { return false; }
 -     int getSwapInterval() const                 { return 0; }
 - 
 -     //==============================================================================
 -     bool createdOk() const noexcept             { return hasInitialised; }
 -     void* getRawContext() const noexcept        { return surfaceView.get(); }
 -     GLuint getFrameBufferID() const noexcept    { return 0; }
 - 
 -     //==============================================================================
 -     void updateWindowPosition (Rectangle<int> bounds)
 -     {
 -         if (lastBounds != bounds)
 -         {
 -             JNIEnv* env = getEnv();
 - 
 -             lastBounds = bounds;
 -             Rectangle<int> r = bounds * Desktop::getInstance().getDisplays().getMainDisplay().scale;
 - 
 -             env->CallVoidMethod (surfaceView.get(), NativeSurfaceView.layout,
 -                                  (jint) r.getX(), (jint) r.getY(), (jint) r.getRight(), (jint) r.getBottom());
 -         }
 -     }
 - 
 -     //==============================================================================
 -     // Android Surface Callbacks:
 - 
 -     void dispatchDraw (jobject canvas)
 -     {
 -         ignoreUnused (canvas);
 - 
 -         if (juceContext != nullptr)
 -             juceContext->triggerRepaint();
 -     }
 - 
 -     void surfaceChanged (jobject holder, int format, int width, int height)
 -     {
 -         ignoreUnused (holder, format, width, height);
 -     }
 - 
 -     void surfaceCreated (jobject holder);
 -     void surfaceDestroyed (jobject holder);
 - 
 -     //==============================================================================
 -     struct Locker { Locker (NativeContext&) {} };
 - 
 -     Component& component;
 - 
 - private:
 -     //==============================================================================
 -     bool initEGLDisplay()
 -     {
 -         // already initialised?
 -         if (display != EGL_NO_DISPLAY)
 -             return true;
 - 
 -         const EGLint attribs[] =
 -         {
 -             EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT,
 -             EGL_SURFACE_TYPE, EGL_WINDOW_BIT,
 -             EGL_BLUE_SIZE, 8,
 -             EGL_GREEN_SIZE, 8,
 -             EGL_RED_SIZE, 8,
 -             EGL_ALPHA_SIZE, 0,
 -             EGL_DEPTH_SIZE, 16,
 -             EGL_NONE
 -         };
 - 
 -         EGLint numConfigs;
 - 
 -         if ((display = eglGetDisplay (EGL_DEFAULT_DISPLAY)) == EGL_NO_DISPLAY)
 -         {
 -             jassertfalse;
 -             return false;
 -         }
 - 
 -         if (! eglInitialize (display, 0, 0))
 -         {
 -             jassertfalse;
 -             return false;
 -         }
 - 
 -         if (! eglChooseConfig (display, attribs, &config, 1, &numConfigs))
 -         {
 -             eglTerminate (display);
 -             jassertfalse;
 -             return false;
 -         }
 - 
 -         return true;
 -     }
 - 
 -     //==============================================================================
 -     bool hasInitialised;
 - 
 -     GlobalRef surfaceView;
 -     Rectangle<int> lastBounds;
 - 
 -     OpenGLContext* juceContext;
 -     EGLSurface surface;
 -     EGLContext context;
 - 
 -     static EGLDisplay display;
 -     static EGLConfig config;
 - 
 -     JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (NativeContext)
 - };
 - 
 - //==============================================================================
 - JUCE_JNI_CALLBACK (JUCE_JOIN_MACRO (JUCE_ANDROID_ACTIVITY_CLASSNAME, _00024NativeSurfaceView), dispatchDrawNative,
 -                    void, (JNIEnv* env, jobject nativeView, jlong host, jobject canvas))
 - {
 -     ignoreUnused (nativeView);
 -     setEnv (env);
 -     reinterpret_cast<OpenGLContext::NativeContext*> (host)->dispatchDraw (canvas);
 - }
 - 
 - JUCE_JNI_CALLBACK (JUCE_JOIN_MACRO (JUCE_ANDROID_ACTIVITY_CLASSNAME, _00024NativeSurfaceView), surfaceChangedNative,
 -                    void, (JNIEnv* env, jobject nativeView, jlong host, jobject holder, jint format, jint width, jint height))
 - {
 -     ignoreUnused (nativeView);
 -     setEnv (env);
 -     reinterpret_cast<OpenGLContext::NativeContext*> (host)->surfaceChanged (holder, format, width, height);
 - }
 - 
 - JUCE_JNI_CALLBACK (JUCE_JOIN_MACRO (JUCE_ANDROID_ACTIVITY_CLASSNAME, _00024NativeSurfaceView), surfaceCreatedNative,
 -                    void, (JNIEnv* env, jobject nativeView, jlong host, jobject holder))
 - {
 -     ignoreUnused (nativeView);
 -     setEnv (env);
 -     reinterpret_cast<OpenGLContext::NativeContext*> (host)->surfaceCreated (holder);
 - }
 - 
 - JUCE_JNI_CALLBACK (JUCE_JOIN_MACRO (JUCE_ANDROID_ACTIVITY_CLASSNAME, _00024NativeSurfaceView), surfaceDestroyedNative,
 -                    void, (JNIEnv* env, jobject nativeView, jlong host, jobject holder))
 - {
 -     ignoreUnused (nativeView);
 -     setEnv (env);
 -     reinterpret_cast<OpenGLContext::NativeContext*> (host)->surfaceDestroyed (holder);
 - }
 - 
 - //==============================================================================
 - bool OpenGLHelpers::isContextActive()
 - {
 -     return eglGetCurrentContext() != EGL_NO_CONTEXT;
 - }
 - 
 - } // namespace juce
 
 
  |