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