public static bool IsPrimitiveRestartSupported(GraphicsContext ctx)
		{
			if (ctx == null)
				throw new ArgumentNullException("ctx");

			return (ctx.Caps.GlExtensions.PrimitiveRestart || ctx.Caps.GlExtensions.PrimitiveRestart_NV);
		}
		/// <summary>
		/// Draw the attributes of this vertex array.
		/// </summary>
		/// <param name="ctx">
		/// The <see cref="GraphicsContext"/> used for rendering.
		/// </param>
		/// <param name="shader">
		/// The <see cref="ShaderProgram"/> used for drawing the vertex arrays.
		/// </param>
		public virtual void Draw(GraphicsContext ctx, ShaderProgram shader)
		{
			CheckThisExistence(ctx);

			if (shader != null && shader.Exists(ctx) == false)
				throw new ArgumentException("not existing", "shader");

			// If vertex was modified after creation, don't miss to create array buffers
			if (_VertexArrayDirty) CreateObject(ctx);

			// Set vertex arrays
			SetVertexArrayState(ctx, shader);
			
			// Fixed or programmable pipeline?
			if     ((shader == null) && (ctx.Caps.GlExtensions.VertexShader_ARB == true))
				ShaderProgram.Unbind(ctx);
			else if (shader != null)
				shader.Bind(ctx);

			// Issue rendering using shader
			foreach (Element attributeElement in DrawElements) {
				if (_FeedbackBuffer != null)
					_FeedbackBuffer.Begin(ctx, attributeElement.ElementsMode);

				attributeElement.Draw(ctx);
				
				if (_FeedbackBuffer != null)
					_FeedbackBuffer.End(ctx);
			}
		}
Example #3
0
		/// <summary>
		/// Upload Texture1D data from an Image instance, allocating it immediately using a GraphicsContext.
		/// </summary>
		/// <param name="ctx">
		/// A <see cref="GraphicsContext"/> used for uploading texture data.
		/// </param>
		/// <param name="image">
		/// An <see cref="Image"/> holding the texture data.
		/// </param>
		/// <remarks>
		/// 
		/// </remarks>
		public void Set(GraphicsContext ctx, Image image)
		{
			if (ctx == null)
				throw new ArgumentNullException("ctx");
			if (ctx.IsCurrent == false)
				throw new ArgumentException("ctx.IsCurrent() == false");
			if (image == null)
				throw new ArgumentNullException("image");
			if ((image.Width == 0) || (image.Height == 0))
				throw new ArgumentException("image.Width == 0 || image.Height == 0");
			if (image.Height != 1)
				throw new ArgumentException("image.Height != 1");

			// Reference pixel data
			mTextureData = image;
			// Derive texture pixel format from 'image' if it is not defined yet
			if (PixelLayout != PixelLayout.None) {
				// Check whether texture pixel format is compatible with the image pixel format
				if (Pixel.IsSupportedSetDataFormat(image.PixelLayout, PixelLayout, ctx) == false)
					throw new InvalidOperationException(String.Format("textel format {0} incompatible with data pixel format {1}", image.PixelLayout, PixelLayout));
			} else {
				// Check whether texture pixel format is compatible with the image pixel format
				if (Pixel.IsSupportedDataFormat(image.PixelLayout, ctx) == false)
					throw new InvalidOperationException(String.Format("not supported data pixel format {1}", image.PixelLayout));
				PixelLayout = image.PixelLayout;
			}
			// Texture extents
			mWidth  = image.Width;

			// Upload texture data
			Set(ctx);
		}
