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(); } } } }