Opentk/Source/OpenTK/Platform/Android/AndroidGraphicsContext.cs
2016-06-08 15:15:59 +09:00

164 lines
4.4 KiB
C#

#region --- License ---
/* Licensed under the MIT/X11 license.
* Copyright (c) 2011 Xamarin, Inc.
* Copyright 2013 Xamarin Inc
* This notice may not be removed from any source distribution.
* See license.txt for licensing detailed licensing details.
*/
#endregion
using System;
using System.Runtime.InteropServices;
using Android.Util;
using Android.Views;
using Android.Runtime;
using Javax.Microedition.Khronos.Egl;
using OpenTK.Graphics;
using OpenTK.Platform.Egl;
namespace OpenTK.Platform.Android {
class AndroidGraphicsContext : EglContext
{
public AndroidGraphicsContext(GraphicsMode mode, EglWindowInfo window, IGraphicsContext sharedContext,
int major, int minor, GraphicsContextFlags flags)
: base(mode, window, sharedContext, major, minor, flags)
{
}
public AndroidGraphicsContext(ContextHandle handle, EglWindowInfo window, IGraphicsContext sharedContext,
int major, int minor, GraphicsContextFlags flags)
: base(handle, window, sharedContext, major, minor, flags)
{
}
protected override IntPtr GetStaticAddress(IntPtr function, RenderableFlags renderable)
{
return IntPtr.Zero;
}
}
public class AndroidWindow : IWindowInfo, IDisposable
{
bool disposed;
WeakReference refHolder;
private EglWindowInfo eglWindowInfo;
// Get native window from surface
[DllImport("android")]
private static extern IntPtr ANativeWindow_fromSurface(IntPtr jni, IntPtr surface);
// Get native window from surface
[DllImport("android")]
private static extern void ANativeWindow_release(IntPtr surface);
public IntPtr Handle { get { return eglWindowInfo != null ? eglWindowInfo.Handle : IntPtr.Zero; } }
public bool HasSurface
{
get { return eglWindowInfo.Surface != IntPtr.Zero; }
}
public ISurfaceHolder Holder {
get {
return refHolder.Target as ISurfaceHolder;
}
}
public AndroidWindow (ISurfaceHolder holder)
{
refHolder = new WeakReference (holder);
}
internal EglWindowInfo CreateEglWindowInfo()
{
UpdateEglWindowInfo();
return eglWindowInfo;
}
public void CreateSurface(IntPtr config)
{
UpdateEglWindowInfo();
if (refHolder.Target == null) {
eglWindowInfo.CreatePbufferSurface(config);
return;
}
eglWindowInfo.CreateWindowSurface(config);
}
private void UpdateEglWindowInfo()
{
if (eglWindowInfo == null)
eglWindowInfo = new EglWindowInfo(IntPtr.Zero, IntPtr.Zero);
var newHandle = IntPtr.Zero;
var holder = Holder;
if (holder != null && holder.Surface != null)
{
newHandle = ANativeWindow_fromSurface(JNIEnv.Handle, holder.Surface.Handle);
}
// Do we need to recreate eglWindowInfo?
if (eglWindowInfo != null && eglWindowInfo.Handle == newHandle)
{
// Same, we can release this reference
if (newHandle != IntPtr.Zero)
ANativeWindow_release(newHandle);
}
else
{
DestroySurface();
eglWindowInfo.Handle = newHandle;
}
}
public void DestroySurface ()
{
eglWindowInfo.DestroySurface();
// Release window handle
if (eglWindowInfo.Handle != IntPtr.Zero)
{
ANativeWindow_release(eglWindowInfo.Handle);
eglWindowInfo.Handle = IntPtr.Zero;
}
}
public void TerminateDisplay ()
{
eglWindowInfo.TerminateDisplay();
}
#region IDisposable Members
public void Dispose ()
{
Dispose (true);
GC.SuppressFinalize (this);
}
void Dispose (bool disposing)
{
if (!disposed)
{
if (disposing) {
DestroySurface ();
TerminateDisplay ();
refHolder = null;
disposed = true;
}
}
}
~AndroidWindow ()
{
Dispose (false);
}
#endregion
}
}