Example #4
0
		/// <summary>
		/// Upload Texture1D data.
		/// </summary>
		/// <param name="ctx">
		/// A <see cref="GraphicsContext"/> used for uploading texture data.
		/// </param>
		private void Set(GraphicsContext ctx)
		{
			// Create texture if necessary
			Create(ctx);

			// Bind this Texture
			Bind(ctx);
			// Upload texture data
			int internalFormat = Pixel.GetGlInternalFormat(PixelLayout, ctx);
			PixelFormat format = Pixel.GetGlFormat(mTextureData.PixelLayout);
			PixelType type = Pixel.GetPixelType(mTextureData.PixelLayout);

			// Set pixel transfer
			foreach (int alignment in new int[] { 8, 4, 2, 1 }) {
				if (mTextureData.Stride % alignment == 0) {
					Gl.PixelStore(PixelStoreParameter.UnpackAlignment, alignment);
					break;
				}
			}

			// Upload texture contents
			Gl.TexImage1D(TextureTarget.Texture1d, 0, internalFormat, (int)Width, 0, format, type, mTextureData.ImageBuffer);
			// Unbind this texture
			Unbind(ctx);

			// Data no more required
			mTextureData = null;
		}
		/// <summary>
		/// Set uniform state variable (any known object type).
		/// </summary>
		/// <param name="ctx">
		/// A <see cref="GraphicsContext"/> used for operations.
		/// </param>
		/// <param name="uniformName">
		/// A <see cref="String"/> that specify the variable name in the shader source.
		/// </param>
		/// <param name="value">
		/// A <see cref="Object"/> holding the uniform variabile data.
		/// </param>
		/// <remarks>
		/// </remarks>
		/// <exception cref="ArgumentNullException">
		/// This exception is thrown if the parameter <paramref name="ctx"/> is null.
		/// </exception>
		/// <exception cref="ArgumentNullException">
		/// This exception is thrown if the parameter <paramref name="uniformName"/> is null.
		/// </exception>
		public void SetUniform(GraphicsContext ctx, string uniformName, object value)
		{
			if (ctx == null)
				throw new ArgumentNullException("ctx");
			if (value == null)
				throw new ArgumentNullException("value");

			MethodInfo setUniformMethod;

			if (_SetUniformMethods.TryGetValue(value.GetType(), out setUniformMethod) == false) {
				setUniformMethod = typeof(ShaderProgram).GetMethod("SetUniform", new Type[] { typeof(GraphicsContext), typeof(string), value.GetType() });
				_SetUniformMethods[value.GetType()] = setUniformMethod;
			}

			if (setUniformMethod != null) {
				// Avoid stack overflow
				if (setUniformMethod.GetParameters()[2].ParameterType == typeof(object))
					throw new NotSupportedException(value.GetType() + " is not supported");

				try {
					setUniformMethod.Invoke(this, new object[] { ctx, uniformName, value });
				} catch (TargetInvocationException targetInvocationException) {
					throw targetInvocationException.InnerException;
				}
			} else
				throw new NotSupportedException(value.GetType() + " is not supported");
		}
		/// <summary>
		/// Check whether one of the extention strings is supported.
		/// </summary>
		/// <param name="ctx">
		/// A <see cref="GraphicsContext"/> that specifies the current OpenGL version to test for extension support. In the case this
		/// parameter is null, the test fallback to the current OpenGL version.
		/// </param>
		public bool IsSupported(GraphicsContext ctx, IDeviceContext deviceContext)
		{
			if (IsSupportedExtension(ctx, deviceContext, mExtensionString) == true)
				return (true);
			if (mExtensionAlternatives != null) {
				foreach (string ext in mExtensionAlternatives)
					if (IsSupportedExtension(ctx, deviceContext, ext) == true)
						return (true);
			}

			return (false);
		}
		public static void DisablePrimitiveRestart(GraphicsContext ctx)
		{
			if (ctx == null)
				throw new ArgumentNullException("ctx");
			
			if (ctx.Caps.GlExtensions.PrimitiveRestart) {
				// Enable primitive restart (server state)
				Gl.Disable(EnableCap.PrimitiveRestart);
			} else if (ctx.Caps.GlExtensions.PrimitiveRestart_NV) {
				// Enable primitive restart (client state)
				Gl.DisableClientState(EnableCap.PrimitiveRestartNv);
			} else
				throw new InvalidOperationException("primitive restart not supported");
		}
		public static void EnablePrimitiveRestart(GraphicsContext ctx, DrawElementsType elementType)
		{
			switch (elementType) {
				case DrawElementsType.UnsignedInt:
					EnablePrimitiveRestart(ctx, UInt32.MaxValue);
					break;
				case DrawElementsType.UnsignedShort:
					EnablePrimitiveRestart(ctx, UInt16.MaxValue);
					break;
				case DrawElementsType.UnsignedByte:
					EnablePrimitiveRestart(ctx, Byte.MaxValue);
					break;
				default:
					throw new ArgumentException(String.Format("unknown element type {0}", elementType));
			}
		}
		/// <summary>
		/// Query OpenGL implementation extensions.
		/// </summary>
		/// <param name="ctx"></param>
		/// <returns></returns>
		public static GraphicsCapabilities Query(GraphicsContext ctx, IDeviceContext deviceContext)
		{
			GraphicsCapabilities graphicsCapabilities = new GraphicsCapabilities();
			FieldInfo[] capsFields = typeof(GraphicsCapabilities).GetFields(BindingFlags.Public | BindingFlags.Instance);

			#region Platform Extension Reload

			// Since at this point there's a current OpenGL context, it's possible to use
			// {glx|wgl}GetExtensionsString to retrieve platform specific extensions

			switch (Environment.OSVersion.Platform) {
				case PlatformID.Win32NT:
				case PlatformID.Win32Windows:
				case PlatformID.Win32S:
				case PlatformID.WinCE:
					Wgl.SyncDelegates();
					break;
			}

			#endregion

			// Only boolean fields are considered
			FieldInfo[] extsFields = Array.FindAll<FieldInfo>(capsFields, delegate(FieldInfo info) {
				return (info.FieldType == typeof(bool));
			});

			foreach (FieldInfo field in extsFields) {
				Attribute[] graphicsExtensionAttributes = Attribute.GetCustomAttributes(field, typeof(GraphicsExtensionAttribute));
				GraphicsExtensionDisabledAttribute graphicsExtensionDisabled = (GraphicsExtensionDisabledAttribute)Attribute.GetCustomAttribute(field, typeof(GraphicsExtensionDisabledAttribute));
				bool implemented = false;

				// Check whether at least one extension is implemented
				implemented = Array.Exists(graphicsExtensionAttributes, delegate(Attribute item) {
					return ((GraphicsExtensionAttribute)item).IsSupported(ctx, deviceContext);
				});
				// Check whether the required extensions are artifically disabled
				if (graphicsExtensionDisabled != null)
					implemented = false;

				field.SetValue(graphicsCapabilities, implemented);
			}

			return (graphicsCapabilities);
		}
		public static void EnablePrimitiveRestart(GraphicsContext ctx, uint index)
		{
			if (ctx == null)
				throw new ArgumentNullException("ctx");
			if (ctx.IsCurrent)
				throw new ArgumentException("not current", "ctx");

			if (ctx.Caps.GlExtensions.PrimitiveRestart) {
				// Enable primitive restart (server state)
				Gl.Enable(EnableCap.PrimitiveRestart);
				// Specify restart index
				Gl.PrimitiveRestartIndex(index);
			} else if(ctx.Caps.GlExtensions.PrimitiveRestart_NV) {
				// Enable primitive restart (client state)
				Gl.EnableClientState(EnableCap.PrimitiveRestartNv);
				// Specify restart index
				Gl.PrimitiveRestartIndexNV(index);
			} else
				throw new InvalidOperationException("primitive restart not supported");
		}
		/// <summary>
		/// Query OpenGL implementation extensions.
		/// </summary>
		/// <param name="ctx"></param>
		/// <returns></returns>
		public static GraphicsCapabilities Query(GraphicsContext ctx, IDeviceContext deviceContext)
		{
			GraphicsCapabilities graphicsCapabilities = new GraphicsCapabilities();

			KhronosApi.LogComment("Query OpenGL extensions.");

			#region Platform Extension Reload

			// Since at this point there's a current OpenGL context, it's possible to use
			// {glx|wgl}GetExtensionsString to retrieve platform specific extensions

			switch (Environment.OSVersion.Platform) {
				case PlatformID.Win32NT:
				case PlatformID.Win32Windows:
				case PlatformID.Win32S:
				case PlatformID.WinCE:
					// Wgl.SyncDelegates();
					break;
			}

			#endregion

			// OpenGL extensions
			graphicsCapabilities._GlExtensions.Query();
			// Windows OpenGL extensions
			WindowsDeviceContext windowsDeviceContext = deviceContext as WindowsDeviceContext;
			if (windowsDeviceContext != null)
				graphicsCapabilities._WglExtensions.Query(windowsDeviceContext);
			// GLX OpenGL extensions
			XServerDeviceContext xserverDeviceContext = deviceContext as XServerDeviceContext;
			if (xserverDeviceContext != null)
				graphicsCapabilities._GlxExtensions.Query(xserverDeviceContext);

			// Query implementation limits
			graphicsCapabilities._GraphicsLimits = GraphicsLimits.Query(graphicsCapabilities._GlExtensions);

			return (graphicsCapabilities);
		}
		/// <summary>
		/// Determine whether this object requires a name bound to a context or not.
		/// </summary>
		/// <param name="ctx">
		/// A <see cref="GraphicsContext"/> used for creating this object name.
		/// </param>
		/// <returns>
		/// <para>
		/// This implementation returns always false.
		/// </para>
		/// </returns>
		protected override bool RequiresName(GraphicsContext ctx)
		{
			return (false);
		}
Example #13
0
		/// <summary>
		/// Actually create this GraphicsResource resources.
		/// </summary>
		/// <param name="ctx">
		/// A <see cref="GraphicsContext"/> used for allocating resources.
		/// </param>
		protected override void CreateObject(GraphicsContext ctx)
		{
			int currentBinding;

			Gl.Get(Gl.RENDERBUFFER_BINDING, out currentBinding);
			Gl.BindRenderbuffer(Gl.RENDERBUFFER, ObjectName);

			// Define buffer storage
			Gl.RenderbufferStorage(Gl.RENDERBUFFER, Pixel.GetGlInternalFormat(_InternalFormat, ctx), (int)_Width, (int)_Height);
			// Restore previous RenderBuffer binding
			Gl.BindRenderbuffer(Gl.RENDERBUFFER, (uint)currentBinding);
		}
