[OpenTK] Introduce OpenTK (#336)
[platform/core/csapi/tizenfx.git] / external / src / OpenTK / OpenTK / BindingsBase.cs
1 //
2 // The Open Toolkit Library License
3 //
4 // Copyright (c) 2006 - 2009 the Open Toolkit library.
5 //
6 // Permission is hereby granted, free of charge, to any person obtaining a copy
7 // of this software and associated documentation files (the "Software"), to deal
8 // in the Software without restriction, including without limitation the rights to
9 // use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
10 // the Software, and to permit persons to whom the Software is furnished to do
11 // so, subject to the following conditions:
12 //
13 // The above copyright notice and this permission notice shall be included in all
14 // copies or substantial portions of the Software.
15 //
16 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
18 // OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
20 // HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
21 // WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
22 // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
23 // OTHER DEALINGS IN THE SOFTWARE.
24 //
25
26 using System;
27 using System.Text;
28 using System.Runtime.InteropServices;
29
30 namespace OpenTK
31 {
32     /// <summary>
33     /// Provides a common foundation for all flat API bindings and implements the extension loading interface.
34     /// </summary>
35     public abstract class BindingsBase
36     {
37         /// <summary>
38         /// Constructs a new BindingsBase instance.
39         /// </summary>
40         public BindingsBase()
41         {
42         }
43
44         /// <summary>
45         /// Gets or sets a <see cref="System.Boolean"/> that indicates whether the list of supported extensions may have changed.
46         /// </summary>
47         protected bool RebuildExtensionList { get; set; } = true;
48
49         /// <summary>
50         /// Retrieves an unmanaged function pointer to the specified function.
51         /// </summary>
52         /// <param name="funcname">
53         /// A <see cref="System.String"/> that defines the name of the function.
54         /// </param>
55         /// <returns>
56         /// A <see cref="IntPtr"/> that contains the address of funcname or IntPtr.Zero,
57         /// if the function is not supported by the drivers.
58         /// </returns>
59         /// <remarks>
60         /// Note: some drivers are known to return non-zero values for unsupported functions.
61         /// Typical values include 1 and 2 - inheritors are advised to check for and ignore these
62         /// values.
63         /// </remarks>
64         protected abstract IntPtr GetAddress(string funcname);
65
66         /// <summary>
67         /// Gets an object that can be used to synchronize access to the bindings implementation.
68         /// </summary>
69         /// <remarks>This object should be unique across bindings but consistent between bindings
70         /// of the same type. For example, ES10.GL, OpenGL.GL and CL10.CL should all return
71         /// unique objects, but all instances of ES10.GL should return the same object.</remarks>
72         protected abstract object SyncRoot { get; }
73
74         /// <summary>
75         /// Marshals a pointer to a null-terminated byte array to a new <c>System.String</c>.
76         /// This method supports OpenTK and is not intended to be called by user code.
77         /// </summary>
78         /// <param name="ptr">A pointer to a null-terminated byte array.</param>
79         /// <returns>
80         /// A <c>System.String</c> with the data from <paramref name="ptr"/>.
81         /// </returns>
82         protected static string MarshalPtrToString(IntPtr ptr)
83         {
84             if (ptr == IntPtr.Zero)
85             {
86                 throw new ArgumentException("ptr");
87             }
88
89             unsafe
90             {
91                 sbyte* str = (sbyte*)ptr;
92                 int len = 0;
93                 while (*str != 0)
94                 {
95                     ++len;
96                     ++str;
97                 }
98
99                 return new string((sbyte*)ptr, 0, len, Encoding.UTF8);
100             }
101         }
102
103         /// <summary>
104         /// Marshal a <c>System.String</c> to unmanaged memory.
105         /// The resulting string is encoded in UTF8 and must be freed
106         /// with <c>FreeStringPtr</c>.
107         /// </summary>
108         /// <param name="str">The <c>System.String</c> to marshal.</param>
109         /// <returns>
110         /// An unmanaged pointer containing the marshalled string.
111         /// This pointer must be freed with <c>FreeStringPtr</c>
112         /// </returns>
113         protected static IntPtr MarshalStringToPtr(string str)
114         {
115             if (String.IsNullOrEmpty(str))
116             {
117                 return IntPtr.Zero;
118             }
119
120             // Allocate a buffer big enough to hold the marshalled string.
121             // GetMaxByteCount() appears to allocate space for the final NUL
122             // character, but allocate an extra one just in case (who knows
123             // what old Mono version would do here.)
124             int max_count = Encoding.UTF8.GetMaxByteCount(str.Length) + 1;
125             IntPtr ptr = Marshal.AllocHGlobal(max_count);
126             if (ptr == IntPtr.Zero)
127             {
128                 throw new OutOfMemoryException();
129             }
130
131             // Pin the managed string and convert it to UTF8 using
132             // the pointer overload of System.Encoding.UTF8.GetBytes().
133             unsafe
134             {
135                 fixed (char* pstr = str)
136                 {
137                     int actual_count = Encoding.UTF8.GetBytes(pstr, str.Length, (byte*)ptr, max_count);
138                     Marshal.WriteByte(ptr, actual_count, 0); // Append '\0' at the end of the string
139                     return ptr;
140                 }
141             }
142         }
143
144         /// <summary>
145         /// Frees a marshalled string that allocated by <c>MarshalStringToPtr</c>.
146         /// </summary>
147         /// <param name="ptr">An unmanaged pointer allocated with <c>MarshalStringToPtr</c></param>
148         protected static void FreeStringPtr(IntPtr ptr)
149         {
150             Marshal.FreeHGlobal(ptr);
151         }
152
153         /// <summary>
154         /// Marshals a <c>System.String</c> array to unmanaged memory by calling
155         /// Marshal.AllocHGlobal for each element.
156         /// </summary>
157         /// <returns>An unmanaged pointer to an array of null-terminated strings</returns>
158         /// <param name="str_array">The string array to marshal.</param>
159         protected static IntPtr MarshalStringArrayToPtr(string[] str_array)
160         {
161             IntPtr ptr = IntPtr.Zero;
162             if (str_array != null && str_array.Length != 0)
163             {
164                 ptr = Marshal.AllocHGlobal(str_array.Length * IntPtr.Size);
165                 if (ptr == IntPtr.Zero)
166                 {
167                     throw new OutOfMemoryException();
168                 }
169
170                 int i = 0;
171                 try
172                 {
173                     for (i = 0; i < str_array.Length; i++)
174                     {
175                         IntPtr str = MarshalStringToPtr(str_array[i]);
176                         Marshal.WriteIntPtr(ptr, i * IntPtr.Size, str);
177                     }
178                 }
179                 catch (OutOfMemoryException)
180                 {
181                     for (i = i - 1; i >= 0; --i)
182                     {
183                         Marshal.FreeHGlobal(Marshal.ReadIntPtr(ptr, i * IntPtr.Size));
184                     }
185
186                     Marshal.FreeHGlobal(ptr);
187
188                     throw;
189                 }
190             }
191             return ptr;
192         }
193
194         /// <summary>
195         /// Frees a marshalled string that allocated by <c>MarshalStringArrayToPtr</c>.
196         /// </summary>
197         /// <param name="ptr">An unmanaged pointer allocated with <c>MarshalStringArrayToPtr</c></param>
198         /// <param name="length">The length of the string array.</param>
199         protected static void FreeStringArrayPtr(IntPtr ptr, int length)
200         {
201             for (int i = 0; i < length; i++)
202             {
203                 Marshal.FreeHGlobal(Marshal.ReadIntPtr(ptr, i * IntPtr.Size));
204             }
205             Marshal.FreeHGlobal(ptr);
206         }
207
208         internal abstract void LoadEntryPoints();
209     }
210 }