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); } }
/// <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); }
/// <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); }
/// <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); }
/// <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); }
/// <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) { }
/// <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); }
/// <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 }
/// <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); }
/// <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); }
/// <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); }
/// <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()); }
/// <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)); }
/// <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); }
/// <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); }
/// <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()); }
/// <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)); }
/// <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()); }
/// <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);
/// <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()); }
public void End(GraphicsContext ctx) { Gl.EndQuery((int)mTarget); }
/// <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); }
/// <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 }