Example #14
0
		/// <summary>
		/// Determine whether this RenderBuffer really exists for a specific context.
		/// </summary>
		/// <param name="ctx">
		/// A <see cref="GraphicsContext"/> that would have created (or a sharing one) the object. This context shall be current to
		/// the calling thread.
		/// </param>
		/// <returns>
		/// It returns a boolean value indicating whether this RenderBuffer exists in the object space of <paramref name="ctx"/>.
		/// </returns>
		/// <remarks>
		/// <para>
		/// The object existence is done by checking a valid object by its name <see cref="IGraphicsResource.ObjectName"/>. This routine will test whether
		/// <paramref name="ctx"/> has created this RenderBuffer (or is sharing with the creator).
		/// </para>
		/// </remarks>
		/// <exception cref="ArgumentNullException">
		/// Exception thrown if <paramref name="ctx"/> is null.
		/// </exception>
		/// <exception cref="ArgumentException">
		/// Exception thrown if <paramref name="ctx"/> is not current to the calling thread.
		/// </exception>
		public override bool Exists(GraphicsContext ctx)
		{
			if (ctx == null)
				throw new ArgumentNullException("ctx");
			if (ctx.IsCurrent == false)
				throw new ArgumentException("not current", "ctx");
		
			// Object name space test (and 'ctx' sanity checks)
			if (base.Exists(ctx) == false)
				return (false);

			return (Gl.IsRenderbuffer(ObjectName));
		}
		protected override void CreateObject(GraphicsContext ctx)
		{
			// Base implementation
			base.CreateObject(ctx);

			if ((_PatchElement != null) && (_PatchElement.ArrayIndices != null))
				_PatchElement.ArrayIndices.Create(ctx);
		}
		/// <summary>
		/// Render this vertex array.
		/// </summary>
		/// <param name="ctx">
		/// The <see cref="GraphicsContext"/> used for rendering.
		/// </param>
		/// <param name="shaderProgram">
		/// The <see cref="ShaderProgram"/> used for drawing this vertex array.
		/// </param>
		public override void Draw(GraphicsContext ctx, ShaderProgram shaderProgram)
		{
			if (ctx == null)
				throw new ArgumentNullException("ctx");
			if (ctx.IsCurrent == false)
				throw new ArgumentException("not current", "ctx");
			if (shaderProgram == null)
				throw new ArgumentNullException("shaderProgram");
			if (shaderProgram.Exists(ctx) == false)
				throw new ArgumentException("not existing", "shaderProgram");
			if (Exists(ctx) == false)
				throw new InvalidOperationException("not existing");
			if (_Elements.Count == 0 && _PatchElement == null)
				throw new InvalidOperationException("no elements defined");

			if (_PatchElement != null) {
				// Setup patch vertices
				Gl.PatchParameter(Gl.PATCH_VERTICES, (int)_PatchElement.PatchCount);

				// GL_PATCH_DEFAULT_OUTER_LEVEL | GL_PATCH_DEFAULT_INNER_LEVEL

				// Set vertex arrays
				SetVertexArrayState(ctx, shaderProgram);
				// Uses shader
				shaderProgram.Bind(ctx);
				// Draw patches
				_PatchElement.Draw(ctx);
			}

			// Based implementation
			if (_Elements.Count > 0)
				base.Draw(ctx, shaderProgram);
		}
Example #17
0
 /// <summary>
 /// Create Texture2d data, defining only the extents and the internal format.
 /// </summary>
 /// <param name="ctx">
 /// A <see cref="GraphicsContext"/> used for creating this Texture. If it null, the current context
 /// will be used.
 /// </param>
 /// <param name="width">
 /// A <see cref="UInt32"/> that specify the texture width.
 /// </param>
 /// <param name="format">
 /// A <see cref="PixelLayout"/> determining the texture internal format.
 /// </param>
 /// <exception cref="ArgumentException">
 /// Exception thrown if <paramref name="width"/> is zero.
 /// </exception>
 /// <exception cref="ArgumentException">
 /// Exception thrown if <paramref name="format"/> equals to <see cref="PixelFormat.None"/>.
 /// </exception>
 /// <exception cref="InvalidOperationException">
 /// Exception thrown if <paramref name="ctx"/> is null and no context is current to the calling thread.
 /// </exception>
 /// <exception cref="ArgumentException">
 /// Exception thrown if <paramref name="width"/> is greater than the maximum allowed for 2D textures.
 /// </exception>
 /// <exception cref="ArgumentException">
 /// Exception thrown if NPOT texture are not supported by <paramref name="ctx"/> and <paramref name="width"/>
 /// is not a power-of-two value.
 /// </exception>
 /// <exception cref="ArgumentException">
 /// Exception thrown if <paramref name="format"/> is not a supported internal format.
 /// </exception>
 public Texture1d(GraphicsContext ctx, uint width, PixelLayout format)
 {
     Create(ctx, width, format);
 }
		/// <summary>
		/// Unbind this GraphicsSurface for drawing.
		/// </summary>
		/// <param name="ctx">
		/// A <see cref="GraphicsContext"/> to wich disassociate its rendering result from this GraphicsSurface.
		/// </param>
		public virtual void UnbindDraw(GraphicsContext ctx) { }
Example #19
0
 /// <summary>
 /// Unbind this Texture.
 /// </summary>
 /// <param name="ctx">
 /// A <see cref="GraphicsContext"/> used for binding this Texture.
 /// </param>
 /// <remarks>
 /// To call this routine the condition <i>IsCreated</i> shall be true.
 /// </remarks>
 public virtual void Unbind(GraphicsContext ctx)
 {
     Unbind(ctx, TextureTarget);
 }
