package net.minecraft.client.renderer.texture; import cpw.mods.fml.client.TextureFXManager; import cpw.mods.fml.relauncher.Side; import cpw.mods.fml.relauncher.SideOnly; import java.awt.image.BufferedImage; import java.io.File; import java.io.IOException; import java.nio.ByteBuffer; import javax.imageio.ImageIO; import net.minecraft.client.Minecraft; import net.minecraft.client.renderer.OpenGlHelper; import net.minecraft.src.FMLRenderAccessLibrary; import org.lwjgl.opengl.GL11; import org.lwjgl.opengl.GL12; @SideOnly(Side.CLIENT) public class Texture { private int glTextureId; private int textureId; private int textureType; /** Width of this texture in pixels. */ private final int width; /** Height of this texture in pixels. */ private final int height; private final int textureDepth; private final int textureFormat; private final int textureTarget; private final int textureMinFilter; private final int textureMagFilter; private final int textureWrap; private final boolean mipmapActive; private final String textureName; private Rect2i textureRect; private boolean transferred; /** * Uninitialized boolean. If true, the texture is re-uploaded every time it's modified. If false, every tick after * it's been modified at least once in that tick. */ private boolean autoCreate; /** * False if the texture has been modified since it was last uploaded to the GPU. */ private boolean textureNotModified; private ByteBuffer textureData; private Texture(String par1Str, int par2, int par3, int par4, int par5, int par6, int par7, int par8, int par9) { this.textureName = par1Str; this.textureType = par2; this.width = par3; this.height = par4; this.textureDepth = par5; this.textureFormat = par7; this.textureMinFilter = par8; this.textureMagFilter = par9; this.textureWrap = par6; this.textureRect = new Rect2i(0, 0, par3, par4); if (par4 == 1 && par5 == 1) { this.textureTarget = 3552; } else if (par5 == 1) { this.textureTarget = 3553; } else { this.textureTarget = 32879; } this.mipmapActive = par8 != 9728 && par8 != 9729 || par9 != 9728 && par9 != 9729; if (par2 != 2) { this.glTextureId = GL11.glGenTextures(); GL11.glBindTexture(this.textureTarget, this.glTextureId); GL11.glTexParameteri(this.textureTarget, GL11.GL_TEXTURE_MIN_FILTER, par8); GL11.glTexParameteri(this.textureTarget, GL11.GL_TEXTURE_MAG_FILTER, par9); GL11.glTexParameteri(this.textureTarget, GL11.GL_TEXTURE_WRAP_S, par6); GL11.glTexParameteri(this.textureTarget, GL11.GL_TEXTURE_WRAP_T, par6); } else { this.glTextureId = -1; } this.textureId = TextureManager.instance().getNextTextureId(); } public Texture(String par1Str, int par2, int par3, int par4, int par5, int par6, int par7, int par8, BufferedImage par9BufferedImage) { this(par1Str, par2, par3, par4, 1, par5, par6, par7, par8, par9BufferedImage); } public Texture(String par1Str, int par2, int par3, int par4, int par5, int par6, int par7, int par8, int par9, BufferedImage par10BufferedImage) { this(par1Str, par2, par3, par4, par5, par6, par7, par8, par9); if (par10BufferedImage == null) { if (par3 != -1 && par4 != -1) { byte[] abyte = new byte[par3 * par4 * par5 * 4]; for (int i2 = 0; i2 < abyte.length; ++i2) { abyte[i2] = 0; } this.textureData = ByteBuffer.allocateDirect(abyte.length); this.textureData.clear(); this.textureData.put(abyte); this.textureData.position(0).limit(abyte.length); if (this.autoCreate) { this.uploadTexture(); } else { this.textureNotModified = false; } } else { this.transferred = false; } } else { this.transferred = true; this.transferFromImage(par10BufferedImage); if (par2 != 2) { this.uploadTexture(); this.autoCreate = false; } } } public final Rect2i getTextureRect() { return this.textureRect; } public void fillRect(Rect2i par1Rect2i, int par2) { if (this.textureTarget != 32879) { Rect2i rect2i1 = new Rect2i(0, 0, this.width, this.height); rect2i1.intersection(par1Rect2i); this.textureData.position(0); for (int j = rect2i1.getRectY(); j < rect2i1.getRectY() + rect2i1.getRectHeight(); ++j) { int k = j * this.width * 4; for (int l = rect2i1.getRectX(); l < rect2i1.getRectX() + rect2i1.getRectWidth(); ++l) { this.textureData.put(k + l * 4 + 0, (byte)(par2 >> 24 & 255)); this.textureData.put(k + l * 4 + 1, (byte)(par2 >> 16 & 255)); this.textureData.put(k + l * 4 + 2, (byte)(par2 >> 8 & 255)); this.textureData.put(k + l * 4 + 3, (byte)(par2 >> 0 & 255)); } } if (this.autoCreate) { this.uploadTexture(); } else { this.textureNotModified = false; } } } public void writeImage(String par1Str) { BufferedImage bufferedimage = new BufferedImage(this.width, this.height, 2); ByteBuffer bytebuffer = this.getTextureData(); byte[] abyte = new byte[this.width * this.height * 4]; bytebuffer.position(0); bytebuffer.get(abyte); for (int i = 0; i < this.width; ++i) { for (int j = 0; j < this.height; ++j) { int k = j * this.width * 4 + i * 4; byte b0 = 0; int l = b0 | (abyte[k + 2] & 255) << 0; l |= (abyte[k + 1] & 255) << 8; l |= (abyte[k + 0] & 255) << 16; l |= (abyte[k + 3] & 255) << 24; bufferedimage.setRGB(i, j, l); } } this.textureData.position(this.width * this.height * 4); try { ImageIO.write(bufferedimage, "png", new File(Minecraft.getMinecraftDir(), par1Str)); } catch (IOException ioexception) { ioexception.printStackTrace(); } } public void copyFrom(int par1, int par2, Texture par3Texture, boolean par4) { if (this.textureTarget != 32879) { if (textureNotModified && !par4) { FMLRenderAccessLibrary.doTextureCopy(this, par3Texture, par1, par2); return; } ByteBuffer bytebuffer = par3Texture.getTextureData(); this.textureData.position(0); bytebuffer.position(0); for (int k = 0; k < par3Texture.getHeight(); ++k) { int l = par2 + k; int i1 = k * par3Texture.getWidth() * 4; int j1 = l * this.width * 4; if (par4) { l = par1 + (par3Texture.getHeight() - k - 1); //BUGFIX: targetY -> targetX and -1 } for (int k1 = 0; k1 < par3Texture.getWidth(); ++k1) { int l1 = j1 + (k1 + par1) * 4; int i2 = i1 + k1 * 4; if (par4) { l1 = (par2 + k1) * this.width * 4 + l * 4; //BUGFIX: targetX -> targetY and parens } this.textureData.put(l1 + 0, bytebuffer.get(i2 + 0)); this.textureData.put(l1 + 1, bytebuffer.get(i2 + 1)); this.textureData.put(l1 + 2, bytebuffer.get(i2 + 2)); this.textureData.put(l1 + 3, bytebuffer.get(i2 + 3)); } } this.textureData.position(this.width * this.height * 4); if (this.autoCreate) { this.uploadTexture(); } else { this.textureNotModified = false; } } } public void func_104062_b(int par1, int par2, Texture par3Texture) { GL11.glBindTexture(this.textureTarget, this.glTextureId); GL11.glTexSubImage2D(this.textureTarget, 0, par1, par2, par3Texture.getWidth(), par3Texture.getHeight(), this.textureFormat, GL11.GL_UNSIGNED_BYTE, (ByteBuffer)par3Texture.getTextureData().position(0)); this.textureNotModified = true; } public void transferFromImage(BufferedImage par1BufferedImage) { if (this.textureTarget != 32879) { int i = par1BufferedImage.getWidth(); int j = par1BufferedImage.getHeight(); if (i <= this.width && j <= this.height) { int[] aint = new int[] {3, 0, 1, 2}; int[] aint1 = new int[] {3, 2, 1, 0}; int[] aint2 = this.textureFormat == 32993 ? aint1 : aint; int[] aint3 = new int[this.width * this.height]; int k = par1BufferedImage.getTransparency(); par1BufferedImage.getRGB(0, 0, this.width, this.height, aint3, 0, i); byte[] abyte = new byte[this.width * this.height * 4]; for (int l = 0; l < this.height; ++l) { for (int i1 = 0; i1 < this.width; ++i1) { int j1 = l * this.width + i1; int k1 = j1 * 4; abyte[k1 + aint2[0]] = (byte)(aint3[j1] >> 24 & 255); abyte[k1 + aint2[1]] = (byte)(aint3[j1] >> 16 & 255); abyte[k1 + aint2[2]] = (byte)(aint3[j1] >> 8 & 255); abyte[k1 + aint2[3]] = (byte)(aint3[j1] >> 0 & 255); } } this.textureData = ByteBuffer.allocateDirect(abyte.length); this.textureData.clear(); this.textureData.put(abyte); this.textureData.limit(abyte.length); if (this.autoCreate) { this.uploadTexture(); } else { this.textureNotModified = false; } } else { Minecraft.getMinecraft().getLogAgent().logWarning("transferFromImage called with a BufferedImage with dimensions (" + i + ", " + j + ") larger than the Texture dimensions (" + this.width + ", " + this.height + "). Ignoring."); } } } public int getTextureId() { return this.textureId; } public int getGlTextureId() { return this.glTextureId; } public int getWidth() { return this.width; } public int getHeight() { return this.height; } public String getTextureName() { return this.textureName; } public void bindTexture(int par1) { if (this.textureDepth == 1) { GL11.glEnable(GL11.GL_TEXTURE_2D); } else { GL11.glEnable(GL12.GL_TEXTURE_3D); } OpenGlHelper.setActiveTexture(OpenGlHelper.defaultTexUnit + par1); GL11.glBindTexture(this.textureTarget, this.glTextureId); if (!this.textureNotModified) { this.uploadTexture(); } } public void uploadTexture() { this.textureData.flip(); if (this.height != 1 && this.textureDepth != 1) { GL12.glTexImage3D(this.textureTarget, 0, this.textureFormat, this.width, this.height, this.textureDepth, 0, this.textureFormat, GL11.GL_UNSIGNED_BYTE, this.textureData); } else if (this.height != 1) { GL11.glTexImage2D(this.textureTarget, 0, this.textureFormat, this.width, this.height, 0, this.textureFormat, GL11.GL_UNSIGNED_BYTE, this.textureData); } else { GL11.glTexImage1D(this.textureTarget, 0, this.textureFormat, this.width, 0, this.textureFormat, GL11.GL_UNSIGNED_BYTE, this.textureData); } this.textureNotModified = true; } public ByteBuffer getTextureData() { return this.textureData; } public void createAndUploadTexture() { this.glTextureId = GL11.glGenTextures(); GL11.glBindTexture(this.textureTarget, this.glTextureId); System.out.printf("Buffer %s %x %d is %s\n",textureName, textureTarget, glTextureId, textureData); textureData.position(textureData.limit()); uploadTexture(); } }