public override object this[string attribute] { get { switch (attribute.ToUpper()) { case "TARGET": var target = new GLSurfaceDesc(); target.Buffer = (GLHardwarePixelBuffer)pixelBuffer; target.ZOffset = zOffset; return(target); break; case "GLCONTEXT": // Get PBuffer for our internal format return(this.manager.GetContextFor(this.pbFormat, Width, Height)); break; default: return(base[attribute]); break; } } }
/// <summary> /// Request a render buffer. If format is Gl.GL_NONE, return a zero buffer. /// </summary> /// <param name="format"></param> /// <param name="width"></param> /// <param name="height"></param> /// <returns></returns> public GLSurfaceDesc RequestRenderBuffer(int format, int width, int height) { var retval = new GLSurfaceDesc(); retval.Buffer = null; // Return 0 buffer if GL_NONE is requested if (format != Gl.GL_NONE) { var key = new RBFormat(format, width, height); RBRef value; if (this._renderBufferMap.TryGetValue(key, out value)) { retval.Buffer = value.Buffer; retval.ZOffset = 0; // Increase refcount value.Refcount++; } else { // New one var rb = new GLRenderBuffer(format, width, height, 0); this._renderBufferMap[key] = new RBRef(rb); retval.Buffer = rb; retval.ZOffset = 0; } } LogManager.Instance.Write("Requested renderbuffer with format " + format.ToString() + " of " + width.ToString() + "x" + height.ToString() + "."); return(retval); }
public GLRenderTexture(string name, GLSurfaceDesc target, bool writeGamma, int fsaa) : base(target.Buffer, target.ZOffset) { this.name = name; this.HwGamma = writeGamma; this.Fsaa = fsaa; }
public GLRenderTexture( string name, GLSurfaceDesc target, bool writeGamma, int fsaa ) : base( target.Buffer, target.ZOffset ) { this.name = name; this.HwGamma = writeGamma; this.Fsaa = fsaa; }
public GLPBRenderTexture( GLPBRTTManager manager, string name, GLSurfaceDesc target, bool writeGamma, int fsaa ) : base( name, target, writeGamma, fsaa ) { this.manager = manager; this.pbFormat = PixelUtil.GetComponentType( target.Buffer.Format ); manager.RequestPBuffer( this.pbFormat, Width, Height ); }
public GLPBRenderTexture(GLPBRTTManager manager, string name, GLSurfaceDesc target, bool writeGamma, int fsaa) : base(name, target, writeGamma, fsaa) { this.manager = manager; this.pbFormat = PixelUtil.GetComponentType(target.Buffer.Format); manager.RequestPBuffer(this.pbFormat, Width, Height); }
/// <summary> /// Bind a surface to a certain attachment point. /// </summary> /// <param name="attachment">0..Config.MaxMultipleRenderTargets-1</param> /// <param name="target"></param> public void BindSurface(int attachment, GLSurfaceDesc target) { //assert( attachment < OGRE_MAX_MULTIPLE_RENDER_TARGETS ); this._color[attachment] = target; // Re-initialise if (this._color[0].Buffer != null) { _initialize(); } }
public GLFBORenderTexture( GLFBORTTManager manager, string name, GLSurfaceDesc target, bool writeGamma, int fsaa ) : base( name, target, writeGamma, fsaa ) { this._fbo = new GLFrameBufferObject( manager ); // Bind target to surface 0 and initialise this._fbo.BindSurface( 0, target ); // Get attributes width = this._fbo.Width; height = this._fbo.Height; }
public GLFBORenderTexture(GLFBORTTManager manager, string name, GLSurfaceDesc target, bool writeGamma, int fsaa) : base(name, target, writeGamma, fsaa) { this._fbo = new GLFrameBufferObject(manager); // Bind target to surface 0 and initialise this._fbo.BindSurface(0, target); // Get attributes width = this._fbo.Width; height = this._fbo.Height; }
/// <summary> /// Request the specific render buffer in case shared somewhere. Ignore /// silently if surface.buffer is 0. /// </summary> /// <param name="surface"></param> public void RequestRenderBuffer(GLSurfaceDesc surface) { if (surface.Buffer == null) { return; } var key = new RBFormat(surface.Buffer.GLFormat, surface.Buffer.Width, surface.Buffer.Height); RBRef value; bool result = this._renderBufferMap.TryGetValue(key, out value); Debug.Assert(result); lock (this) { Debug.Assert(value.Buffer == surface.Buffer); // Increase refcount value.Refcount++; } LogManager.Instance.Write("Requested renderbuffer with format " + surface.Buffer.GLFormat.ToString() + " of " + surface.Buffer.Width.ToString() + "x" + surface.Buffer.Height.ToString() + " with refcount " + value.Refcount.ToString() + "."); }
/// <summary> /// Release a render buffer. Ignore silently if surface.buffer is null. /// </summary> /// <param name="surface"></param> public void ReleaseRenderBuffer(GLSurfaceDesc surface) { if (surface.Buffer == null) { return; } var key = new RBFormat(surface.Buffer.GLFormat, surface.Buffer.Width, surface.Buffer.Height); RBRef value; if (this._renderBufferMap.TryGetValue(key, out value)) { // Decrease refcount value.Refcount--; if (value.Refcount == 0) { // If refcount reaches zero, delete buffer and remove from map value.Buffer.Dispose(); this._renderBufferMap.Remove(key); LogManager.Instance.Write("Destroyed renderbuffer of format {0} of {1}x{2}", key.Format, key.Width, key.Height); } } }
public override object this[ string attribute ] { get { switch ( attribute.ToUpper() ) { case "TARGET": var target = new GLSurfaceDesc(); target.Buffer = (GLHardwarePixelBuffer)pixelBuffer; target.ZOffset = zOffset; return target; break; case "GLCONTEXT": // Get PBuffer for our internal format return this.manager.GetContextFor( this.pbFormat, Width, Height ); break; default: return base[ attribute ]; break; } } }
public GLCopyingRenderTexture(GLCopyingRTTManager manager, string name, GLSurfaceDesc target, bool writeGamma, int fsaa) : base(name, target, writeGamma, fsaa) { }
/// <summary> /// Create a texture rendertarget object /// </summary> /// <param name="name"></param> /// <param name="target"></param> /// <returns></returns> public abstract RenderTexture CreateRenderTexture( string name, GLSurfaceDesc target, bool writeGamma, int fsaa );
/// <summary> /// Create a texture rendertarget object /// </summary> /// <param name="name"></param> /// <param name="target"></param> /// <returns></returns> public abstract RenderTexture CreateRenderTexture(string name, GLSurfaceDesc target, bool writeGamma, int fsaa);
/// <summary> /// Initialize object (find suitable depth and stencil format). /// </summary> /// Must be called every time the bindings change. /// It fails with an exception (ArgumentException) if: /// - Attachment point 0 has no binding /// - Not all bound surfaces have the same size /// - Not all bound surfaces have the same internal format /// <remarks> private void _initialize() { // Release depth and stencil, if they were bound this._manager.ReleaseRenderBuffer(this._depth); this._manager.ReleaseRenderBuffer(this._stencil); /// First buffer must be bound if (this._color[0].Buffer == null) { throw new ArgumentException("Attachment 0 must have surface attached."); } /// Bind FBO to frame buffer Bind(); /// Store basic stats int width = this._color[0].Buffer.Width; int height = this._color[0].Buffer.Height; int glFormat = this._color[0].Buffer.GLFormat; PixelFormat format = this._color[0].Buffer.Format; /// Bind all attachment points to frame buffer for (int x = 0; x < Config.MaxMultipleRenderTargets; ++x) { if (this._color[x].Buffer != null) { if (this._color[x].Buffer.Width != width || this._color[x].Buffer.Height != height) { throw new ArgumentException( String.Format( "Attachment {0} has incompatible size {1}x{2}. It must be of the same as the size of surface 0, {3}x{4}.", x, this._color[x].Buffer.Width, this._color[x].Buffer.Height, width, height)); } if (this._color[x].Buffer.GLFormat != glFormat) { throw new ArgumentException(String.Format("Attachment {0} has incompatible format.", x)); } this._color[x].Buffer.BindToFramebuffer(Gl.GL_COLOR_ATTACHMENT0_EXT + x, this._color[x].ZOffset); } else { // Detach Gl.glFramebufferRenderbufferEXT(Gl.GL_FRAMEBUFFER_EXT, Gl.GL_COLOR_ATTACHMENT0_EXT + x, Gl.GL_RENDERBUFFER_EXT, 0); } } // Find suitable depth and stencil format that is compatible with color format int depthFormat, stencilFormat; this._manager.GetBestDepthStencil(format, out depthFormat, out stencilFormat); // Request surfaces this._depth = this._manager.RequestRenderBuffer(depthFormat, width, height); if (depthFormat == GLFBORTTManager.GL_DEPTH24_STENCIL8_EXT) { // bind same buffer to depth and stencil attachments this._manager.RequestRenderBuffer(this._depth); this._stencil = this._depth; } else { // separate stencil this._stencil = this._manager.RequestRenderBuffer(stencilFormat, width, height); } /// Attach/detach surfaces if (this._depth.Buffer != null) { this._depth.Buffer.BindToFramebuffer(Gl.GL_DEPTH_ATTACHMENT_EXT, this._depth.ZOffset); } else { Gl.glFramebufferRenderbufferEXT(Gl.GL_FRAMEBUFFER_EXT, Gl.GL_DEPTH_ATTACHMENT_EXT, Gl.GL_RENDERBUFFER_EXT, 0); } if (this._stencil.Buffer != null) { this._stencil.Buffer.BindToFramebuffer(Gl.GL_STENCIL_ATTACHMENT_EXT, this._stencil.ZOffset); } else { Gl.glFramebufferRenderbufferEXT(Gl.GL_FRAMEBUFFER_EXT, Gl.GL_STENCIL_ATTACHMENT_EXT, Gl.GL_RENDERBUFFER_EXT, 0); } /// Do glDrawBuffer calls var bufs = new int[Config.MaxMultipleRenderTargets]; int n = 0; for (int x = 0; x < Config.MaxMultipleRenderTargets; ++x) { // Fill attached color buffers if (this._color[x].Buffer != null) { bufs[x] = Gl.GL_COLOR_ATTACHMENT0_EXT + x; // Keep highest used buffer + 1 n = x + 1; } else { bufs[x] = Gl.GL_NONE; } } if (this._manager.GLSupport.CheckExtension("GL_ARB_draw_buffers")) { /// Drawbuffer extension supported, use it Gl.glDrawBuffers(n, bufs); } else if (this._manager.GLSupport.CheckExtension("GL_ATI_draw_buffers")) { Gl.glDrawBuffersATI(n, bufs); } else { /// In this case, the capabilities will not show more than 1 simultaneaous render target. Gl.glDrawBuffer(bufs[0]); } /// No read buffer, by default, if we want to read anyway we must not forget to set this. Gl.glReadBuffer(Gl.GL_NONE); /// Check status int status; status = Gl.glCheckFramebufferStatusEXT(Gl.GL_FRAMEBUFFER_EXT); /// Bind main buffer Gl.glBindFramebufferEXT(Gl.GL_FRAMEBUFFER_EXT, 0); switch (status) { case Gl.GL_FRAMEBUFFER_COMPLETE_EXT: // All is good break; case Gl.GL_FRAMEBUFFER_UNSUPPORTED_EXT: throw new ArgumentException("All framebuffer formats with this texture internal format unsupported"); default: throw new ArgumentException("Framebuffer incomplete or other FBO status error"); } }
/// <summary> /// Bind a surface to a certain attachment point. /// </summary> /// <param name="attachment">0..Config.MaxMultipleRenderTargets-1</param> /// <param name="target"></param> public void BindSurface( int attachment, GLSurfaceDesc target ) { //assert( attachment < OGRE_MAX_MULTIPLE_RENDER_TARGETS ); this._color[ attachment ] = target; // Re-initialise if ( this._color[ 0 ].Buffer != null ) { _initialize(); } }
public override RenderTexture CreateRenderTexture( string name, GLSurfaceDesc target, bool writeGamma, int fsaa ) { return new GLCopyingRenderTexture( this, name, target, writeGamma, fsaa ); }
public override RenderTexture CreateRenderTexture(string name, GLSurfaceDesc target, bool writeGamma, int fsaa) { return(new GLCopyingRenderTexture(this, name, target, writeGamma, fsaa)); }
/// <summary> /// Request a render buffer. If format is Gl.GL_NONE, return a zero buffer. /// </summary> /// <param name="format"></param> /// <param name="width"></param> /// <param name="height"></param> /// <returns></returns> public GLSurfaceDesc RequestRenderBuffer( int format, int width, int height ) { var retval = new GLSurfaceDesc(); retval.Buffer = null; // Return 0 buffer if GL_NONE is requested if ( format != Gl.GL_NONE ) { var key = new RBFormat( format, width, height ); RBRef value; if ( this._renderBufferMap.TryGetValue( key, out value ) ) { retval.Buffer = value.Buffer; retval.ZOffset = 0; // Increase refcount value.Refcount++; } else { // New one var rb = new GLRenderBuffer( format, width, height, 0 ); this._renderBufferMap[ key ] = new RBRef( rb ); retval.Buffer = rb; retval.ZOffset = 0; } } LogManager.Instance.Write( "Requested renderbuffer with format " + format.ToString() + " of " + width.ToString() + "x" + height.ToString() + "." ); return retval; }
public GLCopyingRenderTexture( GLCopyingRTTManager manager, string name, GLSurfaceDesc target, bool writeGamma, int fsaa ) : base( name, target, writeGamma, fsaa ) { }
/// <summary> /// Request the specific render buffer in case shared somewhere. Ignore /// silently if surface.buffer is 0. /// </summary> /// <param name="surface"></param> public void RequestRenderBuffer( GLSurfaceDesc surface ) { if ( surface.Buffer == null ) { return; } var key = new RBFormat( surface.Buffer.GLFormat, surface.Buffer.Width, surface.Buffer.Height ); RBRef value; bool result = this._renderBufferMap.TryGetValue( key, out value ); Debug.Assert( result ); lock ( this ) { Debug.Assert( value.Buffer == surface.Buffer ); // Increase refcount value.Refcount++; } LogManager.Instance.Write( "Requested renderbuffer with format " + surface.Buffer.GLFormat.ToString() + " of " + surface.Buffer.Width.ToString() + "x" + surface.Buffer.Height.ToString() + " with refcount " + value.Refcount.ToString() + "." ); }
/// <summary> /// Initialize object (find suitable depth and stencil format). /// </summary> /// Must be called every time the bindings change. /// It fails with an exception (ArgumentException) if: /// - Attachment point 0 has no binding /// - Not all bound surfaces have the same size /// - Not all bound surfaces have the same internal format /// <remarks> private void _initialize() { // Release depth and stencil, if they were bound this._manager.ReleaseRenderBuffer( this._depth ); this._manager.ReleaseRenderBuffer( this._stencil ); /// First buffer must be bound if ( this._color[ 0 ].Buffer == null ) { throw new ArgumentException( "Attachment 0 must have surface attached." ); } /// Bind FBO to frame buffer Bind(); /// Store basic stats int width = this._color[ 0 ].Buffer.Width; int height = this._color[ 0 ].Buffer.Height; int glFormat = this._color[ 0 ].Buffer.GLFormat; PixelFormat format = this._color[ 0 ].Buffer.Format; /// Bind all attachment points to frame buffer for ( int x = 0; x < Config.MaxMultipleRenderTargets; ++x ) { if ( this._color[ x ].Buffer != null ) { if ( this._color[ x ].Buffer.Width != width || this._color[ x ].Buffer.Height != height ) { throw new ArgumentException( String.Format( "Attachment {0} has incompatible size {1}x{2}. It must be of the same as the size of surface 0, {3}x{4}.", x, this._color[ x ].Buffer.Width, this._color[ x ].Buffer.Height, width, height ) ); } if ( this._color[ x ].Buffer.GLFormat != glFormat ) { throw new ArgumentException( String.Format( "Attachment {0} has incompatible format.", x ) ); } this._color[ x ].Buffer.BindToFramebuffer( Gl.GL_COLOR_ATTACHMENT0_EXT + x, this._color[ x ].ZOffset ); } else { // Detach Gl.glFramebufferRenderbufferEXT( Gl.GL_FRAMEBUFFER_EXT, Gl.GL_COLOR_ATTACHMENT0_EXT + x, Gl.GL_RENDERBUFFER_EXT, 0 ); } } // Find suitable depth and stencil format that is compatible with color format int depthFormat, stencilFormat; this._manager.GetBestDepthStencil( format, out depthFormat, out stencilFormat ); // Request surfaces this._depth = this._manager.RequestRenderBuffer( depthFormat, width, height ); if ( depthFormat == GLFBORTTManager.GL_DEPTH24_STENCIL8_EXT ) { // bind same buffer to depth and stencil attachments this._manager.RequestRenderBuffer( this._depth ); this._stencil = this._depth; } else { // separate stencil this._stencil = this._manager.RequestRenderBuffer( stencilFormat, width, height ); } /// Attach/detach surfaces if ( this._depth.Buffer != null ) { this._depth.Buffer.BindToFramebuffer( Gl.GL_DEPTH_ATTACHMENT_EXT, this._depth.ZOffset ); } else { Gl.glFramebufferRenderbufferEXT( Gl.GL_FRAMEBUFFER_EXT, Gl.GL_DEPTH_ATTACHMENT_EXT, Gl.GL_RENDERBUFFER_EXT, 0 ); } if ( this._stencil.Buffer != null ) { this._stencil.Buffer.BindToFramebuffer( Gl.GL_STENCIL_ATTACHMENT_EXT, this._stencil.ZOffset ); } else { Gl.glFramebufferRenderbufferEXT( Gl.GL_FRAMEBUFFER_EXT, Gl.GL_STENCIL_ATTACHMENT_EXT, Gl.GL_RENDERBUFFER_EXT, 0 ); } /// Do glDrawBuffer calls var bufs = new int[Config.MaxMultipleRenderTargets]; int n = 0; for ( int x = 0; x < Config.MaxMultipleRenderTargets; ++x ) { // Fill attached color buffers if ( this._color[ x ].Buffer != null ) { bufs[ x ] = Gl.GL_COLOR_ATTACHMENT0_EXT + x; // Keep highest used buffer + 1 n = x + 1; } else { bufs[ x ] = Gl.GL_NONE; } } if ( this._manager.GLSupport.CheckExtension( "GL_ARB_draw_buffers" ) ) { /// Drawbuffer extension supported, use it Gl.glDrawBuffers( n, bufs ); } else if ( this._manager.GLSupport.CheckExtension( "GL_ATI_draw_buffers" ) ) { Gl.glDrawBuffersATI( n, bufs ); } else { /// In this case, the capabilities will not show more than 1 simultaneaous render target. Gl.glDrawBuffer( bufs[ 0 ] ); } /// No read buffer, by default, if we want to read anyway we must not forget to set this. Gl.glReadBuffer( Gl.GL_NONE ); /// Check status int status; status = Gl.glCheckFramebufferStatusEXT( Gl.GL_FRAMEBUFFER_EXT ); /// Bind main buffer Gl.glBindFramebufferEXT( Gl.GL_FRAMEBUFFER_EXT, 0 ); switch ( status ) { case Gl.GL_FRAMEBUFFER_COMPLETE_EXT: // All is good break; case Gl.GL_FRAMEBUFFER_UNSUPPORTED_EXT: throw new ArgumentException( "All framebuffer formats with this texture internal format unsupported" ); default: throw new ArgumentException( "Framebuffer incomplete or other FBO status error" ); } }
/// <summary> /// Release a render buffer. Ignore silently if surface.buffer is null. /// </summary> /// <param name="surface"></param> public void ReleaseRenderBuffer( GLSurfaceDesc surface ) { if ( surface.Buffer == null ) { return; } var key = new RBFormat( surface.Buffer.GLFormat, surface.Buffer.Width, surface.Buffer.Height ); RBRef value; if ( this._renderBufferMap.TryGetValue( key, out value ) ) { // Decrease refcount value.Refcount--; if ( value.Refcount == 0 ) { // If refcount reaches zero, delete buffer and remove from map value.Buffer.Dispose(); this._renderBufferMap.Remove( key ); LogManager.Instance.Write( "Destroyed renderbuffer of format {0} of {1}x{2}", key.Format, key.Width, key.Height ); } } }