Example #20
0
        /// <summary>
        /// Apply Texture parameters of specific target.
        /// </summary>
        /// <param name="ctx">
        /// A <see cref="GraphicsContext"/> used for setting texture parameter.
        /// </param>
        /// <param name="target">
        /// A <see cref="TextureTarget"/> that specify the Texture target.
        /// </param>
        protected void ApplyParameters(GraphicsContext ctx, TextureTarget target)
        {
            int iParam;

            #region Minification Filter

            if (_HasMipMaps)
            {
                switch (MinFilter)
                {
                case Filter.Nearest:
                    switch (MipFilter)
                    {
                    case Filter.Nearest:
                        iParam = Gl.NEAREST_MIPMAP_NEAREST;
                        break;

                    case Filter.Linear:
                        iParam = Gl.NEAREST_MIPMAP_LINEAR;
                        break;

                    default:
                        throw new NotSupportedException(String.Format("unknown mipmap minification filter {0}", MipFilter));
                    }
                    break;

                case Filter.Linear:
                    switch (MipFilter)
                    {
                    case Filter.Nearest:
                        iParam = Gl.LINEAR_MIPMAP_NEAREST;
                        break;

                    case Filter.Linear:
                        iParam = Gl.LINEAR_MIPMAP_LINEAR;
                        break;

                    default:
                        throw new NotSupportedException(String.Format("unknown mipmap minification filter {0}", MipFilter));
                    }
                    break;

                default:
                    throw new NotSupportedException(String.Format("unknown minification filter {0}", MinFilter));
                }

                // Set minification filter (with mipmaps)
                Gl.TexParameter(target, TextureParameterName.TextureMinFilter, iParam);
            }
            else
            {
                switch (MinFilter)
                {
                case Filter.Nearest:
                    iParam = Gl.NEAREST;
                    break;

                case Filter.Linear:
                    iParam = Gl.LINEAR;
                    break;

                default:
                    throw new NotSupportedException(String.Format("unknown minification filter {0}", MinFilter));
                }
                // Set minification filter (without mipmaps)
                Gl.TexParameter(target, TextureParameterName.TextureMinFilter, iParam);
            }

            #endregion

            #region Magnification Filter

            switch (MagFilter)
            {
            case Filter.Nearest:
                iParam = Gl.NEAREST;
                break;

            case Filter.Linear:
                iParam = Gl.LINEAR;
                break;

            default:
                throw new NotSupportedException(String.Format("unknown magnification filter {0}", MagFilter));
            }

            // Set minification filter (without mipmaps)
            Gl.TexParameter(target, TextureParameterName.TextureMagFilter, iParam);

            #endregion

            #region Wrapping

            if (target != TextureTarget.TextureRectangle)
            {
                // Wrap S coordinate
                Gl.TexParameter(target, TextureParameterName.TextureWrapS, (int)WrapCoordS);
                // Wrap T coordinate
                Gl.TexParameter(target, TextureParameterName.TextureWrapT, (int)WrapCoordT);
                // Wrap R coordinate
                Gl.TexParameter(target, TextureParameterName.TextureWrapR, (int)WrapCoordR);
            }

            #endregion

            #region Textel Components Swizzle

            if ((_TextelSwizzleRGBA != null) && (ctx.Caps.GlExtensions.TextureSwizzle_ARB))
            {
                // Set components swizzle setup
                Gl.TexParameter(target, (TextureParameterName)Gl.TEXTURE_SWIZZLE_RGBA, _TextelSwizzleRGBA);
            }

            #endregion
        }
Example #21
0
 /// <summary>
 /// Apply this Texture parameters.
 /// </summary>
 /// <param name="ctx">
 /// A <see cref="GraphicsContext"/> used for setting texture parameter.
 /// </param>
 /// <remarks>
 /// Tipically this routine is implemented by simply calling the routine
 /// <see cref="ApplyParameters(GraphicsContext,int)"/>.
 /// </remarks>
 public virtual void ApplyParameters(GraphicsContext ctx)
 {
     ApplyParameters(ctx, TextureTarget);
 }
Example #22
0
 /// <summary>
 /// Generate mipmaps for this Texture.
 /// </summary>
 /// <param name="ctx">
 /// A <see cref="GraphicsContext"/> used for generating texture mipmaps.
 /// </param>
 internal virtual void GenerateMipmaps(GraphicsContext ctx)
 {
     GenerateMipmaps(ctx, TextureTarget);
 }
Example #23
0
 /// <summary>
 /// Delete a Texture name.
 /// </summary>
 /// <param name="ctx">
 /// A <see cref="GraphicsContext"/> used for deleting this object name.
 /// </param>
 /// <param name="name">
 /// A <see cref="UInt32"/> that specify the object name to delete.
 /// </param>
 protected override void DeleteName(GraphicsContext ctx, uint name)
 {
     // Delete texture name
     Gl.DeleteTextures(name);
 }
Example #24
0
 /// <summary>
 /// Create a Texture name.
 /// </summary>
 /// <param name="ctx">
 /// A <see cref="GraphicsContext"/> used for creating this object name.
 /// </param>
 /// <returns>
 /// It returns a valid object name for this Texture.
 /// </returns>
 protected override uint CreateName(GraphicsContext ctx)
 {
     // Generate texture name
     return(Gl.GenTexture());
 }
Example #25
0
 /// <summary>
 /// Render on this UserControl.
 /// </summary>
 /// <param name="ctx">
 /// A <see cref="GraphicsContext"/> used for rendering this UserControl.
 /// </param>
 protected virtual void RenderThis(GraphicsContext ctx)
 {
 }
		/// <summary>
		/// Delete this GraphicsResource.
		/// </summary>
		/// <param name="ctx">
		/// A <see cref="GraphicsContext"/> used for deleting this object. The IGraphicsResource shall belong to the object space to this
		/// <see cref="GraphicsContext"/>. The <see cref="GraphicsContext"/> shall be current to the calling thread.
		/// </param>
		/// <remarks>
		/// <para>
		/// After this method, the resource must have deallocated every graphic resource associated with it. Normally it should be possible
		/// to create again the resources by calling <see cref="Create"/>.
		/// </para>
		/// <para>
		/// This methods shall be the preferred way to deallocate graphic resources.
		/// </para>
		/// <para>
		/// After a successfull call to Create, <see cref="Exists"/> shall return true.
		/// </para>
		/// <para>
		/// The actual implementation deletes the name (<see cref="DeleteName"/>) only if the implementation requires a context related name
		/// (<see cref="RequiresName"/>). In the case derived classes requires more complex resource deletion pattern, this method could
		/// be overriden for that purpose, paying attention to call the base implementation.
		/// </para>
		/// </remarks>
		/// <seealso cref="Create"/>
		/// <exception cref="ArgumentNullException">
		/// Exception thrown if <paramref name="ctx"/> is null.
		/// </exception>
		/// <exception cref="ArgumentException">
		/// Exception thrown if <paramref name="ctx"/> is not current to the calling thread.
		/// </exception>
		/// <exception cref="ArgumentException">
		/// Exception thrown if this object doesn't exists for <paramref name="ctx"/> (this is determined by calling <see cref="Exists"/>
		/// method), or this resource has a name and <paramref name="ctx"/> is not current to the calling thread.
		/// </exception>
		public override void Delete(GraphicsContext ctx)
		{
			// Base implementation
			base.Delete(ctx);
			// Dispose shader includes
			foreach (ShaderInclude shaderInclude in _IncludeFileSystem.Values)
				shaderInclude.DecRef();
		}
		/// <summary>
		/// Clear surface buffers.
		/// </summary>
		/// <param name="ctx">
		/// A <see cref="GraphicsContext"/> used for clearing buffers.
		/// </param>
		/// <param name="bufferMask">
		/// A <see cref="GraphicsBuffersFormat.BufferType"/> indicating which buffers to clear.
		/// </param>
		public void Clear(GraphicsContext ctx, GraphicsBuffersFormat.BufferType bufferMask)
		{
			// Update clear values (only what is necessary)
			if ((bufferMask & GraphicsBuffersFormat.BufferType.Color) != 0)
				Gl.ClearColor(mClearColor.Red, mClearColor.Green, mClearColor.Blue, mClearColor.Alpha);
			if ((bufferMask & GraphicsBuffersFormat.BufferType.Depth) != 0)
				Gl.ClearDepth(mClearDepth);
			if ((bufferMask & GraphicsBuffersFormat.BufferType.Stencil) != 0)
				Gl.ClearStencil(mClearStencil);
			
			// Clear
			Gl.Clear(GetClearFlags(bufferMask));
		}
