mirror of
https://github.com/curioustorvald/Terrarum.git
synced 2026-06-11 11:04:05 +09:00
added sources for Slick
Former-commit-id: 1647fa32ef6894bd7db44f741f07c2f4dcdf9054 Former-commit-id: 0e5810dcfbe1fd59b13e7cabe9f1e93c5542da2d
This commit is contained in:
@@ -0,0 +1,228 @@
|
||||
package org.newdawn.slick.opengl.pbuffer;
|
||||
|
||||
import java.nio.IntBuffer;
|
||||
|
||||
import org.lwjgl.BufferUtils;
|
||||
import org.lwjgl.opengl.EXTFramebufferObject;
|
||||
import org.lwjgl.opengl.GL11;
|
||||
import org.lwjgl.opengl.GLContext;
|
||||
import org.newdawn.slick.Graphics;
|
||||
import org.newdawn.slick.Image;
|
||||
import org.newdawn.slick.SlickException;
|
||||
import org.newdawn.slick.opengl.InternalTextureLoader;
|
||||
import org.newdawn.slick.opengl.SlickCallable;
|
||||
import org.newdawn.slick.opengl.Texture;
|
||||
import org.newdawn.slick.util.Log;
|
||||
|
||||
/**
|
||||
* A graphics implementation that renders to an FBO
|
||||
*
|
||||
* @author kevin
|
||||
*/
|
||||
public class FBOGraphics extends Graphics {
|
||||
/** The image we're we're sort of rendering to */
|
||||
private Image image;
|
||||
/** The ID of the FBO in use */
|
||||
private int FBO;
|
||||
/** True if this context is valid */
|
||||
private boolean valid = true;
|
||||
|
||||
/**
|
||||
* Create a new graphics context around an FBO
|
||||
*
|
||||
* @param image The image we're rendering to
|
||||
* @throws SlickException Indicates a failure to use pbuffers
|
||||
*/
|
||||
public FBOGraphics(Image image) throws SlickException {
|
||||
super(image.getTexture().getTextureWidth(), image.getTexture().getTextureHeight());
|
||||
this.image = image;
|
||||
|
||||
Log.debug("Creating FBO "+image.getWidth()+"x"+image.getHeight());
|
||||
|
||||
boolean FBOEnabled = GLContext.getCapabilities().GL_EXT_framebuffer_object;
|
||||
if (!FBOEnabled) {
|
||||
throw new SlickException("Your OpenGL card does not support FBO and hence can't handle the dynamic images required for this application.");
|
||||
}
|
||||
|
||||
init();
|
||||
}
|
||||
|
||||
/**
|
||||
* Check the FBO for completeness as shown in the LWJGL tutorial
|
||||
*
|
||||
* @throws SlickException Indicates an incomplete FBO
|
||||
*/
|
||||
private void completeCheck() throws SlickException {
|
||||
int framebuffer = EXTFramebufferObject.glCheckFramebufferStatusEXT(EXTFramebufferObject.GL_FRAMEBUFFER_EXT);
|
||||
switch ( framebuffer ) {
|
||||
case EXTFramebufferObject.GL_FRAMEBUFFER_COMPLETE_EXT:
|
||||
break;
|
||||
case EXTFramebufferObject.GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT_EXT:
|
||||
throw new SlickException( "FrameBuffer: " + FBO
|
||||
+ ", has caused a GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT_EXT exception" );
|
||||
case EXTFramebufferObject.GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT_EXT:
|
||||
throw new SlickException( "FrameBuffer: " + FBO
|
||||
+ ", has caused a GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT_EXT exception" );
|
||||
case EXTFramebufferObject.GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS_EXT:
|
||||
throw new SlickException( "FrameBuffer: " + FBO
|
||||
+ ", has caused a GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS_EXT exception" );
|
||||
case EXTFramebufferObject.GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER_EXT:
|
||||
throw new SlickException( "FrameBuffer: " + FBO
|
||||
+ ", has caused a GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER_EXT exception" );
|
||||
case EXTFramebufferObject.GL_FRAMEBUFFER_INCOMPLETE_FORMATS_EXT:
|
||||
throw new SlickException( "FrameBuffer: " + FBO
|
||||
+ ", has caused a GL_FRAMEBUFFER_INCOMPLETE_FORMATS_EXT exception" );
|
||||
case EXTFramebufferObject.GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER_EXT:
|
||||
throw new SlickException( "FrameBuffer: " + FBO
|
||||
+ ", has caused a GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER_EXT exception" );
|
||||
default:
|
||||
throw new SlickException( "Unexpected reply from glCheckFramebufferStatusEXT: " + framebuffer);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialise the FBO that will be used to render to
|
||||
*
|
||||
* @throws SlickException
|
||||
*/
|
||||
private void init() throws SlickException {
|
||||
IntBuffer buffer = BufferUtils.createIntBuffer(1);
|
||||
EXTFramebufferObject.glGenFramebuffersEXT(buffer);
|
||||
FBO = buffer.get();
|
||||
|
||||
// for some reason FBOs won't work on textures unless you've absolutely just
|
||||
// created them.
|
||||
try {
|
||||
Texture tex = InternalTextureLoader.get().createTexture(image.getWidth(), image.getHeight(), image.getFilter());
|
||||
|
||||
EXTFramebufferObject.glBindFramebufferEXT(EXTFramebufferObject.GL_FRAMEBUFFER_EXT, FBO);
|
||||
EXTFramebufferObject.glFramebufferTexture2DEXT(EXTFramebufferObject.GL_FRAMEBUFFER_EXT,
|
||||
EXTFramebufferObject.GL_COLOR_ATTACHMENT0_EXT,
|
||||
GL11.GL_TEXTURE_2D, tex.getTextureID(), 0);
|
||||
|
||||
completeCheck();
|
||||
unbind();
|
||||
|
||||
// Clear our destination area before using it
|
||||
clear();
|
||||
flush();
|
||||
|
||||
// keep hold of the original content
|
||||
drawImage(image, 0, 0);
|
||||
image.setTexture(tex);
|
||||
|
||||
} catch (Exception e) {
|
||||
throw new SlickException("Failed to create new texture for FBO");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Bind to the FBO created
|
||||
*/
|
||||
private void bind() {
|
||||
EXTFramebufferObject.glBindFramebufferEXT(EXTFramebufferObject.GL_FRAMEBUFFER_EXT, FBO);
|
||||
GL11.glReadBuffer(EXTFramebufferObject.GL_COLOR_ATTACHMENT0_EXT);
|
||||
}
|
||||
|
||||
/**
|
||||
* Unbind from the FBO created
|
||||
*/
|
||||
private void unbind() {
|
||||
EXTFramebufferObject.glBindFramebufferEXT(EXTFramebufferObject.GL_FRAMEBUFFER_EXT, 0);
|
||||
GL11.glReadBuffer(GL11.GL_BACK);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.newdawn.slick.Graphics#disable()
|
||||
*/
|
||||
protected void disable() {
|
||||
GL.flush();
|
||||
|
||||
unbind();
|
||||
GL11.glPopClientAttrib();
|
||||
GL11.glPopAttrib();
|
||||
GL11.glMatrixMode(GL11.GL_MODELVIEW);
|
||||
GL11.glPopMatrix();
|
||||
GL11.glMatrixMode(GL11.GL_PROJECTION);
|
||||
GL11.glPopMatrix();
|
||||
GL11.glMatrixMode(GL11.GL_MODELVIEW);
|
||||
|
||||
SlickCallable.leaveSafeBlock();
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.newdawn.slick.Graphics#enable()
|
||||
*/
|
||||
protected void enable() {
|
||||
if (!valid) {
|
||||
throw new RuntimeException("Attempt to use a destroy()ed offscreen graphics context.");
|
||||
}
|
||||
SlickCallable.enterSafeBlock();
|
||||
|
||||
GL11.glPushAttrib(GL11.GL_ALL_ATTRIB_BITS);
|
||||
GL11.glPushClientAttrib(GL11.GL_ALL_CLIENT_ATTRIB_BITS);
|
||||
GL11.glMatrixMode(GL11.GL_PROJECTION);
|
||||
GL11.glPushMatrix();
|
||||
GL11.glMatrixMode(GL11.GL_MODELVIEW);
|
||||
GL11.glPushMatrix();
|
||||
|
||||
bind();
|
||||
initGL();
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialise the GL context
|
||||
*/
|
||||
protected void initGL() {
|
||||
GL11.glEnable(GL11.GL_TEXTURE_2D);
|
||||
GL11.glShadeModel(GL11.GL_SMOOTH);
|
||||
GL11.glDisable(GL11.GL_DEPTH_TEST);
|
||||
GL11.glDisable(GL11.GL_LIGHTING);
|
||||
|
||||
GL11.glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
|
||||
GL11.glClearDepth(1);
|
||||
|
||||
GL11.glEnable(GL11.GL_BLEND);
|
||||
GL11.glBlendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA);
|
||||
|
||||
GL11.glViewport(0,0,screenWidth,screenHeight);
|
||||
GL11.glMatrixMode(GL11.GL_MODELVIEW);
|
||||
GL11.glLoadIdentity();
|
||||
|
||||
enterOrtho();
|
||||
}
|
||||
|
||||
/**
|
||||
* Enter the orthographic mode
|
||||
*/
|
||||
protected void enterOrtho() {
|
||||
GL11.glMatrixMode(GL11.GL_PROJECTION);
|
||||
GL11.glLoadIdentity();
|
||||
GL11.glOrtho(0, screenWidth, 0, screenHeight, 1, -1);
|
||||
GL11.glMatrixMode(GL11.GL_MODELVIEW);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.newdawn.slick.Graphics#destroy()
|
||||
*/
|
||||
public void destroy() {
|
||||
super.destroy();
|
||||
|
||||
IntBuffer buffer = BufferUtils.createIntBuffer(1);
|
||||
buffer.put(FBO);
|
||||
buffer.flip();
|
||||
|
||||
EXTFramebufferObject.glDeleteFramebuffersEXT(buffer);
|
||||
valid = false;
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.newdawn.slick.Graphics#flush()
|
||||
*/
|
||||
public void flush() {
|
||||
super.flush();
|
||||
|
||||
image.flushPixelData();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,141 @@
|
||||
package org.newdawn.slick.opengl.pbuffer;
|
||||
|
||||
import java.util.HashMap;
|
||||
|
||||
import org.lwjgl.opengl.GLContext;
|
||||
import org.lwjgl.opengl.Pbuffer;
|
||||
import org.newdawn.slick.Graphics;
|
||||
import org.newdawn.slick.Image;
|
||||
import org.newdawn.slick.SlickException;
|
||||
import org.newdawn.slick.util.Log;
|
||||
|
||||
/**
|
||||
* A factory to produce an appropriate render to texture graphics context based on current
|
||||
* hardware
|
||||
*
|
||||
* @author kevin
|
||||
*/
|
||||
public class GraphicsFactory {
|
||||
/** The graphics list of graphics contexts created */
|
||||
private static HashMap graphics = new HashMap();
|
||||
/** True if pbuffers are supported */
|
||||
private static boolean pbuffer = true;
|
||||
/** True if pbuffer render to texture are supported */
|
||||
private static boolean pbufferRT = true;
|
||||
/** True if fbo are supported */
|
||||
private static boolean fbo = true;
|
||||
/** True if we've initialised */
|
||||
private static boolean init = false;
|
||||
|
||||
/**
|
||||
* Initialise offscreen rendering by checking what buffers are supported
|
||||
* by the card
|
||||
*
|
||||
* @throws SlickException Indicates no buffers are supported
|
||||
*/
|
||||
private static void init() throws SlickException {
|
||||
init = true;
|
||||
|
||||
if (fbo) {
|
||||
fbo = GLContext.getCapabilities().GL_EXT_framebuffer_object;
|
||||
}
|
||||
pbuffer = (Pbuffer.getCapabilities() & Pbuffer.PBUFFER_SUPPORTED) != 0;
|
||||
pbufferRT = (Pbuffer.getCapabilities() & Pbuffer.RENDER_TEXTURE_SUPPORTED) != 0;
|
||||
|
||||
if (!fbo && !pbuffer && !pbufferRT) {
|
||||
throw new SlickException("Your OpenGL card does not support offscreen buffers and hence can't handle the dynamic images required for this application.");
|
||||
}
|
||||
|
||||
Log.info("Offscreen Buffers FBO="+fbo+" PBUFFER="+pbuffer+" PBUFFERRT="+pbufferRT);
|
||||
}
|
||||
|
||||
/**
|
||||
* Force FBO use on or off
|
||||
*
|
||||
* @param useFBO True if we should try and use FBO for offscreen images
|
||||
*/
|
||||
public static void setUseFBO(boolean useFBO) {
|
||||
fbo = useFBO;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if we're using FBO for dynamic textures
|
||||
*
|
||||
* @return True if we're using FBOs
|
||||
*/
|
||||
public static boolean usingFBO() {
|
||||
return fbo;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if we're using PBuffer for dynamic textures
|
||||
*
|
||||
* @return True if we're using PBuffer
|
||||
*/
|
||||
public static boolean usingPBuffer() {
|
||||
return !fbo && pbuffer;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a graphics context for a particular image
|
||||
*
|
||||
* @param image The image for which to retrieve the graphics context
|
||||
* @return The graphics context
|
||||
* @throws SlickException Indicates it wasn't possible to create a graphics context
|
||||
* given available hardware.
|
||||
*/
|
||||
public static Graphics getGraphicsForImage(Image image) throws SlickException {
|
||||
Graphics g = (Graphics) graphics.get(image.getTexture());
|
||||
|
||||
if (g == null) {
|
||||
g = createGraphics(image);
|
||||
graphics.put(image.getTexture(), g);
|
||||
}
|
||||
|
||||
return g;
|
||||
}
|
||||
|
||||
/**
|
||||
* Release any graphics context that is assocaited with the given image
|
||||
*
|
||||
* @param image The image to release
|
||||
* @throws SlickException Indicates a failure to release the context
|
||||
*/
|
||||
public static void releaseGraphicsForImage(Image image) throws SlickException {
|
||||
Graphics g = (Graphics) graphics.remove(image.getTexture());
|
||||
|
||||
if (g != null) {
|
||||
g.destroy();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Create an underlying graphics context for the given image
|
||||
*
|
||||
* @param image The image we want to render to
|
||||
* @return The graphics context created
|
||||
* @throws SlickException
|
||||
*/
|
||||
private static Graphics createGraphics(Image image) throws SlickException {
|
||||
init();
|
||||
|
||||
if (fbo) {
|
||||
try {
|
||||
return new FBOGraphics(image);
|
||||
} catch (Exception e) {
|
||||
fbo = false;
|
||||
Log.warn("FBO failed in use, falling back to PBuffer");
|
||||
}
|
||||
}
|
||||
|
||||
if (pbuffer) {
|
||||
if (pbufferRT) {
|
||||
return new PBufferGraphics(image);
|
||||
} else {
|
||||
return new PBufferUniqueGraphics(image);
|
||||
}
|
||||
}
|
||||
|
||||
throw new SlickException("Failed to create offscreen buffer even though the card reports it's possible");
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,172 @@
|
||||
package org.newdawn.slick.opengl.pbuffer;
|
||||
|
||||
import org.lwjgl.LWJGLException;
|
||||
import org.lwjgl.opengl.Display;
|
||||
import org.lwjgl.opengl.GL11;
|
||||
import org.lwjgl.opengl.Pbuffer;
|
||||
import org.lwjgl.opengl.PixelFormat;
|
||||
import org.lwjgl.opengl.RenderTexture;
|
||||
import org.newdawn.slick.Graphics;
|
||||
import org.newdawn.slick.Image;
|
||||
import org.newdawn.slick.SlickException;
|
||||
import org.newdawn.slick.opengl.SlickCallable;
|
||||
import org.newdawn.slick.opengl.Texture;
|
||||
import org.newdawn.slick.opengl.TextureImpl;
|
||||
import org.newdawn.slick.opengl.InternalTextureLoader;
|
||||
import org.newdawn.slick.util.Log;
|
||||
|
||||
/**
|
||||
* A graphics implementation that renders to a PBuffer
|
||||
*
|
||||
* @author kevin
|
||||
*/
|
||||
public class PBufferGraphics extends Graphics {
|
||||
|
||||
/** The pbuffer we're going to render to */
|
||||
private Pbuffer pbuffer;
|
||||
/** The image we're we're sort of rendering to */
|
||||
private Image image;
|
||||
|
||||
/**
|
||||
* Create a new graphics context around a pbuffer
|
||||
*
|
||||
* @param image The image we're rendering to
|
||||
* @throws SlickException Indicates a failure to use pbuffers
|
||||
*/
|
||||
public PBufferGraphics(Image image) throws SlickException {
|
||||
super(image.getTexture().getTextureWidth(), image.getTexture().getTextureHeight());
|
||||
this.image = image;
|
||||
|
||||
Log.debug("Creating pbuffer(rtt) "+image.getWidth()+"x"+image.getHeight());
|
||||
if ((Pbuffer.getCapabilities() & Pbuffer.PBUFFER_SUPPORTED) == 0) {
|
||||
throw new SlickException("Your OpenGL card does not support PBuffers and hence can't handle the dynamic images required for this application.");
|
||||
}
|
||||
if ((Pbuffer.getCapabilities() & Pbuffer.RENDER_TEXTURE_SUPPORTED) == 0) {
|
||||
throw new SlickException("Your OpenGL card does not support Render-To-Texture and hence can't handle the dynamic images required for this application.");
|
||||
}
|
||||
|
||||
init();
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialise the PBuffer that will be used to render to
|
||||
*
|
||||
* @throws SlickException
|
||||
*/
|
||||
private void init() throws SlickException {
|
||||
try {
|
||||
Texture tex = InternalTextureLoader.get().createTexture(image.getWidth(), image.getHeight(), image.getFilter());
|
||||
|
||||
final RenderTexture rt = new RenderTexture(false, true, false, false, RenderTexture.RENDER_TEXTURE_2D, 0);
|
||||
pbuffer = new Pbuffer(screenWidth, screenHeight, new PixelFormat(8, 0, 0), rt, null);
|
||||
|
||||
// Initialise state of the pbuffer context.
|
||||
pbuffer.makeCurrent();
|
||||
|
||||
initGL();
|
||||
GL.glBindTexture(GL11.GL_TEXTURE_2D, tex.getTextureID());
|
||||
pbuffer.releaseTexImage(Pbuffer.FRONT_LEFT_BUFFER);
|
||||
image.draw(0,0);
|
||||
image.setTexture(tex);
|
||||
|
||||
Display.makeCurrent();
|
||||
} catch (Exception e) {
|
||||
Log.error(e);
|
||||
throw new SlickException("Failed to create PBuffer for dynamic image. OpenGL driver failure?");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.newdawn.slick.Graphics#disable()
|
||||
*/
|
||||
protected void disable() {
|
||||
GL.flush();
|
||||
|
||||
// Bind the texture after rendering.
|
||||
GL.glBindTexture(GL11.GL_TEXTURE_2D, image.getTexture().getTextureID());
|
||||
pbuffer.bindTexImage(Pbuffer.FRONT_LEFT_BUFFER);
|
||||
|
||||
try {
|
||||
Display.makeCurrent();
|
||||
} catch (LWJGLException e) {
|
||||
Log.error(e);
|
||||
}
|
||||
|
||||
SlickCallable.leaveSafeBlock();
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.newdawn.slick.Graphics#enable()
|
||||
*/
|
||||
protected void enable() {
|
||||
SlickCallable.enterSafeBlock();
|
||||
|
||||
try {
|
||||
if (pbuffer.isBufferLost()) {
|
||||
pbuffer.destroy();
|
||||
init();
|
||||
}
|
||||
|
||||
pbuffer.makeCurrent();
|
||||
} catch (Exception e) {
|
||||
Log.error("Failed to recreate the PBuffer");
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
|
||||
// Put the renderer contents to the texture
|
||||
GL.glBindTexture(GL11.GL_TEXTURE_2D, image.getTexture().getTextureID());
|
||||
pbuffer.releaseTexImage(Pbuffer.FRONT_LEFT_BUFFER);
|
||||
TextureImpl.unbind();
|
||||
initGL();
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialise the GL context
|
||||
*/
|
||||
protected void initGL() {
|
||||
GL11.glEnable(GL11.GL_TEXTURE_2D);
|
||||
GL11.glShadeModel(GL11.GL_SMOOTH);
|
||||
GL11.glDisable(GL11.GL_DEPTH_TEST);
|
||||
GL11.glDisable(GL11.GL_LIGHTING);
|
||||
|
||||
GL11.glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
|
||||
GL11.glClearDepth(1);
|
||||
|
||||
GL11.glEnable(GL11.GL_BLEND);
|
||||
GL11.glBlendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA);
|
||||
|
||||
GL11.glViewport(0,0,screenWidth,screenHeight);
|
||||
GL11.glMatrixMode(GL11.GL_MODELVIEW);
|
||||
GL11.glLoadIdentity();
|
||||
|
||||
enterOrtho();
|
||||
}
|
||||
|
||||
/**
|
||||
* Enter the orthographic mode
|
||||
*/
|
||||
protected void enterOrtho() {
|
||||
GL11.glMatrixMode(GL11.GL_PROJECTION);
|
||||
GL11.glLoadIdentity();
|
||||
GL11.glOrtho(0, screenWidth, 0, screenHeight, 1, -1);
|
||||
GL11.glMatrixMode(GL11.GL_MODELVIEW);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.newdawn.slick.Graphics#destroy()
|
||||
*/
|
||||
public void destroy() {
|
||||
super.destroy();
|
||||
|
||||
pbuffer.destroy();
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.newdawn.slick.Graphics#flush()
|
||||
*/
|
||||
public void flush() {
|
||||
super.flush();
|
||||
|
||||
image.flushPixelData();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,167 @@
|
||||
package org.newdawn.slick.opengl.pbuffer;
|
||||
|
||||
import org.lwjgl.LWJGLException;
|
||||
import org.lwjgl.opengl.Display;
|
||||
import org.lwjgl.opengl.GL11;
|
||||
import org.lwjgl.opengl.Pbuffer;
|
||||
import org.lwjgl.opengl.PixelFormat;
|
||||
import org.newdawn.slick.Graphics;
|
||||
import org.newdawn.slick.Image;
|
||||
import org.newdawn.slick.SlickException;
|
||||
import org.newdawn.slick.opengl.SlickCallable;
|
||||
import org.newdawn.slick.opengl.Texture;
|
||||
import org.newdawn.slick.opengl.TextureImpl;
|
||||
import org.newdawn.slick.opengl.InternalTextureLoader;
|
||||
import org.newdawn.slick.util.Log;
|
||||
|
||||
/**
|
||||
* A graphics implementation that renders to a PBuffer using a unique context, i.e.
|
||||
* without render to texture
|
||||
*
|
||||
* @author kevin
|
||||
*/
|
||||
public class PBufferUniqueGraphics extends Graphics {
|
||||
/** The pbuffer we're going to render to */
|
||||
private Pbuffer pbuffer;
|
||||
/** The image we're we're sort of rendering to */
|
||||
private Image image;
|
||||
|
||||
/**
|
||||
* Create a new graphics context around a pbuffer
|
||||
*
|
||||
* @param image The image we're rendering to
|
||||
* @throws SlickException Indicates a failure to use pbuffers
|
||||
*/
|
||||
public PBufferUniqueGraphics(Image image) throws SlickException {
|
||||
super(image.getTexture().getTextureWidth(), image.getTexture().getTextureHeight());
|
||||
this.image = image;
|
||||
|
||||
Log.debug("Creating pbuffer(unique) "+image.getWidth()+"x"+image.getHeight());
|
||||
if ((Pbuffer.getCapabilities() & Pbuffer.PBUFFER_SUPPORTED) == 0) {
|
||||
throw new SlickException("Your OpenGL card does not support PBuffers and hence can't handle the dynamic images required for this application.");
|
||||
}
|
||||
|
||||
init();
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialise the PBuffer that will be used to render to
|
||||
*
|
||||
* @throws SlickException
|
||||
*/
|
||||
private void init() throws SlickException {
|
||||
try {
|
||||
Texture tex = InternalTextureLoader.get().createTexture(image.getWidth(), image.getHeight(), image.getFilter());
|
||||
|
||||
pbuffer = new Pbuffer(screenWidth, screenHeight, new PixelFormat(8, 0, 0), null, null);
|
||||
// Initialise state of the pbuffer context.
|
||||
pbuffer.makeCurrent();
|
||||
|
||||
initGL();
|
||||
image.draw(0,0);
|
||||
GL11.glBindTexture(GL11.GL_TEXTURE_2D, tex.getTextureID());
|
||||
GL11.glCopyTexImage2D(GL11.GL_TEXTURE_2D, 0, GL11.GL_RGBA, 0, 0,
|
||||
tex.getTextureWidth(),
|
||||
tex.getTextureHeight(), 0);
|
||||
image.setTexture(tex);
|
||||
|
||||
Display.makeCurrent();
|
||||
} catch (Exception e) {
|
||||
Log.error(e);
|
||||
throw new SlickException("Failed to create PBuffer for dynamic image. OpenGL driver failure?");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.newdawn.slick.Graphics#disable()
|
||||
*/
|
||||
protected void disable() {
|
||||
// Bind the texture after rendering.
|
||||
GL11.glBindTexture(GL11.GL_TEXTURE_2D, image.getTexture().getTextureID());
|
||||
GL11.glCopyTexImage2D(GL11.GL_TEXTURE_2D, 0, GL11.GL_RGBA, 0, 0,
|
||||
image.getTexture().getTextureWidth(),
|
||||
image.getTexture().getTextureHeight(), 0);
|
||||
|
||||
try {
|
||||
Display.makeCurrent();
|
||||
} catch (LWJGLException e) {
|
||||
Log.error(e);
|
||||
}
|
||||
|
||||
SlickCallable.leaveSafeBlock();
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.newdawn.slick.Graphics#enable()
|
||||
*/
|
||||
protected void enable() {
|
||||
SlickCallable.enterSafeBlock();
|
||||
|
||||
try {
|
||||
if (pbuffer.isBufferLost()) {
|
||||
pbuffer.destroy();
|
||||
init();
|
||||
}
|
||||
|
||||
pbuffer.makeCurrent();
|
||||
} catch (Exception e) {
|
||||
Log.error("Failed to recreate the PBuffer");
|
||||
Log.error(e);
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
|
||||
// Put the renderer contents to the texture
|
||||
TextureImpl.unbind();
|
||||
initGL();
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialise the GL context
|
||||
*/
|
||||
protected void initGL() {
|
||||
GL11.glEnable(GL11.GL_TEXTURE_2D);
|
||||
GL11.glShadeModel(GL11.GL_SMOOTH);
|
||||
GL11.glDisable(GL11.GL_DEPTH_TEST);
|
||||
GL11.glDisable(GL11.GL_LIGHTING);
|
||||
|
||||
GL11.glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
|
||||
GL11.glClearDepth(1);
|
||||
|
||||
GL11.glEnable(GL11.GL_BLEND);
|
||||
GL11.glBlendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA);
|
||||
|
||||
GL11.glViewport(0,0,screenWidth,screenHeight);
|
||||
GL11.glMatrixMode(GL11.GL_MODELVIEW);
|
||||
GL11.glLoadIdentity();
|
||||
|
||||
enterOrtho();
|
||||
}
|
||||
|
||||
/**
|
||||
* Enter the orthographic mode
|
||||
*/
|
||||
protected void enterOrtho() {
|
||||
GL11.glMatrixMode(GL11.GL_PROJECTION);
|
||||
GL11.glLoadIdentity();
|
||||
GL11.glOrtho(0, screenWidth, 0, screenHeight, 1, -1);
|
||||
GL11.glMatrixMode(GL11.GL_MODELVIEW);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.newdawn.slick.Graphics#destroy()
|
||||
*/
|
||||
public void destroy() {
|
||||
super.destroy();
|
||||
|
||||
pbuffer.destroy();
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.newdawn.slick.Graphics#flush()
|
||||
*/
|
||||
public void flush() {
|
||||
super.flush();
|
||||
|
||||
image.flushPixelData();
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user