/* * 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.rs; import haven.*; import javax.media.opengl.*; public class GBuffer { public final Context ctx; public final Coord sz; private final GLFrameBuffer buf; private final GLState ostate; public static class Context { private final Object dmon = new Object(); public final GLProfile prof; public final GLAutoDrawable buf; private final GLState gstate; private GLConfig glconf; private GBuffer curdraw; private GLState.Applier state; public Context() { this.prof = GLProfile.getDefault(); GLDrawableFactory df = GLDrawableFactory.getFactory(prof); gstate = new GLState() { public void apply(GOut g) { GL2 gl = g.gl; gl.glColor3f(1, 1, 1); gl.glPointSize(4); gl.setSwapInterval(1); gl.glEnable(GL.GL_BLEND); gl.glBlendFunc(GL.GL_SRC_ALPHA, GL.GL_ONE_MINUS_SRC_ALPHA); if(g.gc.havefsaa()) g.gl.glDisable(GL.GL_MULTISAMPLE); GOut.checkerr(gl); } public void unapply(GOut g) { } public void prep(Buffer buf) { buf.put(HavenPanel.global, this); } }; /* XXX: This seems a bit unreliable. On Xorg with nvidia * drivers, an OffscreenAutoDrawable produces no results, * while a Pbuffer works; while on Xvfb with mesa-swx, an * OffscreenAutoDrawable works, while Pbuffer creation * fails. :-/ */ this.buf = df.createOffscreenAutoDrawable(null, caps(prof), null, 1, 1, null); buf.addGLEventListener(new GLEventListener() { public void display(GLAutoDrawable d) { GL2 gl = d.getGL().getGL2(); /* gl = new TraceGL2(gl, System.err) */ redraw(gl); GLObject.disposeall(gl); } public void init(GLAutoDrawable d) { GL2 gl = d.getGL().getGL2(); glconf = GLConfig.fromgl(gl, d.getContext(), d.getChosenGLCapabilities()); glconf.pref = GLSettings.defconf(glconf); glconf.pref.meshmode.val = GLSettings.MeshMode.MEM; } public void reshape(GLAutoDrawable d, final int x, final int y, final int w, final int h) { } public void dispose(GLAutoDrawable d) { GL2 gl = d.getGL().getGL2(); GLObject.disposeall(gl); } }); } protected GLCapabilities caps(GLProfile prof) { GLCapabilities ret = new GLCapabilities(prof); ret.setDoubleBuffered(true); ret.setAlphaBits(8); ret.setRedBits(8); ret.setGreenBits(8); ret.setBlueBits(8); ret.setSampleBuffers(true); ret.setNumSamples(4); return(ret); } private void redraw(GL2 gl) { curdraw.redraw(gl); } } public GBuffer(Context ctx, Coord sz) { this.ctx = ctx; this.sz = sz; buf = new GLFrameBuffer(new TexE(sz, GL.GL_RGBA, GL.GL_RGBA, GL.GL_UNSIGNED_BYTE), null); ostate = HavenPanel.OrthoState.fixed(new Coord(sz)); } private static Context defctx = null; private static Context defctx() { synchronized(GBuffer.class) { if(defctx == null) defctx = new Context(); } return(defctx); } public GBuffer(Coord sz) { this(defctx(), sz); } private Drawn curdraw; protected void redraw(GL2 gl) { if((ctx.state == null) || (ctx.state.gl != gl)) ctx.state = new GLState.Applier(gl, ctx.glconf); GLState.Buffer ibuf = new GLState.Buffer(ctx.glconf); ctx.gstate.prep(ibuf); ostate.prep(ibuf); buf.prep(ibuf); GOut g = new GOut(gl, ctx.buf.getContext(), ctx.glconf, ctx.state, ibuf, sz); g.apply(); gl.glClearColor(0, 0, 0, 0); gl.glClear(GL.GL_COLOR_BUFFER_BIT); curdraw.draw(g); ctx.state.clean(); } public void render(Drawn thing) { synchronized(ctx.dmon) { curdraw = thing; ctx.curdraw = this; try { ctx.buf.display(); } finally { curdraw = null; ctx.curdraw = null; } } } public void dispose() { buf.dispose(); } public static void main(String[] args) { GBuffer test = new GBuffer(new Coord(250, 250)); test.render(new Drawn() { public void draw(GOut g) { g.chcolor(255, 0, 128, 255); g.frect(new Coord(50, 50), new Coord(100, 100)); try { javax.imageio.ImageIO.write(g.getimage(), "PNG", new java.io.File("/tmp/bard.png")); } catch(java.io.IOException e) { throw(new RuntimeException(e)); } g.checkerr(g.gl); } }); } }