Example #28
0
 /// <summary>
 /// Bind this Texture on specific target.
 /// </summary>
 /// <param name="ctx">
 /// A <see cref="GraphicsContext"/> used for binding this Texture.
 /// </param>
 /// <param name="target">
 /// A <see cref="TextureTarget"/> that specify the texture target.
 /// </param>
 protected void Bind(GraphicsContext ctx, TextureTarget target)
 {
     // Bind this Texture on specified target
     Gl.BindTexture(target, ObjectName);
 }
		/// <summary>
		/// Read this GraphicsSurface color buffer.
		/// </summary>
		/// <param name="ctx">
		/// A <see cref="GraphicsContext"/>
		/// </param>
		/// <param name="rBuffer">
		/// A <see cref="ReadBufferMode"/> that specify the read buffer where the colors are read from.
		/// </param>
		/// <param name="x">
		/// A <see cref="Int32"/> that specify the x coordinate of the lower left corder of the rectangle area to read.
		/// </param>
		/// <param name="y">
		/// A <see cref="Int32"/> that specify the y coordinate of the lower left corder of the rectangle area to read.
		/// </param>
		/// <param name="width">
		/// A <see cref="Int32"/> that specify the width of the rectangle area to read.
		/// </param>
		/// <param name="height">
		/// A <see cref="Int32"/> that specify the height of the rectangle area to read.
		/// </param>
		/// <param name="pType">
		/// A <see cref="PixelLayout"/> which determine the pixel storage of the returned image.
		/// </param>
		/// <returns>
		/// It returns an <see cref="Image"/> representing the current read buffer <paramref name="rBuffer"/>.
		/// </returns>
		protected Image ReadBuffer(GraphicsContext ctx, ReadBufferMode rBuffer, uint x, uint y, uint width, uint height, PixelLayout pType)
		{
			Image image = null;

			if ((x + width > Width) || (y + height > Height))
				throw new ArgumentException("specified region lies outside the GraphicsSurface");

			// Bind for reading
			BindRead(ctx);
			// Set for reading
			Gl.ReadBuffer(rBuffer);

			// Allocate image holding data read
			image = new Image();
			image.Create(pType, width, height);

			// Set pixel transfer
			foreach (int alignment in new int[] { 8, 4, 2, 1 }) {
				if (image.Stride % alignment == 0) {
					Gl.PixelStore(PixelStoreParameter.PackAlignment, alignment);
					break;
				}
			}

			// Grab frame buffer pixels
			PixelFormat rFormat = Pixel.GetGlFormat(pType);
			PixelType rType = Pixel.GetPixelType(pType);

			Gl.ReadPixels((int)x, (int)y, (int)width, (int)height, rFormat, rType, image.ImageBuffer);

			// Unbind from reading
			UnbindRead(ctx);

			return (image);
		}
Example #30
0
 /// <summary>
 /// Unbind this Texture on specific target.
 /// </summary>
 /// <param name="ctx">
 /// A <see cref="GraphicsContext"/> used for binding this Texture.
 /// </param>
 /// <param name="target">
 /// A <see cref="TextureTarget"/> that specify the texture target.
 /// </param>
 protected void Unbind(GraphicsContext ctx, TextureTarget target)
 {
     // Unbind this Texture on specified target
     Gl.BindTexture(target, 0);
 }
Example #31
0
		/// <summary>
		/// Create a Texture name.
		/// </summary>
		/// <param name="ctx">
		/// A <see cref="GraphicsContext"/> used for creating this object name.
		/// </param>
		/// <returns>
		/// It returns a valid object name for this Texture.
		/// </returns>
		protected override uint CreateName(GraphicsContext ctx)
		{
			// Generate texture name
			return (Gl.GenTexture());
		}
Example #32
0
 /// <summary>
 /// Delete a ShaderProgram name.
 /// </summary>
 /// <param name="ctx">
 /// A <see cref="GraphicsContext"/> used for deleting this object name.
 /// </param>
 /// <param name="name">
 /// A <see cref="UInt32"/> that specify the object name to delete.
 /// </param>
 protected override void DeleteName(GraphicsContext ctx, uint name)
 {
     // Delete program
     Gl.DeleteProgram(name);
 }
		/// <summary>
		/// Create a BufferObject name.
		/// </summary>
		/// <param name="ctx">
		/// A <see cref="GraphicsContext"/> used for creating this buffer object name.
		/// </param>
		/// <returns>
		/// It returns a valid object name for this BufferObject.
		/// </returns>
		/// <exception cref="ArgumentNullException">
		/// Exception thrown if <paramref name="ctx"/> is null.
		/// </exception>
		/// <exception cref="ArgumentException">
		/// Exception thrown if <paramref name="ctx"/> is not current on the calling thread.
		/// </exception>
		protected override uint CreateName(GraphicsContext ctx)
		{
			if (ctx == null)
				throw new ArgumentNullException("ctx");

			// Here is the most appropriate point where to check patch support by current OpenGL implementation.
			if (ctx.Caps.GlExtensions.TessellationShader_ARB == false)
				throw new NotSupportedException("GL_ARB_tesselation_shader_ARB not supported by current implementation");

			// Base implementation
			return (base.CreateName(ctx));
		}
Example #34
0
 /// <summary>
 /// Create a ShaderProgram name.
 /// </summary>
 /// <param name="ctx">
 /// A <see cref="GraphicsContext"/> used for creating this object name.
 /// </param>
 /// <returns>
 /// It returns a valid object name for this ShaderProgram.
 /// </returns>
 protected override uint CreateName(GraphicsContext ctx)
 {
     // Create program
     return(Gl.CreateProgram());
 }
Example #35
0
		/// <summary>
		/// Allocate this RenderBuffer.
		/// </summary>
		/// <param name="ctx">
		/// A <see cref="GraphicsContext"/> used for allocation.
		/// </param>
		/// <param name="w">
		/// A <see cref="Int32"/> that specify the width of the renderbuffer.
		/// </param>
		/// <param name="h">
		/// A <see cref="Int32"/> that specify the height of the renderbuffer.
		/// </param>
		public void Allocate(GraphicsContext ctx, uint w, uint h)
		{
			// Allocate buffer
			Gl.BindRenderbuffer(Gl.RENDERBUFFER, ObjectName);
			// Define buffer storage
			Gl.RenderbufferStorage(Gl.RENDERBUFFER, Pixel.GetGlInternalFormat(_InternalFormat, ctx), (int)w, (int)h);
		}
 /// <summary>
 /// Draw the elements instances
 /// </summary>
 ///  <param name="ctx">
 /// The <see cref="GraphicsContext"/> used for drawing.
 /// </param>
 /// <param name="instances">
 /// A <see cref="UInt32"/> that specify the number of instances to draw.
 /// </param>
 public abstract void DrawInstanced(GraphicsContext ctx, uint instances);
