using System;
using System.ComponentModel;
using System.Runtime.InteropServices;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Diagnostics.CodeAnalysis;
namespace Tizen.NUI.BaseComponents
{
///
/// DirectRenderingGLView allows drawing with OpenGL. You can render to a Window directly.
/// DirectRenderingGLView creates a context.
///
/// 11
[EditorBrowsable(EditorBrowsableState.Never)]
public class DirectRenderingGLView : View
{
///
/// The parameter of the RenderFrame Callback.
/// It has data to render directly.
///
[SuppressMessage("Microsoft.Design", "CA1034:NestedTypesShouldNotBeVisible")]
public class RenderCallbackInput
{
Matrix mvp;
Matrix projection;
Size2D size;
Rectangle clippingBox;
ReadOnlyCollection textureBindings;
public RenderCallbackInput(Matrix mvp, Matrix projection, Size2D size, Rectangle clippingBox, int[] textureBindings)
{
this.mvp = mvp;
this.projection = projection;
this.size = size;
this.clippingBox = clippingBox;
this.textureBindings = new ReadOnlyCollection(textureBindings);
}
///
/// MVP matrix
///
public Matrix Mvp
{
get { return mvp; }
}
///
/// Projection matrix
///
public Matrix Projection
{
get { return projection; }
}
///
/// The size of the DirectRenderingGLView
///
public Size2D Size
{
get { return size; }
}
///
/// The area of DirectRenderingGLView. You can use this for glScissor()
///
public Rectangle ClippingBox
{
get { return clippingBox; }
}
///
/// Texture bindings
///
public ReadOnlyCollection TextureBindings
{
get { return textureBindings; }
}
}
private GLInitializeDelegate glInitializeCallback;
private GLRenderFrameDelegate glRenderFrameCallback;
private GLTerminateDelegate glTerminateCallback;
private InternalGLRenderFrameDelegate internalRenderFrameCallback;
///
/// Type of callback to initialize OpenGLES.
///
public delegate void GLInitializeDelegate();
///
/// Type of callback to render the frame with OpenGLES APIs.
/// If the return value of this callback is not 0, the eglSwapBuffers() will be called.
///
/// The return value is not 0, the eglSwapBuffers() will be called.
public delegate int GLRenderFrameDelegate(in RenderCallbackInput input);
private delegate int InternalGLRenderFrameDelegate(global::System.IntPtr cPtr);
///
/// Type of callback to clean up GL resource.
///
public delegate void GLTerminateDelegate();
internal DirectRenderingGLView(global::System.IntPtr cPtr, bool cMemoryOwn) : base(cPtr, cMemoryOwn)
{
}
///
/// Creates an initialized DirectRenderingGLView.
///
/// The format of the color buffer
public DirectRenderingGLView(ColorFormat colorFormat) : this(Interop.GLView.New(0, (int)colorFormat), true)
{
if (NDalicPINVOKE.SWIGPendingException.Pending) throw NDalicPINVOKE.SWIGPendingException.Retrieve();
}
///
/// Enumeration for the color format of the color buffer
///
public enum ColorFormat
{
///
/// 8 red bits, 8 green bits, 8 blue bits
///
RGB888 = 0,
///
/// 8 red bits, 8 green bits, 8 blue bits, alpha 8 bits
///
RGBA8888
}
///
/// Gets or sets the rendering mode of the DirectRenderingGLView.
///
public GLRenderingMode RenderingMode
{
[SuppressMessage("Microsoft.Design", "CA1065:DoNotRaiseExceptionsInUnexpectedLocations", Justification = "SWIG boilerplate, no exceptions are expected")]
get
{
GLRenderingMode ret = (GLRenderingMode)Interop.GLView.GlViewGetRenderingMode(SwigCPtr);
if (NDalicPINVOKE.SWIGPendingException.Pending) throw NDalicPINVOKE.SWIGPendingException.Retrieve();
return ret;
}
set
{
Interop.GLView.GlViewSetRenderingMode(SwigCPtr, (int)value);
if (NDalicPINVOKE.SWIGPendingException.Pending) throw NDalicPINVOKE.SWIGPendingException.Retrieve();
}
}
///
/// Registers GL callback functions to render with OpenGL ES
///
/// The callback function for GL initialization
/// The callback function to render the frame
/// The callback function to clean up GL resources
public void RegisterGLCallbacks(GLInitializeDelegate glInit, GLRenderFrameDelegate glRenderFrame, GLTerminateDelegate glTerminate)
{
glInitializeCallback = glInit;
HandleRef InitHandleRef = new HandleRef(this, Marshal.GetFunctionPointerForDelegate(glInitializeCallback));
glRenderFrameCallback = glRenderFrame;
internalRenderFrameCallback = OnRenderFrame;
HandleRef RenderHandlerRef = new HandleRef(this, Marshal.GetFunctionPointerForDelegate(internalRenderFrameCallback));
glTerminateCallback = glTerminate;
HandleRef TerminateHandlerRef = new HandleRef(this, Marshal.GetFunctionPointerForDelegate(glTerminateCallback));
Interop.GLView.GlViewRegisterGlCallbacks(SwigCPtr, InitHandleRef, RenderHandlerRef, TerminateHandlerRef);
if (NDalicPINVOKE.SWIGPendingException.Pending) throw NDalicPINVOKE.SWIGPendingException.Retrieve();
}
///
/// Binds textures to own context.
/// You can get the bind IDs in RenderCallbackInput in the glRenderFrame callback.
///
/// List of Textures
public void BindTextureResources(List textures)
{
unsafe
{
if (textures != null)
{
IntPtr unmanagedPointer = Marshal.AllocHGlobal(sizeof(IntPtr) * textures.Count);
IntPtr[] texturesArray = new IntPtr[textures.Count];
for (int i = 0; i < textures.Count; i++)
{
texturesArray[i] = HandleRef.ToIntPtr(Texture.getCPtr(textures[i]));
}
System.Runtime.InteropServices.Marshal.Copy(texturesArray, 0, unmanagedPointer, textures.Count);
Interop.GLView.GlViewBindTextureResources(SwigCPtr, unmanagedPointer, textures.Count);
Marshal.FreeHGlobal(unmanagedPointer);
}
}
}
///
/// Sets graphics configuration for the DirectRenderingGLView
///
/// The flag of depth buffer. When the value is true, 24bit depth buffer is enabled.
/// The flag of stencil. When the value is true, 8bit stencil buffer is enabled.
/// The bit of MSAA
/// The GLES version
/// True if the config was successfully set, false otherwise.
public bool SetGraphicsConfig(bool depth, bool stencil, int msaa, GLESVersion version)
{
bool ret = Interop.GLView.GlViewSetGraphicsConfig(SwigCPtr, depth, stencil, msaa, (int)version);
if (NDalicPINVOKE.SWIGPendingException.Pending) throw NDalicPINVOKE.SWIGPendingException.Retrieve();
return ret;
}
///
/// Renders once more, even when paused.
///
public void RenderOnce()
{
Interop.GLView.GlViewRenderOnce(SwigCPtr);
if (NDalicPINVOKE.SWIGPendingException.Pending) throw NDalicPINVOKE.SWIGPendingException.Retrieve();
}
private int OnRenderFrame(global::System.IntPtr cPtr)
{
if (glRenderFrameCallback != null)
{
Matrix mvp = Matrix.GetMatrixFromPtr(Interop.GLView.GlViewGetRednerCallbackInputMvp(cPtr));
Matrix projection = Matrix.GetMatrixFromPtr(Interop.GLView.GlViewGetRednerCallbackInputProjection(cPtr));
Size2D size = Size2D.GetSize2DFromPtr(Interop.GLView.GlViewGetRednerCallbackInputSize(cPtr));
Rectangle clippingBox = Rectangle.GetRectangleFromPtr(Interop.GLView.GlViewGetRednerCallbackInputClipplingBox(cPtr));
int[] textureBindings = GetTextureBindings(cPtr);
RenderCallbackInput input = new RenderCallbackInput(mvp, projection, size, clippingBox, textureBindings);
return glRenderFrameCallback(input);
}
return 0;
}
private static int[] GetTextureBindings(global::System.IntPtr cPtr)
{
int bindingSize = 0;
global::System.IntPtr arrayPtr = Interop.GLView.GlViewGetRednerCallbackInputTextureBindings(cPtr, ref bindingSize);
if (bindingSize != 0)
{
int[] result = new int[bindingSize];
System.Runtime.InteropServices.Marshal.Copy(arrayPtr, result, 0, bindingSize);
return result;
}
else
{
return Array.Empty();
}
}
}
}