protected void GenerateMipMaps(byte[] data, bool useSoftware, bool isCompressed, int faceNum) { // use regular type, unless cubemap, then specify which face of the cubemap we // are dealing with here int type = (TextureType == TextureType.CubeMap) ? Gl.GL_TEXTURE_CUBE_MAP_POSITIVE_X + faceNum : GLTextureType; if (useSoftware && MipmapCount > 0) { if (TextureType == TextureType.OneD) { Glu.gluBuild1DMipmaps(type, HasAlpha ? Gl.GL_RGBA8 : Gl.GL_RGB8, Width, GLFormat, Gl.GL_UNSIGNED_BYTE, data); } else if (TextureType == TextureType.ThreeD) { // TODO: Tao needs glTexImage3D Gl.glTexImage3DEXT(type, 0, HasAlpha ? Gl.GL_RGBA8 : Gl.GL_RGB8, SrcWidth, SrcHeight, Depth, 0, GLFormat, Gl.GL_UNSIGNED_BYTE, data); } else { // build the mipmaps Glu.gluBuild2DMipmaps(type, HasAlpha ? Gl.GL_RGBA8 : Gl.GL_RGB8, Width, Height, GLFormat, Gl.GL_UNSIGNED_BYTE, data); } } else { if (TextureType == TextureType.OneD) { Gl.glTexImage1D(type, 0, HasAlpha ? Gl.GL_RGBA8 : Gl.GL_RGB8, Width, 0, GLFormat, Gl.GL_UNSIGNED_BYTE, data); } else if (TextureType == TextureType.ThreeD) { // TODO: Tao needs glTexImage3D Gl.glTexImage3DEXT(type, 0, HasAlpha ? Gl.GL_RGBA8 : Gl.GL_RGB8, SrcWidth, SrcHeight, Depth, 0, GLFormat, Gl.GL_UNSIGNED_BYTE, data); } else { if (isCompressed && Root.Instance.RenderSystem.Capabilities.HasCapability(Capabilities.TextureCompressionDXT)) { int blockSize = (Format == PixelFormat.DXT1) ? 8 : 16; int size = ((Width + 3) / 4) * ((Height + 3) / 4) * blockSize; // load compressed image data Gl.glCompressedTexImage2DARB(type, 0, GLFormat, SrcWidth, SrcHeight, 0, size, data); } else { Gl.glTexImage2D(type, 0, HasAlpha ? Gl.GL_RGBA8 : Gl.GL_RGB8, Width, Height, 0, GLFormat, Gl.GL_UNSIGNED_BYTE, data); } } } }
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); }