Example #37
0
		/// <summary>
		/// Create a RenderBuffer name.
		/// </summary>
		/// <param name="ctx">
		/// A <see cref="GraphicsContext"/> used for creating this object name.
		/// </param>
		/// <returns>
		/// It returns a valid object name for this RenderBuffer.
		/// </returns>
		protected override uint CreateName(GraphicsContext ctx)
		{
			return (Gl.GenRenderbuffer());
		}
Example #38
0
 public void End(GraphicsContext ctx)
 {
     Gl.EndQuery((int)mTarget);
 }
Example #39
0
		/// <summary>
		/// Delete a RenderBuffer name.
		/// </summary>
		/// <param name="ctx">
		/// A <see cref="GraphicsContext"/> used for deleting this object name.
		/// </param>
		/// <param name="name">
		/// A <see cref="UInt32"/> that specify the object name to delete.
		/// </param>
		protected override void DeleteName(GraphicsContext ctx, uint name)
		{
			// Delete this render buffer
			Gl.DeleteRenderbuffers(name);
		}
 /// <summary>
 /// Draw the elements.
 /// </summary>
 /// <param name="ctx">
 /// The <see cref="GraphicsContext"/> used for drawing.
 /// </param>
 public abstract void Draw(GraphicsContext ctx);
		/// <summary>
		/// Actually create this GraphicsResource resources.
		/// </summary>
		/// <param name="ctx">
		/// A <see cref="GraphicsContext"/> used for allocating resources.
		/// </param>
		protected override void CreateObject(GraphicsContext ctx)
		{
			foreach (ShaderInclude shaderInclude in _IncludeFileSystem.Values)
				shaderInclude.Create(ctx);
		}
 /// <summary>
 /// Ensure that all required resources are created.
 /// </summary>
 /// <param name="ctx">
 /// The <see cref="GraphicsContext"/> used for allocating resources.
 /// </param>
 public virtual void Create(GraphicsContext ctx)
 {
 }
		/// <summary>
		/// Clear all Surface buffers.
		/// </summary>
		/// <param name="ctx">
		/// A <see cref="GraphicsContext"/> used for clearing buffers.
		/// </param>
		public void Clear(GraphicsContext ctx)
		{
			Clear(ctx, BufferFormat.BuffersMask);
		}
 /// <summary>
 /// Draw the elements instances
 /// </summary>
 ///  <param name="ctx">
 /// The <see cref="GraphicsContext"/> used for drawing.
 /// </param>
 /// <param name="instances">
 /// A <see cref="UInt32"/> that specify the number of instances to draw.
 /// </param>
 public override void DrawInstanced(GraphicsContext ctx, uint instances)
 {
     throw new NotSupportedException();
 }
		/// <summary>
		/// Check whether sRGB color correction on this GraphicsSurface is enabled.
		/// </summary>
		/// <param name="ctx">
		/// A <see cref="GraphicsContext"/>.
		/// </param>
		/// <param name="surfaceFormat">
		/// 
		/// </param>
		/// <returns>
		/// Is returns a boolean value indicating whether sRGB color correction on this GraphicsSurface is enabled.
		/// </returns>
		protected bool IsEnabledSRGB(GraphicsContext ctx, GraphicsBuffersFormat surfaceFormat)
		{
			if (surfaceFormat.HasBuffer(GraphicsBuffersFormat.BufferType.ColorSRGB) == false)
				throw new InvalidOperationException("surface has no sRGB buffer");
			if ((ctx.Caps.GlExtensions.FramebufferSRGB_ARB == false) && (ctx.Caps.GlExtensions.FramebufferSRGB_EXT == false))
				throw new InvalidOperationException("no framebuffer sRGB extension supported");

			return (Gl.IsEnabled(EnableCap.FramebufferSrgb));
		}
            /// <summary>
            /// Draw the elements instances
            /// </summary>
            ///  <param name="ctx">
            /// The <see cref="GraphicsContext"/> used for drawing.
            /// </param>
            /// <param name="instances">
            /// A <see cref="UInt32"/> that specify the number of instances to draw.
            /// </param>
            public override void DrawInstanced(GraphicsContext ctx, uint instances)
            {
                uint count = ElementCount != 0 ? ElementCount : _VertexArrayObject.ArrayLength;

                Gl.DrawArraysInstanced(ElementsMode, (int)ElementOffset, (int)count, (int)instances);
            }
		/// <summary>
		/// Unbind this GraphicsSurface for reading.
		/// </summary>
		/// <param name="ctx">
		/// A <see cref="GraphicsContext"/> to wich disassociate its read result from this GraphicsSurface.
		/// </param>
		public virtual void UnbindRead(GraphicsContext ctx) { }
            /// <summary>
            /// Draw the elements.
            /// </summary>
            /// <param name="ctx">
            /// The <see cref="GraphicsContext"/> used for drawing.
            /// </param>
            public override void Draw(GraphicsContext ctx)
            {
                uint count = ElementCount != 0 ? ElementCount : _VertexArrayObject.ArrayLength;

                Gl.DrawArrays(ElementsMode, (int)ElementOffset, (int)count);
            }
		/// <summary>
		/// Copy this GraphicsSurface color buffer into a buffer.
		/// </summary>
		/// <param name="ctx">
		/// A <see cref="GraphicsContext"/> which is bound to this GraphicsSurface.
		/// </param>
		/// <param name="rBuffer">
		/// A <see cref="ReadBufferMode"/> that specify the read buffer where the colors are read from.
		/// </param>
		/// <param name="x">
		/// A <see cref="Int32"/> that specify the x coordinate of the lower left corder of the rectangle area to read.
		/// </param>
		/// <param name="y">
		/// A <see cref="Int32"/> that specify the y coordinate of the lower left corder of the rectangle area to read.
		/// </param>
		/// <param name="texture">
		/// A <see cref="Texture"/> that will hold the buffer data.
		/// </param>
		/// <param name="level">
		/// The level of the texture <paramref name="texture"/> to be written.
		/// </param>
		/// <returns>
		/// It returns an <see cref="Image"/> representing the current read buffer <paramref name="rBuffer"/>.
		/// </returns>
		protected void CopyBuffer(GraphicsContext ctx, ReadBufferMode rBuffer, uint x, uint y, ref Texture texture, uint level)
		{
			if (texture == null)
				throw new ArgumentNullException("texture");
			if (texture.Exists(ctx) == false)
				throw new ArgumentException("not exists", "texture");
			if ((x + texture.Width > Width) || (y + texture.Height > Height))
				throw new ArgumentException("specified region lies outside the GraphicsSurface");

			// Bind for reading
			BindRead(ctx);
			// Set for reading
			Gl.ReadBuffer(rBuffer);

			// Copy pixels from read buffer to texture
			Gl.CopyTexImage2D(texture.TextureTarget, (int)level, Pixel.GetGlInternalFormat(texture.PixelLayout, ctx), (int)x, (int)y, (int)texture.Width, (int)texture.Height, 0);

			// Unbind from reading
			UnbindRead(ctx);
			// Reset read configuration
			Gl.ReadBuffer(Gl.NONE);
		}
