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");
}
}