using System; using System.Runtime.InteropServices; using Tao.OpenGl; using Tao.Platform.Windows; using VJProjector; using VJProjector.GFX.Immerse.Materials; namespace VJProjector.GFX.Immerse.GPU { /// <summary> /// Implements an easy way to access OpenGL PBuffers /// </summary> public class PBuffer : RenderingContext { protected IntPtr hPBufferDC; protected IntPtr hPBufferRC; protected IntPtr hPBuffer; protected bool isBindable; protected bool isLocked; public IntPtr HPBuffer { get { return hPBuffer; } } public IntPtr HPBufferDC { get { return hPBufferDC; } } public IntPtr HPBufferRC { get { return hPBufferRC; } } protected IntPtr lastDC; protected IntPtr lastRC; protected Texture uploadTexture; protected Bmp textureBitmap; protected int realWidth, realHeight; public Texture Texture { get { return uploadTexture; } } public PBuffer() : base() { isBindable = false; } protected static int FindNextPOTD(int x) { for(int i = 0; i < 32; i++) { int p = 1<<i; if(p>=x) return p; } return x; } public override void CreateContext(IntPtr hDC, int width, int height, int ColorBits, int ZBufferBits, int StencilBits) { CreateContext(hDC, width, height, ColorBits, ZBufferBits, StencilBits, isBindable, TextureFilter.Linear, TextureFilter.Linear); } public virtual void CreateContext(IntPtr hDC, int width, int height, int ColorBits, int ZBufferBits, int StencilBits, bool isBindable) { CreateContext(hDC, width, height, ColorBits, ZBufferBits, StencilBits, isBindable, TextureFilter.Linear, TextureFilter.Linear); } public virtual void CreateContext(IntPtr hDC, int width, int height, int ColorBits, int ZBufferBits, int StencilBits, bool isBindable, TextureFilter magFilter, TextureFilter minFilter) { if(hDC == IntPtr.Zero) { hDC = Wgl.wglGetCurrentDC(); } this.hDC = hDC; this.isBindable = isBindable; this.width = width; this.height = height; hRC = Wgl.wglGetCurrentContext(); const int MAX_PBUFFER_PFD_ATTRIBS = 50; const int MAX_PBUFFER_PB_ATTRIBS = 50; const int MAX_PBUFFER_PFD_FORMATS = 50; int [] iattributes = new int[2*MAX_PBUFFER_PFD_ATTRIBS]; float [] fattributes = new float[2*MAX_PBUFFER_PFD_ATTRIBS]; int [] pbattributes = new int[2*MAX_PBUFFER_PB_ATTRIBS]; //int nfattribs = 0; int niattribs = 0; int npbattribs = 0; for(int i = 0; i < 2*MAX_PBUFFER_PFD_ATTRIBS; i++ ) { iattributes[i] = 0; pbattributes[i] = 0; fattributes[i] = 0; } /*iattributes[2*niattribs ] = Wgl.WGL_SUPPORT_OPENGL_ARB; iattributes[2*niattribs+1] = Gl.GL_TRUE; niattribs++;*/ iattributes[2*niattribs ] = Wgl.WGL_DRAW_TO_PBUFFER_ARB; iattributes[2*niattribs+1] = Gl.GL_TRUE; niattribs++; if(isBindable) { iattributes[2*niattribs ] = ((ColorBits>24)?Wgl.WGL_BIND_TO_TEXTURE_RGBA_ARB:Wgl.WGL_BIND_TO_TEXTURE_RGB_ARB); iattributes[2*niattribs+1] = Gl.GL_TRUE; niattribs++; } iattributes[2*niattribs ] = Wgl.WGL_DEPTH_BITS_ARB; iattributes[2*niattribs+1] = ZBufferBits; niattribs++; iattributes[2*niattribs ] = Wgl.WGL_STENCIL_BITS_ARB; iattributes[2*niattribs+1] = StencilBits; niattribs++; //if(isBindable) //{ iattributes[2*niattribs ] = Wgl.WGL_RED_BITS_ARB; iattributes[2*niattribs+1] = 8; niattribs++; iattributes[2*niattribs ] = Wgl.WGL_GREEN_BITS_ARB; iattributes[2*niattribs+1] = 8; niattribs++; iattributes[2*niattribs ] = Wgl.WGL_BLUE_BITS_ARB; iattributes[2*niattribs+1] = 8; niattribs++; iattributes[2*niattribs ] = Wgl.WGL_ALPHA_BITS_ARB; iattributes[2*niattribs+1] = ((ColorBits==32)?8:0); niattribs++; /* } else {*/ iattributes[2*niattribs ] = Wgl.WGL_COLOR_BITS_ARB; iattributes[2*niattribs+1] = ColorBits; niattribs++; //} int [] pformat = new int[MAX_PBUFFER_PFD_FORMATS]; uint nformats; if(Ext.wglChoosePixelFormatARB(hDC, iattributes, fattributes, MAX_PBUFFER_PFD_FORMATS, pformat, out nformats) == 0) { throw new Exception("Couldn't find a suitable pixel format: pbuffer creation error"); } if(nformats == 0) { throw new Exception("Couldn't find a suitable pixel format: PBuffer creation error"); } pbattributes[2*npbattribs ] = Wgl.WGL_PBUFFER_LARGEST_ARB; pbattributes[2*npbattribs+1] = Gl.GL_FALSE; npbattribs++; if(isBindable) { pbattributes[2*npbattribs ] = Wgl.WGL_TEXTURE_TARGET_ARB; pbattributes[2*npbattribs+1] = Wgl.WGL_TEXTURE_2D_ARB; npbattribs++; pbattributes[2*npbattribs ] = Wgl.WGL_TEXTURE_FORMAT_ARB; pbattributes[2*npbattribs+1] = Wgl.WGL_TEXTURE_RGBA_ARB; npbattribs++; pbattributes[2*npbattribs ] = Wgl.WGL_MIPMAP_TEXTURE_ARB; pbattributes[2*npbattribs+1] = Gl.GL_FALSE; npbattribs++; } //realWidth = FindNextPOTD(width); //realHeight = FindNextPOTD(height); realWidth = width; realHeight = height; hPBuffer = Ext.wglCreatePbufferARB(hDC, pformat[0], realWidth, realHeight, pbattributes); hPBufferDC = Ext.wglGetPbufferDCARB(hPBuffer); hPBufferRC = Wgl.wglCreateContext(hPBufferDC); Wgl.wglShareLists(hRC, hPBufferRC); Ext.wglQueryPbufferARB( hPBuffer, Wgl.WGL_PBUFFER_WIDTH_ARB, out this.realWidth); Ext.wglQueryPbufferARB( hPBuffer, Wgl.WGL_PBUFFER_HEIGHT_ARB, out this.realHeight); if(!isBindable) { // Create a texture for uploading int tID = 0; textureBitmap = new Bmp("PBuffer Internal Texture Bitmap"); textureBitmap.CreateBlank(realWidth, realHeight, ColorBits); textureBitmap.UsesMipmaps = false; textureBitmap.MagFilter = magFilter; textureBitmap.MinFilter = minFilter; textureBitmap.TileType[0] = TextureTileTypes.ClampToEdge; textureBitmap.TileType[1] = TextureTileTypes.ClampToEdge; textureBitmap.InitializeOnHardware(ref tID); uploadTexture = new Texture("PBuffer Internal Texture",textureBitmap); // Correct POTD //width = this.width = textureBitmap.Width; //height = this.height = textureBitmap.Height; } else { int tID = 0; textureBitmap = new Bmp("PBuffer Internal Texture Bitmap"); textureBitmap.CreateBlank(realWidth, realHeight, ColorBits); textureBitmap.UsesMipmaps = false; textureBitmap.MagFilter = magFilter; textureBitmap.MinFilter = minFilter; textureBitmap.TileType[0] = TextureTileTypes.ClampToEdge; textureBitmap.TileType[1] = TextureTileTypes.ClampToEdge; int w, h; w = textureBitmap.Width; h = textureBitmap.Height; for(int x = 0; x < w; x++) { for(int y = 0; y < h; y++) { textureBitmap.Data[x*(ColorBits/8)+y*w*(ColorBits/8)] = (byte)((x*y)%256); textureBitmap.Data[x*(ColorBits/8)+y*w*(ColorBits/8)+1] = (byte)((x*y)%256); textureBitmap.Data[x*(ColorBits/8)+y*w*(ColorBits/8)+2] = (byte)((x*y)%256); textureBitmap.Data[x*(ColorBits/8)+y*w*(ColorBits/8)+3] = (byte)((x*y)%256); } } textureBitmap.InitializeOnHardware(ref tID); uploadTexture = new Texture("PBuffer Internal Texture",textureBitmap); // uploadTexture = new BlankTexture("PBuffer Internal Bindable Texture"); } initialized = true; MakeCurrent(); Gl.glClearColor(0,0,0,1); Gl.glClear(Gl.GL_COLOR_BUFFER_BIT|Gl.GL_DEPTH_BUFFER_BIT); ReleaseCurrent(); ContextHelper.MakeCurrent(hDC, hRC); } public override void MakeCurrent() { CheckInitialized(); lastDC = ContextHelper.CurrentDC; lastRC = ContextHelper.CurrentRC; if(isBindable) { if(!isLocked) { uploadTexture.SetTexture(); Ext.wglReleaseTexImageARB(this.HPBuffer, Wgl.WGL_FRONT_LEFT_ARB); } isLocked = true; } ContextHelper.MakeCurrent(hPBufferDC, hPBufferRC); } public void ReleaseCurrent() { ReleaseCurrent(true); } public void ReleaseCurrent(bool uploadFrame) { CheckInitialized(); if(!isBindable) { if(uploadFrame) { ((Bmp)uploadTexture.Bitmap).CopyFrameToHardware(uploadTexture.Bitmap.TextureID, width, height); } } ContextHelper.MakeCurrent(lastDC, lastRC); if(isBindable) { if(isLocked) { uploadTexture.SetTexture(); Ext.wglBindTexImageARB(this.HPBuffer, Wgl.WGL_FRONT_LEFT_ARB); } isLocked = false; } } public void Bind() { CheckInitialized(); if(!isBindable || (isBindable && !isLocked)) { uploadTexture.SetTexture(); if(isBindable) Ext.wglBindTexImageARB(this.HPBuffer, Wgl.WGL_FRONT_LEFT_ARB); } } public void Unbind() { CheckInitialized(); if(isBindable && !isLocked) { Ext.wglReleaseTexImageARB(this.HPBuffer, Wgl.WGL_FRONT_LEFT_ARB); } } } }
pbuffer.cs - 9.6 KB