Example #50
0
        /// <summary>
        /// Link this ShaderProgram.
        /// </summary>
        /// <param name="ctx">
        /// A <see cref="GraphicsContext"/> used for linking this ShaderProgram.
        /// </param>
        /// <param name="cctx">
        /// A <see cref="ShaderCompilerContext"/> that specify additional compiler parameters.
        /// </param>
        /// <remarks>
        /// <para>
        /// Generate shader program source code, compile and link it. After a successfull
        /// link, obtain every information about active uniform and input variables.
        /// </para>
        /// <para>
        /// This routine generate the source code of each attached ShaderObject instance and
        /// compile it. This step is performed only if really required (tendentially every
        /// shader object is already compiled).
        /// </para>
        /// <para>
        /// After having compiled every attached shader object, it's performed the linkage between
        /// shader objects. After this process the ShaderProgram instance can be bound to issue
        /// rendering commands.
        /// </para>
        /// </remarks>
        /// <exception cref="InvalidOperationException">
        /// Exception thrown in the case this ShaderProgram is already linked.
        /// </exception>
        /// <exception cref="ShaderException">
        /// Exception throw in the case this ShaderProgram is not linkable.
        /// </exception>
        private void Link(GraphicsContext ctx, ShaderCompilerContext cctx)
        {
            CheckCurrentContext(ctx);

            if (cctx == null)
            {
                throw new ArgumentNullException("cctx");
            }

            // Using a deep copy of the shader compiler context, since it will be modified by this ShaderProgram
            // instance and the attached ShaderObject instances
            cctx = new ShaderCompilerContext(cctx);

            #region Compile and Attach Shader Objects

            // Be sure to take every attached shader
            uint[] shadersObject = null;
            int    shadersCount;

            Gl.GetProgram(ObjectName, Gl.ATTACHED_SHADERS, out shadersCount);

            if (shadersCount > 0)
            {
                shadersObject = new uint[shadersCount];
                Gl.GetAttachedShaders(ObjectName, out shadersCount, shadersObject);
                Debug.Assert(shadersCount == shadersObject.Length);
            }

            foreach (ShaderObject shaderObject in _ProgramObjects)
            {
                // Create shader object, if necessary
                if (shaderObject.Exists(ctx) == false)
                {
                    shaderObject.Create(ctx, cctx);
                }

                // Do not re-attach the same shader object
                if ((shadersObject != null) && Array.Exists(shadersObject, delegate(uint item) { return(item == shaderObject.ObjectName); }))
                {
                    continue;
                }

                // Attach shader object
                Gl.AttachShader(ObjectName, shaderObject.ObjectName);
            }

            #endregion

            #region Transform Feedback Definition

            IntPtr[] feedbackVaryingsPtrs = null;

            if ((_FeedbackVaryings != null) && (_FeedbackVaryings.Count > 0))
            {
                sLog.Debug("Feedback varyings ({0}):", cctx.FeedbackVaryingsFormat);
                sLog.Indent();
                foreach (string feedbackVarying in _FeedbackVaryings)
                {
                    sLog.Debug("- {0}", feedbackVarying);
                }
                sLog.Unindent();

                if (ctx.Caps.GlExtensions.TransformFeedback2_ARB || ctx.Caps.GlExtensions.TransformFeedback_EXT)
                {
                    string[] feedbackVaryings = _FeedbackVaryings.ToArray();

                    // Bug in NVIDIA drivers? Not exactly, but the NVIDIA driver hold the 'feedbackVaryings' pointer until
                    // glLinkProgram is executed, causing linker errors like 'duplicate varying names are not allowed' or garbaging
                    // part of the returned strings via glGetTransformFeedbackVarying
                    feedbackVaryingsPtrs = feedbackVaryings.AllocHGlobal();

                    // Specify feedback varyings
                    Gl.TransformFeedbackVaryings(ObjectName, feedbackVaryingsPtrs, (int)cctx.FeedbackVaryingsFormat);
                }
                else if (ctx.Caps.GlExtensions.TransformFeedback2_NV)
                {
                    // Nothing to do ATM
                }
                else
                {
                    throw new InvalidOperationException("transform feedback not supported");
                }
            }

            #endregion

            #region Bind Fragment Locations

            if (ctx.Caps.GlExtensions.GpuShader4_EXT)
            {
                // Setup fragment locations, where defined
                foreach (KeyValuePair <string, int> pair in _FragLocations)
                {
                    if (pair.Value >= 0)
                    {
                        Gl.BindFragDataLocation(ObjectName, (uint)pair.Value, pair.Key);
                    }
                }
            }

            #endregion

            #region Link Shader Program Objects

            int lStatus;

            sLog.Debug("Link shader program {0}", Identifier ?? "<Unnamed>");

            // Link shader program
            Gl.LinkProgram(ObjectName);
            // Check for linking errors
            Gl.GetProgram(ObjectName, Gl.LINK_STATUS, out lStatus);

            // Release feedback varyings unmanaged memory
            if (feedbackVaryingsPtrs != null)
            {
                feedbackVaryingsPtrs.FreeHGlobal();
            }

            if (lStatus != Gl.TRUE)
            {
                const int MaxInfoLength = 4096;

                StringBuilder logInfo = new StringBuilder(MaxInfoLength);
                int           logLength;

                // Obtain compilation log
                Gl.GetProgramInfoLog(ObjectName, MaxInfoLength, out logLength, logInfo);

                // Stop link process
                StringBuilder sb = new StringBuilder(logInfo.Capacity);

                string[] compilerLogLines = logInfo.ToString().Split(new char[] { '\n' }, StringSplitOptions.RemoveEmptyEntries);
                foreach (string logLine in compilerLogLines)
                {
                    sb.AppendLine("  $ " + logLine);
                }

                sLog.Error("Shader program \"{0}\" linkage failed: {1}", Identifier ?? "<Unnamed>", sb.ToString());

                throw new ShaderException("shader program is not valid. Linker output for {0}: {1}\n", Identifier ?? "<Unnamed>", sb.ToString());
            }
            // Set linked flag
            _Linked = true;

            #endregion

            #region Collect Active Program Uniforms

            int uniformBufferSize, attributeBufferSize;
            int uniformCount;

            // Get active uniforms count
            Gl.GetProgram(ObjectName, Gl.ACTIVE_UNIFORMS, out uniformCount);
            // Get uniforms maximum length for name
            Gl.GetProgram(ObjectName, Gl.ACTIVE_UNIFORM_MAX_LENGTH, out uniformBufferSize);

            // Clear uniform mapping
            _UniformMap.Clear();
            _DefaultBlockUniformSlots = 0;

            // Collect uniform information
            for (uint i = 0; i < (uint)uniformCount; i++)
            {
                int uniformNameLength, uniformSize, uniformType;

                // Mono optimize StringBuilder capacity after P/Invoke... ensure enought room
                StringBuilder uNameBuilder = new StringBuilder(uniformBufferSize + 2);
                uNameBuilder.EnsureCapacity(uniformBufferSize);

                // Obtain active uniform informations
                Gl.GetActiveUniform(ObjectName, i, uniformBufferSize, out uniformNameLength, out uniformSize, out uniformType, uNameBuilder);

                string uniformName = uNameBuilder.ToString();

                // Obtain active uniform location
                int uLocation = Gl.GetUniformLocation(ObjectName, uniformName);

                UniformBinding uniformBinding = new UniformBinding(uniformName, i, uLocation, (ShaderUniformType)uniformType);

                // Map active uniform
                _UniformMap[uniformName] = uniformBinding;
                // Keep track of used slot
                _DefaultBlockUniformSlots += GetUniformSlotCount(uniformBinding.UniformType);
            }

            // Log uniform location mapping
            List <string> uniformNames = new List <string>(_UniformMap.Keys);

            // Make uniform list invariant respect the used driver (ease log comparation)
            uniformNames.Sort();

            sLog.Debug("Shader program active uniforms:");
            foreach (string uniformName in uniformNames)
            {
                sLog.Debug("\tUniform {0} (Type: {1}, Location: {2})", uniformName, _UniformMap[uniformName].UniformType, _UniformMap[uniformName].Location);
            }

            sLog.Debug("Shader program active uniform slots: {0}", _DefaultBlockUniformSlots);

            #endregion

            #region Collect Active Program Inputs

            // Get active inputs count
            int activeInputs;

            Gl.GetProgram(ObjectName, Gl.ACTIVE_ATTRIBUTES, out activeInputs);
            // Get inputs maximum length for name
            Gl.GetProgram(ObjectName, Gl.ACTIVE_ATTRIBUTE_MAX_LENGTH, out attributeBufferSize);

            // Clear input mapping
            _AttributesMap.Clear();

            // Collect input location mapping
            for (uint i = 0; i < (uint)activeInputs; i++)
            {
                StringBuilder nameBuffer = new StringBuilder(attributeBufferSize);
                int           nameLength, size, type;

                // Mono optimize StringBuilder capacity after P/Invoke... ensure enought room for the current loop
                nameBuffer.EnsureCapacity(attributeBufferSize);

                // Obtain active input informations
                Gl.GetActiveAttrib(ObjectName, i, attributeBufferSize, out nameLength, out size, out type, nameBuffer);
                // Obtain active input location
                string name = nameBuffer.ToString();

                int location = Gl.GetAttribLocation(ObjectName, name);
                // Map active input
                _AttributesMap[name] = new AttributeBinding((uint)location, (ShaderAttributeType)type);
            }

            // Log attribute mapping
            List <string> attributeNames = new List <string>(_AttributesMap.Keys);

            // Make attribute list invariant respect the used driver (ease log comparation)
            attributeNames.Sort();

            sLog.Debug("Shader program active attributes:");
            foreach (string attributeName in attributeNames)
            {
                sLog.Debug("\tAttribute {0} (Type: {1}, Location: {2})", attributeName, _AttributesMap[attributeName].Type, _AttributesMap[attributeName].Location);
            }

            #endregion

            #region Collect Fragment Locations

            if (ctx.Caps.GlExtensions.GpuShader4_EXT)
            {
                // Get fragment locations, just in the case automatically assigned
                foreach (string fragOutputName in new List <string>(_FragLocations.Keys))
                {
                    _FragLocations[fragOutputName] = Gl.GetFragDataLocation(ObjectName, fragOutputName);
                }
            }

            #endregion

            #region Collect Feedback Varyings

            if ((_FeedbackVaryings != null) && (_FeedbackVaryings.Count > 0))
            {
                if (ctx.Caps.GlExtensions.TransformFeedback2_ARB || ctx.Caps.GlExtensions.TransformFeedback_EXT)
                {
                    // Map active feedback
                    int feebackVaryings, feebackVaryingsMaxLength;

                    Gl.GetProgram(ObjectName, Gl.TRANSFORM_FEEDBACK_VARYINGS, out feebackVaryings);
                    Gl.GetProgram(ObjectName, Gl.TRANSFORM_FEEDBACK_VARYING_MAX_LENGTH, out feebackVaryingsMaxLength);

                    for (uint i = 0; i < feebackVaryings; i++)
                    {
                        StringBuilder sb = new StringBuilder(feebackVaryingsMaxLength);
                        int           length = 0, size = 0, type = 0;

                        Gl.GetTransformFeedbackVarying(ObjectName, (uint)i, feebackVaryingsMaxLength, out length, out size, out type, sb);
                        _FeedbacksMap.Add(sb.ToString(), new FeedbackBinding((ShaderAttributeType)type, (uint)size));
                    }
                }
                else if (ctx.Caps.GlExtensions.TransformFeedback2_NV)
                {
                    // Activate varyings
                    foreach (string feedbackVaryingName in _FeedbackVaryings)
                    {
                        Gl.ActiveVaryingNV(ObjectName, feedbackVaryingName);
                    }

                    // Map active feedback
                    int feebackVaryings, feebackVaryingsMaxLength;

                    Gl.GetProgram(ObjectName, Gl.ACTIVE_VARYINGS_NV, out feebackVaryings);
                    Gl.GetProgram(ObjectName, Gl.ACTIVE_VARYING_MAX_LENGTH_NV, out feebackVaryingsMaxLength);

                    for (uint i = 0; i < feebackVaryings; i++)
                    {
                        StringBuilder sb = new StringBuilder(feebackVaryingsMaxLength * 2);
                        int           length = 0, size = 0, type = 0;

                        Gl.GetActiveVaryingNV(ObjectName, (uint)i, feebackVaryingsMaxLength * 2, out length, out size, out type, sb);

                        _FeedbacksMap.Add(sb.ToString(), new FeedbackBinding((ShaderAttributeType)type, (uint)size));
                    }

                    // Specify feedback varyings
                    List <int> feedbackLocations = new List <int>();

                    foreach (string feedbackVaryingName in _FeedbackVaryings)
                    {
                        int location = Gl.GetVaryingLocationNV(ObjectName, feedbackVaryingName);

                        if (location >= 0)
                        {
                            feedbackLocations.Add(location);
                        }
                    }

                    Gl.TransformFeedbackVaryingsNV(ObjectName, feedbackLocations.ToArray(), (int)cctx.FeedbackVaryingsFormat);

                    // Map active feedback
                }

                Debug.Assert(_FeedbacksMap.Count > 0);

                // Log feedback mapping
                sLog.Debug("Shader program active feedbacks:");
                foreach (string feedbackName in _FeedbacksMap.Keys)
                {
                    sLog.Debug("\tFeedback {0} (Type: {1})", feedbackName, _FeedbacksMap[feedbackName].Type);
                }
            }

            #endregion
        }