protected override void LoadFromSource()
{
Gl.glBindProgramARB( programType, programId );
// MONO: Cannot compile programs when passing in the string as is for whatever reason.
// would get "Invalid vertex program header", which I assume means the source got mangled along the way
byte[] bytes = Encoding.ASCII.GetBytes( Source );
// TODO: We pin the managed 'bytes' to get a pointer to data and get sure they won't move around in memory.
// In case glProgramStringARB() doesn't store the pointer internally, we better free the handle yet in this method,
// or rather utilize a fixed (byte* sourcePtr = bytes) statement, which cares for unpinning the data even in case
// of an exception, where GCHandle.Free() would be missed without try-finally.
// In case the above isn't possible, the theory also says that if we have a handle to managed data (except Weak, WeakTrackResurrection handle types)
// we should be implementing a finalizer to ensure freeing the handle as that can be treated as an unmanaged resource from this point of view.
// I decided not to extend this class with IDisposable for several reasons, including class's user contract,
// and the fact that this might be a temporary issue only. So for now only a finalizer will take care for avoiding memory leaks (although minor ones in this case).
// So recheck the MONO issue later, the above comment talks about passing the string directly, btw. the method seems to take byte[] as well (if that would work eventually...).
if ( _handle.IsAllocated )
{
_handle.Free();
}
_handle = GCHandle.Alloc( bytes, GCHandleType.Pinned );
IntPtr sourcePtr = _handle.AddrOfPinnedObject();
Gl.glProgramStringARB( programType, Gl.GL_PROGRAM_FORMAT_ASCII_ARB, Source.Length, sourcePtr );
// check for any errors
if ( Gl.glGetError() == Gl.GL_INVALID_OPERATION )
{
int pos;
string error;
Gl.glGetIntegerv( Gl.GL_PROGRAM_ERROR_POSITION_ARB, out pos );
error = Gl.glGetString( Gl.GL_PROGRAM_ERROR_STRING_ARB ); // TAO 2.0
//error = Marshal.PtrToStringAnsi( Gl.glGetString( Gl.GL_PROGRAM_ERROR_STRING_ARB ) );
throw new Exception( string.Format( "Error on line {0} in program '{1}'\nError: {2}", pos, Name, error ) );
}
}