/* * This file is part of the Haven & Hearth game client. * Copyright (C) 2009 Fredrik Tolf <fredrik@dolda2000.com>, and * Björn Johannessen <johannessen.bjorn@gmail.com> * * Redistribution and/or modification of this file is subject to the * terms of the GNU Lesser General Public License, version 3, as * published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * Other parts of this source tree adhere to other copying * rights. Please see the file `COPYING' in the root directory of the * source tree for details. * * A copy the GNU Lesser General Public License is distributed along * with the source tree of which this file is a part in the file * `doc/LPGL-3'. If it is missing for any reason, please see the Free * Software Foundation's website at <http://www.fsf.org/>, or write * to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, * Boston, MA 02111-1307 USA */ package haven; import java.util.*; import java.awt.image.*; import java.nio.ByteBuffer; import javax.media.opengl.*; import haven.Defer.Future; public abstract class TexL extends TexGL { protected Mipmapper mipmap = null; private Future<Prepared> decode = null; protected abstract BufferedImage fill(); public TexL(Coord sz) { super(sz); if((sz.x != nextp2(sz.x)) || (sz.y != nextp2(sz.y))) throw(new RuntimeException("TexL does not support non-power-of-two textures")); } public void mipmap(Mipmapper mipmap) { this.mipmap = mipmap; dispose(); } private class Prepared { BufferedImage img; byte[][] data; int ifmt; private Prepared() { img = fill(); if(!Utils.imgsz(img).equals(dim)) throw(new RuntimeException("Generated TexL image from " + TexL.this + " does not match declared size")); ifmt = TexI.detectfmt(img); LinkedList<byte[]> data = new LinkedList<byte[]>(); if((ifmt == GL.GL_RGB) || (ifmt == GL2.GL_BGR)) { if((mipmap != null) && !(mipmap instanceof Mipmapper.Mipmapper3)) ifmt = -1; } if((ifmt == GL.GL_RGB) || (ifmt == GL2.GL_BGR)) { byte[] pixels = ((DataBufferByte)img.getRaster().getDataBuffer()).getData(); data.add(pixels); if(mipmap != null) { Coord msz = dim; Mipmapper.Mipmapper3 alg = (Mipmapper.Mipmapper3)mipmap; while((msz.x > 1) || (msz.y > 1)) { pixels = alg.gen3(msz, pixels, ifmt); data.add(pixels); msz = Mipmapper.nextsz(msz); } } } else { byte[] pixels; if((ifmt == GL.GL_RGBA) || (ifmt == GL.GL_BGRA)) { pixels = ((DataBufferByte)img.getRaster().getDataBuffer()).getData(); } else { pixels = TexI.convert(img, dim); ifmt = GL.GL_RGBA; } data.add(pixels); if(mipmap != null) { Coord msz = dim; while((msz.x > 1) || (msz.y > 1)) { pixels = mipmap.gen4(msz, pixels, ifmt); data.add(pixels); msz = Mipmapper.nextsz(msz); } } } this.data = data.toArray(new byte[0][]); } } private Future<Prepared> prepare() { return(Defer.later(new Defer.Callable<Prepared>() { public Prepared call() { Prepared ret = new Prepared(); return(ret); } })); } protected void fill(GOut g) { if(decode == null) decode = prepare(); Prepared prep = decode.get(); decode = null; GL2 gl = g.gl; gl.glPixelStorei(GL.GL_UNPACK_ALIGNMENT, 1); Coord cdim = tdim; for(int i = 0; i < prep.data.length; i++) { gl.glTexImage2D(GL.GL_TEXTURE_2D, i, GL.GL_RGBA, cdim.x, cdim.y, 0, prep.ifmt, GL.GL_UNSIGNED_BYTE, ByteBuffer.wrap(prep.data[i])); cdim = Mipmapper.nextsz(cdim); } } }