public override Media.PixelFormat GetNativeFormat(Graphics.TextureType ttype, Media.PixelFormat format, Graphics.TextureUsage usage) { var caps = Root.Instance.RenderSystem.Capabilities; //Check compressed texture support //if a compressed formt not supported, rever to PixelFormat.A8R8G8B8 if (PixelUtil.IsCompressed(format) && !caps.HasCapability(Graphics.Capabilities.TextureCompressionDXT) && !caps.HasCapability(Graphics.Capabilities.TextureCompressionPVRTC)) { return(PixelFormat.A8R8G8B8); } //if floating point texture not supported, rever to PixelFormat.A8R8G8B8 if (PixelUtil.IsFloatingPoint(format) && !caps.HasCapability(Graphics.Capabilities.TextureFloat)) { return(PixelFormat.A8R8G8B8); } //Check if this is a valid rendertarget format if ((usage & Graphics.TextureUsage.RenderTarget) == Graphics.TextureUsage.RenderTarget) { //Get closest supported alternative //if format is supported it's returned return(GLES2RTTManager.Instance.GetSupportedAlternative(format)); } //Supported return(format); }
protected static void FromD3DLock(PixelBox rval, DX.DataBox lbox) { var bpp = PixelUtil.GetNumElemBytes(rval.Format); var size = 0; if (bpp != 0) { rval.RowPitch = lbox.RowPitch / bpp; rval.SlicePitch = lbox.SlicePitch / bpp; Debug.Assert((lbox.RowPitch % bpp) == 0); Debug.Assert((lbox.SlicePitch % bpp) == 0); size = lbox.RowPitch * rval.Height; } else if (PixelUtil.IsCompressed(rval.Format)) { rval.RowPitch = rval.Width; rval.SlicePitch = rval.Width * rval.Height; size = rval.Width * rval.Height; } else { throw new AxiomException("Invalid pixel format"); } rval.Data = BufferBase.Wrap(lbox.DataPointer, size); }
public override PixelFormat GetNativeFormat(TextureType ttype, PixelFormat format, TextureUsage usage) { // Adjust requested parameters to capabilities RenderSystemCapabilities caps = Root.Instance.RenderSystem.Capabilities; // Check compressed texture support // if a compressed format not supported, revert to PF_A8R8G8B8 if (PixelUtil.IsCompressed(format) && !caps.HasCapability(Capabilities.TextureCompressionDXT)) { return(PixelFormat.A8R8G8B8); } // if floating point textures not supported, revert to PF_A8R8G8B8 if (PixelUtil.IsFloatingPoint(format) && !caps.HasCapability(Capabilities.TextureFloat)) { return(PixelFormat.A8R8G8B8); } // Check if this is a valid rendertarget format if ((usage & TextureUsage.RenderTarget) != 0) { /// Get closest supported alternative /// If mFormat is supported it's returned return(GLRTTManager.Instance.GetSupportedAlternative(format)); } // Supported return(format); }
/// <summary> /// </summary> /// <param name="ttype"> </param> /// <param name="format"> </param> /// <param name="usage"> </param> /// <returns> </returns> public override Media.PixelFormat GetNativeFormat(TextureType ttype, Media.PixelFormat format, TextureUsage usage) { // Adjust requested parameters to capabilities RenderSystemCapabilities caps = Root.Instance.RenderSystem.HardwareCapabilities; #warning check TextureCompressionVTC == RSC_TEXTURE_COMPRESSION_PVRTC // Check compressed texture support // if a compressed format not supported, revert to A8R8G8B8 if (PixelUtil.IsCompressed(format) && !caps.HasCapability(Capabilities.TextureCompressionDXT) && !caps.HasCapability(Capabilities.TextureCompressionVTC)) { return(Media.PixelFormat.A8R8G8B8); } // if floating point textures not supported, revert to A8R8G8B8 if (PixelUtil.IsFloatingPoint(format) && !caps.HasCapability(Capabilities.TextureFloat)) { return(Media.PixelFormat.A8R8G8B8); } // Check if this is a valid rendertarget format if ((usage & TextureUsage.RenderTarget) != 0) { /// Get closest supported alternative /// If format is supported it's returned return(GLESRTTManager.Instance.GetSupportedAlternative(format)); } // Supported return(format); }
protected override void download(PixelBox data) { if (data.Width != Width || data.Height != Height || data.Depth != Depth) { throw new ArgumentException("only download of entire buffer is supported by GL"); } Gl.glBindTexture(this._target, this._textureId); if (PixelUtil.IsCompressed(data.Format)) { if (data.Format != Format || !data.IsConsecutive) { throw new ArgumentException("Compressed images must be consecutive, in the source format"); } // Data must be consecutive and at beginning of buffer as PixelStorei not allowed // for compressed formate Gl.glGetCompressedTexImageARB(this._faceTarget, this._level, data.Data.Pin()); data.Data.UnPin(); } else { if (data.Width != data.RowPitch) { Gl.glPixelStorei(Gl.GL_PACK_ROW_LENGTH, data.RowPitch); } if (data.Height * data.Width != data.SlicePitch) { Gl.glPixelStorei(Gl.GL_PACK_IMAGE_HEIGHT, (data.SlicePitch / data.Width)); } if (((data.Width * PixelUtil.GetNumElemBytes(data.Format)) & 3) != 0) { // Standard alignment of 4 is not right Gl.glPixelStorei(Gl.GL_PACK_ALIGNMENT, 1); } // We can only get the entire texture Gl.glGetTexImage(this._faceTarget, this._level, GLPixelUtil.GetGLOriginFormat(data.Format), GLPixelUtil.GetGLOriginDataType(data.Format), data.Data.Pin()); data.Data.UnPin(); // Restore defaults Gl.glPixelStorei(Gl.GL_PACK_ROW_LENGTH, 0); Gl.glPixelStorei(Gl.GL_PACK_IMAGE_HEIGHT, 0); Gl.glPixelStorei(Gl.GL_PACK_ALIGNMENT, 4); } }
protected override void Download(PixelBox data) { #if GL_NV_get_tex_image if (data.Width != Width || data.Height != Height || data.Depth != Depth) { throw new Core.AxiomException("only download of entire buffer is supported by GL"); } GL.BindTexture(this.target, this.textureID); if (PixelUtil.IsCompressed(data.Format)) { if (data.Format != format || !data.IsConsecutive) { throw new Core.AxiomException("Compressed images must be consecutive, in the source format"); } GL.GetCompressedTexImageNV(this.faceTarget, this.level, data.Data); } else { if ((data.Width * PixelUtil.GetNumElemBytes(data.Format) & 3) != 0) { //Standard alignment of 4 is not right GL.PixelStore(Glenum.PackAlignment, 1); } //We can only get the entire texture GL.GetTexImageNV(this.faceTarget, this.level, GLES2PixelUtil.GetGLOriginFormat(data.Format), GLES2PixelUtil.GetGLOriginDataType(data.Format), data.Data); //Restore defaults GL.PixelStore(Glenum.PackAlignment, 4); } #else throw new Core.AxiomException("Downloading texture buffers is not supported by OpenGL ES"); #endif }
protected override void upload(PixelBox box) { Gl.glBindTexture(this._target, this._textureId); if (PixelUtil.IsCompressed(box.Format)) { if (box.Format != Format || !box.IsConsecutive) { throw new ArgumentException("Compressed images must be consecutive, in the source format"); } int format = GLPixelUtil.GetClosestGLInternalFormat(Format); // Data must be consecutive and at beginning of buffer as PixelStorei not allowed // for compressed formats switch (this._target) { case Gl.GL_TEXTURE_1D: Gl.glCompressedTexSubImage1DARB(Gl.GL_TEXTURE_1D, this._level, box.Left, box.Width, format, box.ConsecutiveSize, box.Data.Pin()); box.Data.UnPin(); break; case Gl.GL_TEXTURE_2D: case Gl.GL_TEXTURE_CUBE_MAP: Gl.glCompressedTexSubImage2DARB(this._faceTarget, this._level, box.Left, box.Top, box.Width, box.Height, format, box.ConsecutiveSize, box.Data.Pin()); box.Data.UnPin(); break; case Gl.GL_TEXTURE_3D: Gl.glCompressedTexSubImage3DARB(Gl.GL_TEXTURE_3D, this._level, box.Left, box.Top, box.Front, box.Width, box.Height, box.Depth, format, box.ConsecutiveSize, box.Data.Pin()); box.Data.UnPin(); break; } } else if (this._softwareMipmap) { int internalFormat; Gl.glGetTexLevelParameteriv(this._target, this._level, Gl.GL_TEXTURE_INTERNAL_FORMAT, out internalFormat); if (box.Width != box.RowPitch) { Gl.glPixelStorei(Gl.GL_UNPACK_ROW_LENGTH, box.RowPitch); } if (box.Height * box.Width != box.SlicePitch) { Gl.glPixelStorei(Gl.GL_UNPACK_IMAGE_HEIGHT, (box.SlicePitch / box.Width)); } Gl.glPixelStorei(Gl.GL_UNPACK_ALIGNMENT, 1); switch (this._target) { case Gl.GL_TEXTURE_1D: Glu.gluBuild1DMipmaps(Gl.GL_TEXTURE_1D, internalFormat, box.Width, GLPixelUtil.GetGLOriginFormat(box.Format), GLPixelUtil.GetGLOriginDataType(box.Format), box.Data.Pin()); box.Data.UnPin(); break; case Gl.GL_TEXTURE_2D: case Gl.GL_TEXTURE_CUBE_MAP: Glu.gluBuild2DMipmaps(this._faceTarget, internalFormat, box.Width, box.Height, GLPixelUtil.GetGLOriginFormat(box.Format), GLPixelUtil.GetGLOriginDataType(box.Format), box.Data.Pin()); box.Data.UnPin(); break; case Gl.GL_TEXTURE_3D: /* Requires GLU 1.3 which is harder to come by than cards doing hardware mipmapping * Most 3D textures don't need mipmaps? * Gl.gluBuild3DMipmaps( * Gl.GL_TEXTURE_3D, internalFormat, * box.getWidth(), box.getHeight(), box.getDepth(), * GLPixelUtil.getGLOriginFormat(box.format), GLPixelUtil.getGLOriginDataType(box.format), * box.box); */ Gl.glTexImage3D(Gl.GL_TEXTURE_3D, 0, internalFormat, box.Width, box.Height, box.Depth, 0, GLPixelUtil.GetGLOriginFormat(box.Format), GLPixelUtil.GetGLOriginDataType(box.Format), box.Data.Pin()); box.Data.UnPin(); break; } } else { if (box.Width != box.RowPitch) { Gl.glPixelStorei(Gl.GL_UNPACK_ROW_LENGTH, box.RowPitch); } if (box.Height * box.Width != box.SlicePitch) { Gl.glPixelStorei(Gl.GL_UNPACK_IMAGE_HEIGHT, (box.SlicePitch / box.Width)); } if (((box.Width * PixelUtil.GetNumElemBytes(box.Format)) & 3) != 0) { // Standard alignment of 4 is not right Gl.glPixelStorei(Gl.GL_UNPACK_ALIGNMENT, 1); } switch (this._target) { case Gl.GL_TEXTURE_1D: Gl.glTexSubImage1D(Gl.GL_TEXTURE_1D, this._level, box.Left, box.Width, GLPixelUtil.GetGLOriginFormat(box.Format), GLPixelUtil.GetGLOriginDataType(box.Format), box.Data.Pin()); box.Data.UnPin(); break; case Gl.GL_TEXTURE_2D: case Gl.GL_TEXTURE_CUBE_MAP: Gl.glTexSubImage2D(this._faceTarget, this._level, box.Left, box.Top, box.Width, box.Height, GLPixelUtil.GetGLOriginFormat(box.Format), GLPixelUtil.GetGLOriginDataType(box.Format), box.Data.Pin()); box.Data.UnPin(); break; case Gl.GL_TEXTURE_3D: Gl.glTexSubImage3D(Gl.GL_TEXTURE_3D, this._level, box.Left, box.Top, box.Front, box.Width, box.Height, box.Depth, GLPixelUtil.GetGLOriginFormat(box.Format), GLPixelUtil.GetGLOriginDataType(box.Format), box.Data.Pin()); box.Data.UnPin(); break; } } // Restore defaults Gl.glPixelStorei(Gl.GL_UNPACK_ROW_LENGTH, 0); Gl.glPixelStorei(Gl.GL_UNPACK_IMAGE_HEIGHT, 0); Gl.glPixelStorei(Gl.GL_UNPACK_ALIGNMENT, 4); }
/// <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); }
protected void BlitFromMemory(PixelBox src, BasicBox dstBox, BufferResources dstBufferResources) { // for scoped deletion of conversion buffer var converted = src; var bufSize = 0; // convert to pixelbuffer's native format if necessary if (D3D9Helper.ConvertEnum(src.Format) == D3D9.Format.Unknown) { bufSize = PixelUtil.GetMemorySize(src.Width, src.Height, src.Depth, Format); var newBuffer = new byte[bufSize]; using (var data = BufferBase.Wrap(newBuffer)) { converted = new PixelBox(src.Width, src.Height, src.Depth, Format, data); } PixelConverter.BulkPixelConversion(src, converted); } int rowWidth = 0; if (PixelUtil.IsCompressed(converted.Format)) { rowWidth = converted.RowPitch / 4; // D3D wants the width of one row of cells in bytes if (converted.Format == PixelFormat.DXT1) { // 64 bits (8 bytes) per 4x4 block rowWidth *= 8; } else { // 128 bits (16 bytes) per 4x4 block rowWidth *= 16; } } else { rowWidth = converted.RowPitch * PixelUtil.GetNumElemBytes(converted.Format); } if (dstBufferResources.Surface != null) { var srcRect = ToD3DRectangle(converted); var destRect = ToD3DRectangle(dstBox); bufSize = PixelUtil.GetMemorySize(converted.Width, converted.Height, converted.Depth, converted.Format); var data = new byte[bufSize]; using (var dest = BufferBase.Wrap(data)) { Memory.Copy(converted.Data, dest, bufSize); } try { D3D9.Surface.FromMemory(dstBufferResources.Surface, data, D3D9.Filter.Default, 0, D3D9Helper.ConvertEnum(converted.Format), rowWidth, srcRect, destRect); } catch (Exception e) { throw new AxiomException("D3D9.Surface.FromMemory failed in D3D9HardwarePixelBuffer.BlitFromMemory", e); } } else if (dstBufferResources.Volume != null) { var srcBox = ToD3DBox(converted); var destBox = ToD3DBox(dstBox); var sliceWidth = 0; if (PixelUtil.IsCompressed(converted.Format)) { sliceWidth = converted.SlicePitch / 16; // D3D wants the width of one slice of cells in bytes if (converted.Format == PixelFormat.DXT1) { // 64 bits (8 bytes) per 4x4 block sliceWidth *= 8; } else { // 128 bits (16 bytes) per 4x4 block sliceWidth *= 16; } } else { sliceWidth = converted.SlicePitch * PixelUtil.GetNumElemBytes(converted.Format); } bufSize = PixelUtil.GetMemorySize(converted.Width, converted.Height, converted.Depth, converted.Format); var data = new byte[bufSize]; using (var dest = BufferBase.Wrap(data)) { Memory.Copy(converted.Data, dest, bufSize); } //TODO note sliceWidth and rowWidth are ignored.. D3D9.ImageInformation info; try { //D3D9.D3DX9.LoadVolumeFromMemory() not accessible 'cause D3D9.D3DX9 static class is not public D3D9.Volume.FromFileInMemory(dstBufferResources.Volume, data, D3D9.Filter.Default, 0, srcBox, destBox, null, out info); } catch (Exception e) { throw new AxiomException("D3D9.Volume.FromFileInMemory failed in D3D9HardwarePixelBuffer.BlitFromMemory", e); } } if (this.doMipmapGen) { GenMipmaps(dstBufferResources.MipTex); } }
protected override void createInternalResources() { //Conver to nearest power of two size if require this.width = GLES2PixelUtil.OptionalPO2(Width); this.height = GLES2PixelUtil.OptionalPO2(Height); this.depth = GLES2PixelUtil.OptionalPO2(Depth); //Adjust format if required format = TextureManager.Instance.GetNativeFormat(textureType, Format, usage); //Check requested number of mipmaps int maxMips = GLES2PixelUtil.GetMaxMipmaps(this.width, this.height, this.depth, format); if (PixelUtil.IsCompressed(format) && (mipmapCount == 0)) { requestedMipmapCount = 0; } mipmapCount = requestedMipmapCount; if (mipmapCount > maxMips) { mipmapCount = maxMips; } //Generate texture name GL.GenTextures(1, ref this.textureID); GLES2Config.GlCheckError(this); //Set texture name GL.BindTexture(this.GLES2TextureTarget, this.textureID); GLES2Config.GlCheckError(this); //Set some misc default parameters, tehse can of course be changed later GL.TexParameter(this.GLES2TextureTarget, GLenum.TextureMinFilter, (int)GLenum.Nearest); GLES2Config.GlCheckError(this); GL.TexParameter(this.GLES2TextureTarget, GLenum.TextureMagFilter, (int)GLenum.Nearest); GLES2Config.GlCheckError(this); GL.TexParameter(this.GLES2TextureTarget, GLenum.TextureWrapS, (int)GLenum.ClampToEdge); GLES2Config.GlCheckError(this); GL.TexParameter(this.GLES2TextureTarget, GLenum.TextureWrapT, (int)GLenum.ClampToEdge); GLES2Config.GlCheckError(this); //If we can do automip generation and the user desires this, do so mipmapsHardwareGenerated = Root.Instance.RenderSystem.Capabilities.HasCapability(Capabilities.HardwareMipMaps) && !PixelUtil.IsCompressed(format); //Ogre FIXME: For some reason this is crashing on iOS 5 #if !MONOTOUCH && ANDROID if ((usage & TextureUsage.AutoMipMap) == TextureUsage.AutoMipMap && requestedMipmapCount > 0 && mipmapsHardwareGenerated && (textureType != Graphics.TextureType.CubeMap)) { GL.GenerateMipmap(this.GLES2TextureTarget); GLES2Config.GlCheckError(this); } #endif //Allocate internal buffer so that glTexSubImageXD can be used //INternal format GLenum glformat = GLES2PixelUtil.GetClosestGLInternalFormat(format, hwGamma); GLenum dataType = GLES2PixelUtil.GetGLOriginDataType(format); int width = Width; int height = Height; int depth = Depth; if (PixelUtil.IsCompressed(format)) { //Compressed formats int size = PixelUtil.GetMemorySize(Width, Height, Depth, Format); // Provide temporary buffer filled with zeroes as glCompressedTexImageXD does not // accept a 0 pointer like normal glTexImageXD // Run through this process for every mipmap to pregenerate mipmap pyramid var tmpData = new IntPtr(); for (int mip = 0; mip < mipmapCount; mip++) { size = PixelUtil.GetMemorySize(width, height, depth, Format); switch (textureType) { case TextureType.OneD: case TextureType.TwoD: GL.CompressedTexImage2D(GLenum.Texture2D, mip, glformat, width, height, 0, size, tmpData); GLES2Config.GlCheckError(this); break; case TextureType.CubeMap: for (int face = 0; face < 6; face++) { GL.CompressedTexImage2D((GLenum)((int)GLenum.TextureCubeMapPositiveX + face), mip, glformat, width, height, 0, size, tmpData); GLES2Config.GlCheckError(this); } break; case TextureType.ThreeD: break; default: break; } if (width > 1) { width = width / 2; } if (height > 1) { height = height / 2; } if (depth > 1) { depth = depth / 2; } } tmpData = IntPtr.Zero; } else { //Run through this process to pregenerate mipmap pyramid for (int mip = 0; mip < mipmapCount; mip++) { //Normal formats switch (textureType) { case TextureType.OneD: case TextureType.TwoD: GL.TexImage2D(GLenum.Texture2D, mip, (int)glformat, width, height, 0, glformat, dataType, new IntPtr()); GLES2Config.GlCheckError(this); break; case TextureType.CubeMap: for (int face = 0; face < 6; face++) { GL.TexImage2D(GLenum.TextureCubeMapPositiveX + face, mip, (int)glformat, width, height, 0, glformat, dataType, new IntPtr()); GLES2Config.GlCheckError(this); } break; case TextureType.ThreeD: default: break; } if (width > 1) { width /= 2; } if (height > 1) { height /= 2; } } } this.CreateSurfaceList(); //Get final internal format base.format = this.GetBuffer(0, 0).Format; }
/// <summary> /// </summary> /// <param name="data"> </param> /// <param name="dest"> </param> protected override void Upload(PixelBox data, BasicBox dest) { OpenGL.BindTexture(this._target, this._textureId); GLESConfig.GlCheckError(this); if (PixelUtil.IsCompressed(data.Format)) { if (data.Format != Format || !data.IsConsecutive) { throw new AxiomException("Compressed images must be consecutive, in the source format"); } if (data.Format != Format || !data.IsConsecutive) { throw new AxiomException("Compressed images must be consecutive, in the source format."); } All format = GLESPixelUtil.GetClosestGLInternalFormat(Format); // Data must be consecutive and at beginning of buffer as PixelStorei not allowed // for compressed formats if (dest.Left == 0 && dest.Top == 0) { OpenGL.CompressedTexImage2D(All.Texture2D, this._level, format, dest.Width, dest.Height, 0, data.ConsecutiveSize, data.Data); } else { OpenGL.CompressedTexSubImage2D(All.Texture2D, this._level, dest.Left, dest.Top, dest.Width, dest.Height, format, data.ConsecutiveSize, data.Data); } GLESConfig.GlCheckError(this); } else if (this._softwareMipmap) { if (data.Width != data.RowPitch) { //TODO throw new AxiomException("Unsupported Texture format!"); } if (data.Height * data.Width != data.SlicePitch) { //TODO throw new AxiomException("Unsupported Texture format!"); } OpenGL.PixelStore(All.UnpackAlignment, 1); GLESConfig.GlCheckError(this); BuildMipmaps(data); } else { if (data.Width != data.RowPitch) { //TODO throw new AxiomException("Unsupported Texture format!"); } if (data.Height * data.Width != data.SlicePitch) { //TODO throw new AxiomException("Unsupported Texture format!"); } if (((data.Width * PixelUtil.GetNumElemBytes(data.Format)) & 3) != 0) { // Standard alignment of 4 is not right OpenGL.PixelStore(All.UnpackAlignment, 1); GLESConfig.GlCheckError(this); } All form = GLESPixelUtil.GetGLOriginFormat(data.Format); All pix = GLESPixelUtil.GetGLOriginDataType(data.Format); GLESConfig.GlCheckError(this); GL.TexSubImage2D(this._faceTarget, this._level, dest.Left, dest.Top, dest.Width, dest.Height, GLESPixelUtil.GetGLOriginFormat(data.Format), GLESPixelUtil.GetGLOriginDataType(data.Format), data.Data); GLESConfig.GlCheckError(this); } OpenGL.PixelStore(All.UnpackAlignment, 4); GLESConfig.GlCheckError(this); }
protected override void Upload(PixelBox data, BasicBox dest) { GL.BindTexture(this.target, this.textureID); GLES2Config.GlCheckError(this); if (PixelUtil.IsCompressed(data.Format)) { if (data.Format != format || !data.IsConsecutive) { var glFormat = GLES2PixelUtil.GetClosestGLInternalFormat(format); //Data must be consecutive and at beginning of buffer as PixelStore is not allowed //for compressed formats if (dest.Left == 0 && dest.Top == 0) { GL.CompressedTexImage2D(this.faceTarget, this.level, glFormat, dest.Width, dest.Height, 0, data.ConsecutiveSize, data.Data.Pin()); GLES2Config.GlCheckError(this); } else { GL.CompressedTexSubImage2D(this.faceTarget, this.level, dest.Left, dest.Top, dest.Width, dest.Height, glFormat, data.ConsecutiveSize, data.Data.Pin()); GLES2Config.GlCheckError(this); } } } else if (this.softwareMipmap) { if (data.Width != data.RowPitch) { //Ogre TODO throw new Core.AxiomException("Unsupported texture format"); } if (data.Height * data.Width != data.SlicePitch) { //Ogre TODO throw new Core.AxiomException("Unsupported texture format"); } GL.PixelStore(All.UnpackAlignment, 1); GLES2Config.GlCheckError(this); this.BuildMipmaps(data); } else { if (data.Width != data.RowPitch) { //Ogre TODO throw new Core.AxiomException("Unsupported texture format"); } if (data.Height * data.Width != data.SlicePitch) { //Ogre TODO throw new Core.AxiomException("Unsupported texture format"); } if ((data.Width * PixelUtil.GetNumElemBytes(data.Format) & 3) != 0) { //Standard alignment of 4 is not right GL.PixelStore(All.UnpackAlignment, 1); GLES2Config.GlCheckError(this); } var dataPtr = data.Data.Pin(); GL.TexImage2D(this.faceTarget, this.level, (int)GLES2PixelUtil.GetClosestGLInternalFormat(data.Format), data.Width, data.Height, 0, GLES2PixelUtil.GetGLOriginFormat(data.Format), GLES2PixelUtil.GetGLOriginDataType(data.Format), dataPtr); //GL.TexSubImage2D( this.faceTarget, this.level, dest.Left, dest.Top, dest.Width, dest.Height, GLES2PixelUtil.GetGLOriginFormat( data.Format ), GLES2PixelUtil.GetGLOriginDataType( data.Format ), dataPtr ); data.Data.UnPin(); GLES2Config.GlCheckError(this); } GL.PixelStore(All.UnpackAlignment, 4); GLES2Config.GlCheckError(this); }
/// <summary> /// </summary> protected override void createInternalResources() { // Convert to nearest power-of-two size if required Width = GLESPixelUtil.OptionalPO2(Width); Height = GLESPixelUtil.OptionalPO2(Height); Depth = GLESPixelUtil.OptionalPO2(Depth); //adjust format if required Format = TextureManager.Instance.GetNativeFormat(Graphics.TextureType.TwoD, Format, Usage); // Check requested number of mipmaps int maxMips = GLESPixelUtil.GetMaxMipmaps(Width, Height, Depth, Format); if (PixelUtil.IsCompressed(Format) && _mipmapCount == 0) { RequestedMipmapCount = 0; } _mipmapCount = RequestedMipmapCount; if (_mipmapCount > maxMips) { _mipmapCount = maxMips; } // Generate texture name OpenGL.GenTextures(1, ref this._textureID); GLESConfig.GlCheckError(this); // Set texture type OpenGL.BindTexture(All.Texture2D, this._textureID); GLESConfig.GlCheckError(this); // Set some misc default parameters, these can of course be changed later OpenGL.TexParameter(All.Texture2D, All.TextureMinFilter, (int)All.LinearMipmapNearest); GLESConfig.GlCheckError(this); OpenGL.TexParameter(All.Texture2D, All.TextureMagFilter, (int)All.Nearest); GLESConfig.GlCheckError(this); OpenGL.TexParameter(All.Texture2D, All.TextureWrapS, (int)All.ClampToEdge); GLESConfig.GlCheckError(this); OpenGL.TexParameter(All.Texture2D, All.TextureWrapT, (int)All.ClampToEdge); GLESConfig.GlCheckError(this); // If we can do automip generation and the user desires this, do so MipmapsHardwareGenerated = Root.Instance.RenderSystem.HardwareCapabilities.HasCapability(Capabilities.HardwareMipMaps) && !PixelUtil.IsCompressed(Format); if ((Usage & TextureUsage.AutoMipMap) == TextureUsage.AutoMipMap && RequestedMipmapCount > 0 && MipmapsHardwareGenerated) { OpenGL.TexParameter(All.Texture2D, All.GenerateMipmap, (int)All.True); GLESConfig.GlCheckError(this); } // Allocate internal buffer so that TexSubImageXD can be used // Internal format All format = GLESPixelUtil.GetClosestGLInternalFormat(Format, HardwareGammaEnabled); int width = Width; int height = Height; int depth = Depth; if (PixelUtil.IsCompressed(Format)) { // Compressed formats int size = PixelUtil.GetMemorySize(Width, Height, Depth, Format); // Provide temporary buffer filled with zeroes as glCompressedTexImageXD does not // accept a 0 pointer like normal glTexImageXD // Run through this process for every mipmap to pregenerate mipmap pyramid var tmpData = new byte[size]; IntPtr tmpDataptr = Memory.PinObject(tmpData); for (int mip = 0; mip <= MipmapCount; mip++) { size = PixelUtil.GetMemorySize(Width, Height, Depth, Format); OpenGL.CompressedTexImage2D(All.Texture2D, mip, format, width, height, 0, size, tmpDataptr); GLESConfig.GlCheckError(this); if (width > 1) { width = width / 2; } if (height > 1) { height = height / 2; } if (depth > 1) { depth = depth / 2; } } Memory.UnpinObject(tmpData); } else { // Run through this process to pregenerate mipmap pyramid for (int mip = 0; mip <= MipmapCount; mip++) { OpenGL.TexImage2D(All.Texture2D, mip, (int)format, width, height, 0, format, All.UnsignedByte, IntPtr.Zero); GLESConfig.GlCheckError(this); if (width > 1) { width = width / 2; } if (height > 1) { height = height / 2; } } } CreateSurfaceList(); // Get final internal format Format = GetBuffer(0, 0).Format; }
/// <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); }