/// <summary> /// Detect allowed FBO formats /// </summary> private void _detectFBOFormats() { // Try all formats, and report which ones work as target int fb, tid; int old_drawbuffer, old_readbuffer; int target = Gl.GL_TEXTURE_2D; Gl.glGetIntegerv(Gl.GL_DRAW_BUFFER, out old_drawbuffer); Gl.glGetIntegerv(Gl.GL_READ_BUFFER, out old_readbuffer); for (int x = 0; x < (int)PixelFormat.Count; ++x) { this._props[x].Valid = false; // Fetch GL format token int fmt = GLPixelUtil.GetGLInternalFormat((PixelFormat)x); if (fmt == Gl.GL_NONE && x != 0) { continue; } // No test for compressed formats if (PixelUtil.IsCompressed((PixelFormat)x)) { continue; } // Buggy ATI cards *crash* on non-RGB(A) formats int[] depths = PixelUtil.GetBitDepths((PixelFormat)x); if (fmt != Gl.GL_NONE && this._atiMode && (depths[0] == 0 || depths[1] == 0 || depths[2] == 0)) { continue; } // Buggy NVidia Drivers fail on 32Bit FP formats on Windows. if (PixelUtil.IsFloatingPoint((PixelFormat)x) && PlatformManager.IsWindowsOS && !this._atiMode) { continue; } // Create and attach framebuffer Gl.glGenFramebuffersEXT(1, out fb); Gl.glBindFramebufferEXT(Gl.GL_FRAMEBUFFER_EXT, fb); if (fmt != Gl.GL_NONE) { // Create and attach texture Gl.glGenTextures(1, out tid); Gl.glBindTexture(target, tid); // Set some default parameters so it won't fail on NVidia cards Gl.glTexParameteri(target, Gl.GL_TEXTURE_MAX_LEVEL, 0); Gl.glTexParameteri(target, Gl.GL_TEXTURE_MIN_FILTER, Gl.GL_NEAREST); Gl.glTexParameteri(target, Gl.GL_TEXTURE_MAG_FILTER, Gl.GL_NEAREST); Gl.glTexParameteri(target, Gl.GL_TEXTURE_WRAP_S, Gl.GL_CLAMP_TO_EDGE); Gl.glTexParameteri(target, Gl.GL_TEXTURE_WRAP_T, Gl.GL_CLAMP_TO_EDGE); Gl.glTexImage2D(target, 0, fmt, PROBE_SIZE, PROBE_SIZE, 0, Gl.GL_RGBA, Gl.GL_UNSIGNED_BYTE, IntPtr.Zero); Gl.glFramebufferTexture2DEXT(Gl.GL_FRAMEBUFFER_EXT, Gl.GL_COLOR_ATTACHMENT0_EXT, target, tid, 0); } else { // Draw to nowhere -- stencil/depth only tid = 0; Gl.glDrawBuffer(Gl.GL_NONE); Gl.glReadBuffer(Gl.GL_NONE); } // Check status int status = Gl.glCheckFramebufferStatusEXT(Gl.GL_FRAMEBUFFER_EXT); // Ignore status in case of fmt==GL_NONE, because no implementation will accept // a buffer without *any* attachment. Buffers with only stencil and depth attachment // might still be supported, so we must continue probing. if (fmt == Gl.GL_NONE || status == Gl.GL_FRAMEBUFFER_COMPLETE_EXT) { this._props[x].Valid = true; var str = new StringBuilder(); str.AppendFormat("\tFBO {0} depth/stencil support: ", PixelUtil.GetFormatName((PixelFormat)x)); // For each depth/stencil formats for (int depth = 0; depth < this._depthFormats.GetLength(0); ++depth) { if (this._depthFormats[depth] != GL_DEPTH24_STENCIL8_EXT) { // General depth/stencil combination for (int stencil = 0; stencil < this._stencilFormats.GetLength(0); ++stencil) { //LogManager.Instance.Write( "Trying {0} D{1}S{2} ", PixelUtil.GetFormatName( (PixelFormat)x ), _depthBits[ depth ], _stencilBits[ stencil ] ); if (_tryFormat(this._depthFormats[depth], this._stencilFormats[stencil])) { /// Add mode to allowed modes str.AppendFormat("D{0}S{1} ", this._depthBits[depth], this._stencilBits[stencil]); FormatProperties.Mode mode; mode.Depth = depth; mode.Stencil = stencil; this._props[x].Modes.Add(mode); } } } else { // Packed depth/stencil format #if false // Only query packed depth/stencil formats for 32-bit // non-floating point formats (ie not R32!) // Linux nVidia driver segfaults if you query others if (!PlatformManager.IsWindowsOS && (PixelUtil.GetNumElemBits((PixelFormat)x) != 32 || PixelUtil.IsFloatingPoint((PixelFormat)x))) { continue; } #endif if (_tryPackedFormat(this._depthFormats[depth])) { /// Add mode to allowed modes str.AppendFormat("Packed-D{0}S8 ", this._depthBits[depth]); FormatProperties.Mode mode; mode.Depth = depth; mode.Stencil = 0; // unuse this._props[x].Modes.Add(mode); } } } LogManager.Instance.Write(str.ToString()); } // Delete texture and framebuffer Gl.glBindFramebufferEXT(Gl.GL_FRAMEBUFFER_EXT, 0); Gl.glDeleteFramebuffersEXT(1, ref fb); // Workaround for NVIDIA / Linux 169.21 driver problem // see http://www.ogre3d.org/phpBB2/viewtopic.php?t=38037&start=25 Gl.glFinish(); Gl.glDeleteTextures(1, ref tid); } // It seems a bug in nVidia driver: glBindFramebufferEXT should restore // draw and read buffers, but in some unclear circumstances it won't. Gl.glDrawBuffer(old_drawbuffer); Gl.glReadBuffer(old_readbuffer); string fmtstring = ""; for (int x = 0; x < (int)PixelFormat.Count; ++x) { if (this._props[x].Valid) { fmtstring += PixelUtil.GetFormatName((PixelFormat)x) + " "; } } LogManager.Instance.Write("[GL] : Valid FBO targets " + fmtstring); }
public virtual void LoadImages(Image[] images) { if (images.Length < 1) { throw new AxiomException("Cannot load empty vector of images"); } // Set desired texture size and properties from images[0] this.srcWidth = this.width = images[0].Width; this.srcHeight = this.height = images[0].Height; this.srcDepth = this.depth = images[0].Depth; // Get source image format and adjust if required this.srcFormat = images[0].Format; if (this.treatLuminanceAsAlpha && this.srcFormat == PixelFormat.L8) { this.srcFormat = PixelFormat.A8; } if (this.desiredFormat != PixelFormat.Unknown) { // If have desired format, use it this.format = this.desiredFormat; } else { // Get the format according with desired bit depth this.format = PixelUtil.GetFormatForBitDepths(this.srcFormat, this.desiredIntegerBitDepth, this.desiredFloatBitDepth); } // The custom mipmaps in the image have priority over everything var imageMips = images[0].NumMipMaps; if (imageMips > 0) { this.mipmapCount = this.requestedMipmapCount = imageMips; // Disable flag for auto mip generation this.usage &= ~TextureUsage.AutoMipMap; } // Create the texture CreateInternalResources(); // Check if we're loading one image with multiple faces // or a vector of images representing the faces int faces; bool multiImage; // Load from multiple images? if (images.Length > 1) { faces = images.Length; multiImage = true; } else { faces = images[0].NumFaces; multiImage = false; } // Check wether number of faces in images exceeds number of faces // in this texture. If so, clamp it. if (faces > FaceCount) { faces = FaceCount; } // Say what we're doing if (TextureManager.Instance.Verbose) { var msg = new StringBuilder(); msg.AppendFormat("Texture: {0}: Loading {1} faces( {2}, {3}x{4}x{5} ) with", _name, faces, PixelUtil.GetFormatName(images[0].Format), images[0].Width, images[0].Height, images[0].Depth); if (!(this.mipmapsHardwareGenerated && this.mipmapCount == 0)) { msg.AppendFormat(" {0}", this.mipmapCount); } if ((this.usage & TextureUsage.AutoMipMap) == TextureUsage.AutoMipMap) { msg.AppendFormat("{0} generated mipmaps", this.mipmapsHardwareGenerated ? " hardware" : string.Empty); } else { msg.Append(" custom mipmaps"); } msg.AppendFormat(" from {0}.\n\t", multiImage ? "multiple Images" : "an Image"); // Print data about first destination surface var buf = GetBuffer(0, 0); msg.AppendFormat(" Internal format is {0} , {1}x{2}x{3}.", PixelUtil.GetFormatName(buf.Format), buf.Width, buf.Height, buf.Depth); LogManager.Instance.Write(msg.ToString()); } // Main loading loop // imageMips == 0 if the image has no custom mipmaps, otherwise contains the number of custom mips for (var mip = 0; mip <= imageMips; ++mip) { for (var i = 0; i < faces; ++i) { PixelBox src; if (multiImage) { // Load from multiple images src = images[i].GetPixelBox(0, mip); } else { // Load from faces of images[0] src = images[0].GetPixelBox(i, mip); } // Sets to treated format in case is difference src.Format = this.srcFormat; if (this.gamma != 1.0f) { // Apply gamma correction // Do not overwrite original image but do gamma correction in temporary buffer var bufSize = PixelUtil.GetMemorySize(src.Width, src.Height, src.Depth, src.Format); var buff = new byte[bufSize]; var buffer = BufferBase.Wrap(buff); var corrected = new PixelBox(src.Width, src.Height, src.Depth, src.Format, buffer); PixelConverter.BulkPixelConversion(src, corrected); Image.ApplyGamma(corrected.Data, this.gamma, corrected.ConsecutiveSize, PixelUtil.GetNumElemBits(src.Format)); // Destination: entire texture. BlitFromMemory does // the scaling to a power of two for us when needed GetBuffer(i, mip).BlitFromMemory(corrected); } else { // Destination: entire texture. BlitFromMemory does // the scaling to a power of two for us when needed GetBuffer(i, mip).BlitFromMemory(src); } } } // Update size (the final size, not including temp space) Size = FaceCount * PixelUtil.GetMemorySize(this.width, this.height, this.depth, this.format); }
private bool _checkVertexTextureFormats(D3D9RenderWindow renderWindow) { var anySupported = false; var bbSurf = (D3D9.Surface[])renderWindow["DDBACKBUFFER"]; var bbSurfDesc = bbSurf[0].Description; for (var pf = PixelFormat.L8; pf < PixelFormat.Count; ++pf) { var fmt = D3D9Helper.ConvertEnum(D3D9Helper.GetClosestSupported(pf)); if ( !this._pD3D.CheckDeviceFormat(this._activeD3DDriver.AdapterNumber, D3D9.DeviceType.Hardware, bbSurfDesc.Format, D3D9.Usage.QueryVertexTexture, D3D9.ResourceType.Texture, fmt)) { continue; } // cool, at least one supported anySupported = true; LogManager.Instance.Write("D3D9: Vertex texture format supported - {0}", PixelUtil.GetFormatName(pf)); } return(anySupported); }
protected virtual void LoadImages(List <Image> images) { Debug.Assert(images.Count >= 1); if (isLoaded) { log.InfoFormat("Unloading image: {0}", name); Unload(); } srcWidth = width = images[0].Width; srcHeight = height = images[0].Height; srcDepth = depth = images[0].Depth; if (hasAlpha && images[0].Format == PixelFormat.L8) { format = PixelFormat.A8; srcBpp = 8; } else { this.Format = images[0].Format; } if (finalBpp == 16) { switch (format) { case PixelFormat.R8G8B8: case PixelFormat.X8R8G8B8: format = PixelFormat.R5G6B5; break; case PixelFormat.B8G8R8: case PixelFormat.X8B8G8R8: format = PixelFormat.B5G6R5; break; case PixelFormat.A8R8G8B8: case PixelFormat.R8G8B8A8: case PixelFormat.A8B8G8R8: case PixelFormat.B8G8R8A8: format = PixelFormat.A4R4G4B4; break; default: // use the original format break; } } // The custom mipmaps in the image have priority over everything int imageMips = images[0].NumMipMaps; if (imageMips > 0) { numMipmaps = imageMips; usage &= ~TextureUsage.AutoMipMap; } // Create the texture CreateInternalResources(); // Check if we're loading one image with multiple faces // or a vector of images representing the faces int faces; bool multiImage; // Load from multiple images? if (images.Count > 1) { faces = images.Count; multiImage = true; } else { faces = images[0].NumFaces; multiImage = false; } // Check wether number of faces in images exceeds number of faces // in this texture. If so, clamp it. if (faces > this.NumFaces) { faces = this.NumFaces; } // Say what we're doing log.InfoFormat("Texture: {0}: Loading {1} faces({2},{3}x{4}x{5})", name, faces, PixelUtil.GetFormatName(images[0].Format), images[0].Width, images[0].Height, images[0].Depth); #if NOT // crazy ogre logging if (!(mMipmapsHardwareGenerated && mNumMipmaps == 0)) { str << mNumMipmaps; } if (mUsage & TU_AUTOMIPMAP) { if (mMipmapsHardwareGenerated) { str << " hardware"; } str << " generated mipmaps"; } else { str << " custom mipmaps"; } if (multiImage) { str << " from multiple Images."; } else { str << " from Image."; } // Scoped { // Print data about first destination surface HardwarePixelBufferSharedPtr buf = getBuffer(0, 0); str << " Internal format is " << PixelUtil::getFormatName(buf->getFormat()) << "," << buf->getWidth() << "x" << buf->getHeight() << "x" << buf->getDepth() << "."; } LogManager::getSingleton().logMessage( LML_NORMAL, str.str()); #endif // Main loading loop // imageMips == 0 if the image has no custom mipmaps, otherwise contains the number of custom mips for (int mip = 0; mip <= imageMips; ++mip) { for (int i = 0; i < faces; ++i) { PixelBox src; if (multiImage) { // Load from multiple images src = images[i].GetPixelBox(0, mip); } else { // Load from faces of images[0] src = images[0].GetPixelBox(i, mip); if (hasAlpha && src.Format == PixelFormat.L8) { src.Format = PixelFormat.A8; } } if (gamma != 1.0f) { // Apply gamma correction // Do not overwrite original image but do gamma correction in temporary buffer IntPtr buffer = Marshal.AllocHGlobal(PixelUtil.GetMemorySize(src.Width, src.Height, src.Depth, src.Format)); try { PixelBox corrected = new PixelBox(src.Width, src.Height, src.Depth, src.Format, buffer); PixelUtil.BulkPixelConversion(src, corrected); Image.ApplyGamma(corrected.Data, gamma, corrected.ConsecutiveSize, PixelUtil.GetNumElemBits(src.Format)); // Destination: entire texture. BlitFromMemory does the scaling to // a power of two for us when needed GetBuffer(i, mip).BlitFromMemory(corrected); } finally { Marshal.FreeHGlobal(buffer); } } else { // Destination: entire texture. BlitFromMemory does the scaling to // a power of two for us when needed GetBuffer(i, mip).BlitFromMemory(src); } } } // Update size (the final size, not including temp space) size = this.NumFaces * PixelUtil.GetMemorySize(width, height, depth, format); isLoaded = true; }
/// <summary> /// Detect which internal formats are allowed as RTT Also detect what combinations of stencil and depth are allowed with this interal format. /// </summary> private void DetectFBOFormats() { //Try all formats, and report which ones work as target int fb = 0, tid = 0; GLenum target = GLenum.Texture2D; for (int x = 0; x < (int)PixelFormat.Count; x++) { this.props[x].Valid = false; //Fetch gl format token var fmt = GLES2PixelUtil.GetGLInternalFormat((PixelFormat)x); if ((fmt == GLenum.None) && (x != 0)) { continue; } //No test for compressed formats if (PixelUtil.IsCompressed((PixelFormat)x)) { continue; } //Create and attach framebuffer GL.GenFramebuffers(1, ref fb); GL.BindFramebuffer(GLenum.Framebuffer, fb); if (fmt != GLenum.None) { //Create and attach texture GL.GenTextures(1, ref tid); GL.BindTexture(target, tid); //Set some default parameters GL.TexParameter(target, GLenum.TextureMinFilter, (int)GLenum.Nearest); GL.TexParameter(target, GLenum.TextureMagFilter, (int)GLenum.Nearest); GL.TexParameter(target, GLenum.TextureWrapS, (int)GLenum.ClampToEdge); GL.TexParameter(target, GLenum.TextureWrapT, (int)GLenum.ClampToEdge); GL.TexImage2D(target, 0, (int)fmt, PROBE_SIZE, PROBE_SIZE, 0, fmt, GLES2PixelUtil.GetGLOriginDataType((PixelFormat)x), IntPtr.Zero); GL.FramebufferTexture2D(GLenum.Framebuffer, GLenum.ColorAttachment0, target, tid, 0); } //Check status GLenum status = GL.CheckFramebufferStatus(GLenum.Framebuffer); // Ignore status in case of fmt==GL_NONE, because no implementation will accept // a buffer without *any* attachment. Buffers with only stencil and depth attachment // might still be supported, so we must continue probing. if (fmt == GLenum.None || status == GLenum.FramebufferComplete) { this.props[x].Valid = true; var sb = new StringBuilder(); sb.Append("FBO " + PixelUtil.GetFormatName((PixelFormat)x) + " depth/stencil support: "); //For each depth/stencil formats for (int depth = 0; depth < DepthFormatCount; depth++) { if (depthFormats[depth] != GLenum.Depth24Stencil8Oes) { //General depth/stencil combination for (int stencil = 0; stencil < StencilFormatCount; stencil++) { if (this.TryFormat(depthFormats[depth], stencilFormats[stencil])) { //Add mode to allowed modes sb.Append("D" + depthBits[depth] + "S" + stencilBits[stencil] + " "); var mode = new FormatProperties.Mode(); mode.Depth = depth; mode.Stencil = stencil; this.props[x].Modes.Add(mode); } } } else { //Packed depth/stencil format if (this.TryPackedFormat(depthFormats[depth])) { //Add mode to allowed modes sb.Append("Packed-D" + depthBits[depth] + "S" + 8 + " "); var mode = new FormatProperties.Mode(); mode.Depth = depth; mode.Stencil = 0; //unuse this.props[x].Modes.Add(mode); } } } Core.LogManager.Instance.Write(sb.ToString()); } //Delte texture and framebuffer GL.BindFramebuffer(GLenum.Framebuffer, 0); GL.DeleteFramebuffers(1, ref fb); if (fmt != GLenum.None) { GL.DeleteTextures(1, ref tid); } } // Clear any errors GLES2Config.GlClearError(); string fmtstring = string.Empty; for (int x = 0; x < (int)PixelFormat.Count; x++) { if (this.props[x].Valid) { fmtstring += PixelUtil.GetFormatName((PixelFormat)x) + " "; } Core.LogManager.Instance.Write("[GLES2] : Valid FBO targets " + fmtstring); } }
/// <summary> /// Detect which internal formats are allowed as RTT Also detect what combinations of stencil and depth are allowed with this internal format. /// </summary> private void DetectFBOFormats() { // Try all formats, and report which ones work as target int fb = 0, tid = 0; All target = All.Texture2D; for (int x = 0; x < (int)Media.PixelFormat.Count; x++) { LogManager.Instance.Write("[GLES] [DEBUG] testing PixelFormat : {0}", (Media.PixelFormat)x); this._props[x] = new FormatProperties(); this._props[x].Modes = new List <FormatProperties.Mode>(); this._props[x].IsValid = false; // Fetch GL format token All fmt = GLESPixelUtil.GetClosestGLInternalFormat((Media.PixelFormat)x); LogManager.Instance.Write("[GLES] [DEBUG] fmt={0}", fmt); if (fmt == All.Zero && x != 0) { continue; } // No test for compressed formats if (PixelUtil.IsCompressed((Media.PixelFormat)x)) { continue; } // Create and attach framebuffer OpenGLOES.GenRenderbuffers(1, ref fb); GLESConfig.GlCheckError(this); OpenGLOES.BindFramebuffer(All.FramebufferOes, fb); GLESConfig.GlCheckError(this); if (fmt != All.Zero) { // Create and attach texture OpenGL.GenTextures(1, ref tid); GLESConfig.GlCheckError(this); OpenGL.BindTexture(target, tid); GLESConfig.GlCheckError(this); // Set some default parameters OpenGL.TexParameterx(target, All.TextureMinFilter, (int)All.LinearMipmapNearest); GLESConfig.GlCheckError(this); OpenGL.TexParameterx(target, All.TextureMagFilter, (int)All.Nearest); GLESConfig.GlCheckError(this); OpenGL.TexParameterx(target, All.TextureWrapS, (int)All.ClampToEdge); GLESConfig.GlCheckError(this); OpenGL.TexParameterx(target, All.TextureWrapT, (int)All.ClampToEdge); GLESConfig.GlCheckError(this); OpenGL.TexImage2D(target, 0, (int)fmt, ProbeSize, ProbeSize, 0, fmt, All.UnsignedByte, IntPtr.Zero); GLESConfig.GlCheckError(this); OpenGLOES.FramebufferTexture2D(All.FramebufferOes, All.ColorAttachment0Oes, target, tid, 0); GLESConfig.GlCheckError(this); } // Check status All status = OpenGLOES.CheckFramebufferStatus(All.FramebufferOes); GLESConfig.GlCheckError(this); LogManager.Instance.Write("[GLES] [DEBUG] status={0}", status); // Ignore status in case of fmt==GL_NONE, because no implementation will accept // a buffer without *any* attachment. Buffers with only stencil and depth attachment // might still be supported, so we must continue probing. if (fmt == 0 || status == All.FramebufferCompleteOes) { this._props[x].IsValid = true; var str = new StringBuilder(); str.Append("FBO " + PixelUtil.GetFormatName((Media.PixelFormat)x) + " depth/stencil support: "); // For each depth/stencil formats for (int depth = 0; depth < DepthFormats.Length; ++depth) { if (DepthFormats[depth] != All.Depth24Stencil8Oes) { // General depth/stencil combination for (int stencil = 0; stencil < StencilFormats.Length; ++stencil) { if (TryFormat(DepthFormats[depth], StencilFormats[stencil])) { /// Add mode to allowed modes str.Append("D" + DepthBits[depth] + "S" + StencilBits[stencil] + " "); var mode = new FormatProperties.Mode(); mode.Depth = depth; mode.Stencil = stencil; this._props[x].Modes.Add(mode); } } //end for stencil } //end if else { // Packed depth/stencil format if (TryPacketFormat(DepthFormats[depth])) { /// Add mode to allowed modes str.Append("Packed-D" + DepthBits[depth] + "S8" + " "); var mode = new FormatProperties.Mode(); mode.Depth = depth; mode.Stencil = 0; //unused this._props[x].Modes.Add(mode); } } } //end for depth LogManager.Instance.Write(str.ToString()); } //end if // Delete texture and framebuffer #if AXIOM_PLATFORM_IPHONE // The screen buffer is 1 on iPhone OpenGLOES.BindFramebuffer(All.FramebufferOes, 1); #else OpenGLOES.BindFramebuffer(All.FramebufferOes, 0); #endif GLESConfig.GlCheckError(this); OpenGLOES.DeleteFramebuffers(1, ref fb); GLESConfig.GlCheckError(this); if (fmt != 0) { OpenGL.DeleteTextures(1, ref tid); } } //end for pixelformat count string fmtstring = string.Empty; for (int x = 0; x < (int)Media.PixelFormat.Count; x++) { if (this._props[x].IsValid) { fmtstring += PixelUtil.GetFormatName((Media.PixelFormat)x); } } LogManager.Instance.Write("[GLES] : Valid FBO targets " + fmtstring); }