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; }
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); }