Updates the renderers based on JOGL 2.0 (and JOAL 1.1.3)

git-svn-id: https://jmonkeyengine.googlecode.com/svn/trunk@9878 75d07b2b-3a1a-0410-a2c5-0572b91ccdca
3.0
jul..om 12 years ago
parent 1843916822
commit 9b9db3bd31
  1. 1107
      engine/src/jogl/com/jme/audio/joal/JoalAudioRenderer.java
  2. 1226
      engine/src/jogl/com/jme3/renderer/jogl/JoglGL1Renderer.java
  3. 1877
      engine/src/jogl/com/jme3/renderer/jogl/JoglRenderer.java
  4. 386
      engine/src/jogl/com/jme3/renderer/jogl/TextureUtil.java
  5. 182
      engine/src/jogl/com/jme3/system/jogl/JoglAbstractDisplay.java
  6. 129
      engine/src/jogl/com/jme3/system/jogl/JoglCanvas.java
  7. 146
      engine/src/jogl/com/jme3/system/jogl/JoglContext.java
  8. 307
      engine/src/jogl/com/jme3/system/jogl/JoglDisplay.java

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

@ -0,0 +1,386 @@
/*
* Copyright (c) 2009-2012 jMonkeyEngine
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* * Neither the name of 'jMonkeyEngine' nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package com.jme3.renderer.jogl;
import com.jme3.renderer.RendererException;
import com.jme3.texture.Image;
import com.jme3.texture.Image.Format;
import java.nio.ByteBuffer;
import javax.media.opengl.GL;
import javax.media.opengl.GL2;
import javax.media.opengl.GL2ES2;
import javax.media.opengl.GL3;
import javax.media.opengl.GLContext;
public class TextureUtil {
public static int convertTextureFormat(Format fmt) {
switch (fmt) {
case Alpha16:
case Alpha8:
return GL.GL_ALPHA;
case Luminance8Alpha8:
case Luminance16Alpha16:
return GL.GL_LUMINANCE_ALPHA;
case Luminance8:
case Luminance16:
return GL.GL_LUMINANCE;
case RGB10:
case RGB16:
case BGR8:
case RGB8:
case RGB565:
return GL.GL_RGB;
case RGB5A1:
case RGBA16:
case RGBA8:
return GL.GL_RGBA;
case Depth:
return GL2ES2.GL_DEPTH_COMPONENT;
default:
throw new UnsupportedOperationException("Unrecognized format: " + fmt);
}
}
public static class GLImageFormat {
int internalFormat;
int format;
int dataType;
boolean compressed;
public GLImageFormat(int internalFormat, int format, int dataType, boolean compressed) {
this.internalFormat = internalFormat;
this.format = format;
this.dataType = dataType;
this.compressed = compressed;
}
}
private static final GLImageFormat[] formatToGL = new GLImageFormat[Format.values().length];
private static void setFormat(Format format, int glInternalFormat, int glFormat, int glDataType, boolean glCompressed){
formatToGL[format.ordinal()] = new GLImageFormat(glInternalFormat, glFormat, glDataType, glCompressed);
}
static {
// Alpha formats
setFormat(Format.Alpha8, GL2.GL_ALPHA8, GL.GL_ALPHA, GL.GL_UNSIGNED_BYTE, false);
setFormat(Format.Alpha16, GL2.GL_ALPHA16, GL.GL_ALPHA, GL.GL_UNSIGNED_SHORT, false);
// Luminance formats
setFormat(Format.Luminance8, GL2.GL_LUMINANCE8, GL.GL_LUMINANCE, GL.GL_UNSIGNED_BYTE, false);
setFormat(Format.Luminance16, GL2.GL_LUMINANCE16, GL.GL_LUMINANCE, GL.GL_UNSIGNED_SHORT, false);
setFormat(Format.Luminance16F, GL2.GL_LUMINANCE16F_ARB, GL.GL_LUMINANCE, GL.GL_HALF_FLOAT, false);
setFormat(Format.Luminance32F, GL.GL_LUMINANCE32F_ARB, GL.GL_LUMINANCE, GL.GL_FLOAT, false);
// Luminance alpha formats
setFormat(Format.Luminance8Alpha8, GL2.GL_LUMINANCE8_ALPHA8, GL.GL_LUMINANCE_ALPHA, GL.GL_UNSIGNED_BYTE, false);
setFormat(Format.Luminance16Alpha16, GL2.GL_LUMINANCE16_ALPHA16, GL.GL_LUMINANCE_ALPHA, GL.GL_UNSIGNED_SHORT, false);
setFormat(Format.Luminance16FAlpha16F, GL2.GL_LUMINANCE_ALPHA16F_ARB, GL2.GL_LUMINANCE_ALPHA, GL2.GL_HALF_FLOAT, false);
// Depth formats
setFormat(Format.Depth, GL2.GL_DEPTH_COMPONENT, GL2.GL_DEPTH_COMPONENT, GL2.GL_UNSIGNED_BYTE, false);
setFormat(Format.Depth16, GL2.GL_DEPTH_COMPONENT16, GL2.GL_DEPTH_COMPONENT, GL2.GL_UNSIGNED_SHORT, false);
setFormat(Format.Depth24, GL2.GL_DEPTH_COMPONENT24, GL2.GL_DEPTH_COMPONENT, GL2.GL_UNSIGNED_INT, false);
setFormat(Format.Depth32, GL2.GL_DEPTH_COMPONENT32, GL2.GL_DEPTH_COMPONENT, GL2.GL_UNSIGNED_INT, false);
setFormat(Format.Depth32F, GL2.GL_DEPTH_COMPONENT32F, GL2.GL_DEPTH_COMPONENT, GL2.GL_FLOAT, false);
// Depth stencil formats
setFormat(Format.Depth24Stencil8, GL3.GL_DEPTH24_STENCIL8, GL3.GL_DEPTH_STENCIL, GL3.GL_UNSIGNED_INT_24_8, false);
// RGB formats
setFormat(Format.BGR8, GL.GL_RGB8, GL2.GL_BGR, GL.GL_UNSIGNED_BYTE, false);
setFormat(Format.RGB8, GL.GL_RGB8, GL.GL_RGB, GL.GL_UNSIGNED_BYTE, false);
// setFormat(Format.RGB10, GL11.GL_RGB10, GL11.GL_RGB, GL12.GL_UNSIGNED_INT_10_10_10_2, false);
setFormat(Format.RGB16, GL2.GL_RGB16, GL.GL_RGB, GL.GL_UNSIGNED_SHORT, false);
setFormat(Format.RGB16F, GL2ES2.GL_RGB16F, GL.GL_RGB, GL.GL_HALF_FLOAT, false);
setFormat(Format.RGB32F, GL.GL_RGB32F, GL.GL_RGB, GL.GL_FLOAT, false);
// Special RGB formats
setFormat(Format.RGB111110F, GL2.GL_R11F_G11F_B10F, GL.GL_RGB, GL.GL_UNSIGNED_INT_10F_11F_11F_REV, false);
setFormat(Format.RGB9E5, GL2.GL_RGB9_E5, GL.GL_RGB, GL2.GL_UNSIGNED_INT_5_9_9_9_REV, false);
setFormat(Format.RGB16F_to_RGB111110F, GL2.GL_R11F_G11F_B10F, GL.GL_RGB, GL.GL_HALF_FLOAT, false);
setFormat(Format.RGB16F_to_RGB9E5, GL2.GL_RGB9_E5, GL.GL_RGB, GL.GL_HALF_FLOAT, false);
// RGBA formats
setFormat(Format.ABGR8, GL.GL_RGBA8, GL2.GL_ABGR_EXT, GL.GL_UNSIGNED_BYTE, false);
setFormat(Format.RGB5A1, GL.GL_RGB5_A1, GL.GL_RGBA, GL.GL_UNSIGNED_SHORT_5_5_5_1, false);
setFormat(Format.ARGB4444, GL.GL_RGBA4, GL2.GL_ABGR_EXT, GL.GL_UNSIGNED_SHORT_4_4_4_4, false);
setFormat(Format.RGBA8, GL.GL_RGBA8, GL.GL_RGBA, GL.GL_UNSIGNED_BYTE, false);
setFormat(Format.RGBA16, GL2.GL_RGBA16, GL.GL_RGBA, GL.GL_UNSIGNED_SHORT, false); // might be incorrect
setFormat(Format.RGBA16F, GL2.GL_RGBA16F, GL.GL_RGBA, GL.GL_HALF_FLOAT, false);
setFormat(Format.RGBA32F, GL.GL_RGBA32F, GL.GL_RGBA, GL.GL_FLOAT, false);
// DXT formats
setFormat(Format.DXT1, GL.GL_COMPRESSED_RGB_S3TC_DXT1_EXT, GL.GL_RGB, GL2.GL_UNSIGNED_BYTE, true);
setFormat(Format.DXT1A, GL.GL_COMPRESSED_RGBA_S3TC_DXT1_EXT, GL.GL_RGBA, GL2.GL_UNSIGNED_BYTE, true);
setFormat(Format.DXT3, GL.GL_COMPRESSED_RGBA_S3TC_DXT3_EXT, GL.GL_RGBA, GL2.GL_UNSIGNED_BYTE, true);
setFormat(Format.DXT5, GL.GL_COMPRESSED_RGBA_S3TC_DXT5_EXT, GL.GL_RGBA, GL2.GL_UNSIGNED_BYTE, true);
// LTC/LATC/3Dc formats
setFormat(Format.LTC, GL2.GL_COMPRESSED_LUMINANCE_LATC1_EXT, GL.GL_LUMINANCE, GL.GL_UNSIGNED_BYTE, true);
setFormat(Format.LATC, GL2.GL_COMPRESSED_LUMINANCE_ALPHA_LATC2_EXT, GL.GL_LUMINANCE_ALPHA, GL.GL_UNSIGNED_BYTE, true);
}
public static GLImageFormat getImageFormat(Format fmt){
GL gl = GLContext.getCurrentGL();
switch (fmt){
case ABGR8:
if (!gl.isExtensionAvailable("GL_EXT_abgr")){
return null;
}
break;
case BGR8:
if (!gl.isExtensionAvailable("GL_VERSION_1_2") && !gl.isExtensionAvailable("EXT_bgra")){
return null;
}
break;
case DXT1:
case DXT1A:
case DXT3:
case DXT5:
if (!gl.isExtensionAvailable("GL_EXT_texture_compression_s3tc")) {
return null;
}
break;
case Depth:
case Depth16:
case Depth24:
case Depth32:
if (!gl.isExtensionAvailable("GL_VERSION_1_4") && !gl.isExtensionAvailable("ARB_depth_texture")){
return null;
}
break;
case Depth24Stencil8:
if (!gl.isExtensionAvailable("GL_VERSION_3_0")){
return null;
}
break;
case Luminance16F:
case Luminance16FAlpha16F:
case Luminance32F:
if (!gl.isExtensionAvailable("GL_ARB_texture_float")){
return null;
}
break;
case RGB16F:
case RGB32F:
case RGBA16F:
case RGBA32F:
if (!gl.isExtensionAvailable("GL_VERSION_3_0") && !gl.isExtensionAvailable("GL_ARB_texture_float")){
return null;
}
break;
case Depth32F:
if (!gl.isExtensionAvailable("GL_VERSION_3_0") && !gl.isExtensionAvailable("GL_NV_depth_buffer_float")){
return null;
}
break;
case LATC:
case LTC:
if (!gl.isExtensionAvailable("GL_EXT_texture_compression_latc")){
return null;
}
break;
case RGB9E5:
case RGB16F_to_RGB9E5:
if (!gl.isExtensionAvailable("GL_VERSION_3_0") && !gl.isExtensionAvailable("GL_EXT_texture_shared_exponent")){
return null;
}
break;
case RGB111110F:
case RGB16F_to_RGB111110F:
if (!gl.isExtensionAvailable("GL_VERSION_3_0") && !gl.isExtensionAvailable("GL_EXT_packed_float")){
return null;
}
break;
}
return formatToGL[fmt.ordinal()];
}
public static GLImageFormat getImageFormatWithError(Format fmt) {
GLImageFormat glFmt = getImageFormat(fmt);
if (glFmt == null) {
throw new RendererException("Image format '" + fmt + "' is unsupported by the video hardware.");
}
return glFmt;
}
public static void uploadTexture(Image image,
int target,
int index,
int border){
GL gl = GLContext.getCurrentGL();
Image.Format fmt = image.getFormat();
GLImageFormat glFmt = getImageFormatWithError(fmt);
ByteBuffer data;
if (index >= 0 && image.getData() != null && image.getData().size() > 0){
data = image.getData(index);
}else{
data = null;
}
int width = image.getWidth();
int height = image.getHeight();
int depth = image.getDepth();
if (data != null) {
gl.glPixelStorei(GL.GL_UNPACK_ALIGNMENT, 1);
}
int[] mipSizes = image.getMipMapSizes();
int pos = 0;
// TODO: Remove unneccessary allocation
if (mipSizes == null){
if (data != null)
mipSizes = new int[]{ data.capacity() };
else
mipSizes = new int[]{ width * height * fmt.getBitsPerPixel() / 8 };
}
boolean subtex = false;
int samples = image.getMultiSamples();
for (int i = 0; i < mipSizes.length; i++){
int mipWidth = Math.max(1, width >> i);
int mipHeight = Math.max(1, height >> i);
int mipDepth = Math.max(1, depth >> i);
if (data != null){
data.position(pos);
data.limit(pos + mipSizes[i]);
}
if (glFmt.compressed && data != null){
if (target == GL2.GL_TEXTURE_3D){
gl.getGL2().glCompressedTexImage3D(target,
i,
glFmt.internalFormat,
mipWidth,
mipHeight,
mipDepth,
0,
border,
data);
}else{
//all other targets use 2D: array, cubemap, 2d
gl.getGL2().glCompressedTexImage2D(target,
i,
glFmt.internalFormat,
mipWidth,
mipHeight,
0,
border,
data);
}
}else{
if (target == GL2.GL_TEXTURE_3D){
gl.getGL2().glTexImage3D(target,
i,
glFmt.internalFormat,
mipWidth,
mipHeight,
mipDepth,
border,
glFmt.format,
glFmt.dataType,
data);
}else if (target == GL.GL_TEXTURE_2D_ARRAY){
// prepare data for 2D array
// or upload slice
if (index == -1){
gl.getGL2().glTexImage3D(target,
0,
glFmt.internalFormat,
mipWidth,
mipHeight,
image.getData().size(), //# of slices
border,
glFmt.format,
glFmt.dataType,
data);
}else{
gl.getGL2().glTexSubImage3D(target,
i, // level
0, // xoffset
0, // yoffset
index, // zoffset
width, // width
height, // height
1, // depth
glFmt.format,
glFmt.dataType,
data);
}
}else{
if (subtex){
if (samples > 1){
throw new IllegalStateException("Cannot update multisample textures");
}
gl.getGL2().glTexSubImage2D(target,
i,
0, 0,
mipWidth, mipHeight,
glFmt.format,
glFmt.dataType,
data);
}else{
if (samples > 1){
gl.getGL2().glTexImage2DMultisample(target,
samples,
glFmt.internalFormat,
mipWidth,
mipHeight,
true);
}else{
gl.getGL2().glTexImage2D(target,
i,
glFmt.internalFormat,
mipWidth,
mipHeight,
border,
glFmt.format,
glFmt.dataType,
data);
}
}
}
}
pos += mipSizes[i];
}
}
}

@ -0,0 +1,182 @@
/*
* Copyright (c) 2009-2012 jMonkeyEngine
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* * Neither the name of 'jMonkeyEngine' nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package com.jme3.system.jogl;
import com.jme3.input.KeyInput;
import com.jme3.input.MouseInput;
import com.jme3.input.TouchInput;
import com.jme3.input.awt.AwtKeyInput;
import com.jme3.input.awt.AwtMouseInput;
import com.jme3.renderer.jogl.JoglRenderer;
import com.jogamp.opengl.util.Animator;
import com.jogamp.opengl.util.AnimatorBase;
import com.jogamp.opengl.util.FPSAnimator;
import java.awt.GraphicsDevice;
import java.awt.GraphicsEnvironment;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.logging.Logger;
import javax.media.opengl.GLAutoDrawable;
import javax.media.opengl.GLCapabilities;
import javax.media.opengl.GLEventListener;
import javax.media.opengl.GLProfile;
import javax.media.opengl.awt.GLCanvas;
public abstract class JoglAbstractDisplay extends JoglContext implements GLEventListener {
private static final Logger logger = Logger.getLogger(JoglAbstractDisplay.class.getName());
protected GraphicsDevice device;
protected GLCanvas canvas;
protected AnimatorBase animator;
protected AtomicBoolean active = new AtomicBoolean(false);
protected boolean wasActive = false;
protected int frameRate;
protected boolean useAwt = true;
protected AtomicBoolean autoFlush = new AtomicBoolean(true);
protected boolean wasAnimating = false;
protected void initGLCanvas() {
device = GraphicsEnvironment.getLocalGraphicsEnvironment().getDefaultScreenDevice();
GLCapabilities caps = new GLCapabilities(GLProfile.getDefault());
caps.setHardwareAccelerated(true);
caps.setDoubleBuffered(true);
caps.setStencilBits(settings.getStencilBits());
caps.setDepthBits(settings.getDepthBits());
if (settings.getSamples() > 1) {
caps.setSampleBuffers(true);
caps.setNumSamples(settings.getSamples());
}
canvas = new GLCanvas(caps) {
@Override
public void addNotify() {
super.addNotify();
onCanvasAdded();
}
@Override
public void removeNotify() {
onCanvasRemoved();
super.removeNotify();
}
};
if (settings.isVSync()) {
// FIXME: it is too early to get the GL instance from the canvas
canvas.getGL().setSwapInterval(1);
}
canvas.setFocusable(true);
canvas.setIgnoreRepaint(true);
canvas.addGLEventListener(this);
// N.B: it is too early to get the GL instance from the canvas
// if (false){
// trace mode
// jME already uses err stream, use out instead
// gl = new TraceGL(gl, System.out);
// }else if (false){
// debug mode
// gl = new DebugGL(gl);
// }else{
// production mode
// }
renderer = new JoglRenderer();
}
protected void startGLCanvas() {
if (frameRate > 0) {
animator = new FPSAnimator(canvas, frameRate);
// ((FPSAnimator)animator).setRunAsFastAsPossible(true);
}
else {
animator = new Animator(canvas);
((Animator) animator).setRunAsFastAsPossible(true);
}
animator.start();
wasAnimating = true;
}
protected void onCanvasAdded() {
}
protected void onCanvasRemoved() {
}
@Override
public KeyInput getKeyInput() {
return new AwtKeyInput(/*canvas*/);
}
@Override
public MouseInput getMouseInput() {
return new AwtMouseInput(/*canvas*/);
}
public TouchInput getTouchInput() {
return null;
}
public void setAutoFlushFrames(boolean enabled) {
autoFlush.set(enabled);
}
/**
* Callback.
*/
public void reshape(GLAutoDrawable drawable, int x, int y, int width, int height) {
listener.reshape(width, height);
}
/**
* Callback.
*/
public void displayChanged(GLAutoDrawable drawable, boolean modeChanged, boolean deviceChanged) {
}
/**
* Callback
*/
public void dispose(GLAutoDrawable drawable) {
}
}

@ -0,0 +1,129 @@
/*
* Copyright (c) 2009-2012 jMonkeyEngine
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* * Neither the name of 'jMonkeyEngine' nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package com.jme3.system.jogl;
import com.jme3.system.JmeCanvasContext;
import java.awt.Canvas;
import java.util.logging.Logger;
import javax.media.opengl.GLAutoDrawable;
public class JoglCanvas extends JoglAbstractDisplay implements JmeCanvasContext {
private static final Logger logger = Logger.getLogger(JoglCanvas.class.getName());
private int width, height;
public JoglCanvas(){
super();
initGLCanvas();
}
public Type getType() {
return Type.Canvas;
}
public void setTitle(String title) {
}
public void restart() {
}
public void create(boolean waitFor){
if (waitFor)
waitFor(true);
}
public void destroy(boolean waitFor){
if (waitFor)
waitFor(false);
}
@Override
protected void onCanvasRemoved(){
super.onCanvasRemoved();
created.set(false);
waitFor(false);
}
@Override
protected void onCanvasAdded(){
startGLCanvas();
}
public void init(GLAutoDrawable drawable) {
canvas.requestFocus();
super.internalCreate();
logger.info("Display created.");
renderer.initialize();
listener.initialize();
}
public void display(GLAutoDrawable glad) {
if (!created.get() && renderer != null){
listener.destroy();
logger.info("Canvas destroyed.");
super.internalDestroy();
return;
}
if (width != canvas.getWidth() || height != canvas.getHeight()){
width = canvas.getWidth();
height = canvas.getHeight();
if (listener != null)
listener.reshape(width, height);
}
boolean flush = autoFlush.get();
if (flush && !wasAnimating){
animator.start();
wasAnimating = true;
}else if (!flush && wasAnimating){
animator.stop();
wasAnimating = false;
}
listener.update();
renderer.onFrame();
}
public Canvas getCanvas() {
return canvas;
}
@Override
public void dispose(GLAutoDrawable arg0) {
}
}

@ -0,0 +1,146 @@
/*
* Copyright (c) 2009-2012 jMonkeyEngine
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* * Neither the name of 'jMonkeyEngine' nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package com.jme3.system.jogl;
import com.jme3.input.JoyInput;
import com.jme3.input.KeyInput;
import com.jme3.input.MouseInput;
import com.jme3.input.awt.AwtKeyInput;
import com.jme3.input.awt.AwtMouseInput;
import com.jme3.renderer.Renderer;
import com.jme3.renderer.jogl.JoglRenderer;
import com.jme3.system.AppSettings;
import com.jme3.system.JmeContext;
import com.jme3.system.NanoTimer;
import com.jme3.system.SystemListener;
import com.jme3.system.Timer;
import java.util.concurrent.atomic.AtomicBoolean;
public abstract class JoglContext implements JmeContext {
protected AtomicBoolean created = new AtomicBoolean(false);
protected AtomicBoolean renderable = new AtomicBoolean(false);
protected final Object createdLock = new Object();
protected AppSettings settings = new AppSettings(true);
protected JoglRenderer renderer;
protected Timer timer;
protected SystemListener listener;
protected AwtKeyInput keyInput;
protected AwtMouseInput mouseInput;
public void setSystemListener(SystemListener listener){
this.listener = listener;
}
public void setSettings(AppSettings settings) {
this.settings.copyFrom(settings);
}
public boolean isRenderable(){
return renderable.get();
}
public AppSettings getSettings() {
return settings;
}
public Renderer getRenderer() {
return renderer;
}
public MouseInput getMouseInput() {
return mouseInput;
}
public KeyInput getKeyInput() {
return keyInput;
}
public JoyInput getJoyInput() {
return null;
}
public Timer getTimer() {
return timer;
}
public boolean isCreated() {
return created.get();
}
public void create(){
create(false);
}
public void destroy(){
destroy(false);
}
protected void waitFor(boolean createdVal){
synchronized (createdLock){
while (created.get() != createdVal){
try {
createdLock.wait();
} catch (InterruptedException ex) {
}
}
}
}
public void internalCreate() {
timer = new NanoTimer();
synchronized (createdLock){
created.set(true);
createdLock.notifyAll();
}
// renderer initialization must happen in subclass.
/*if (renderable.get()){
initContextFirstTime();
}else{
assert getType() == Type.Canvas;
}*/
}
protected void internalDestroy() {
renderer = null;
timer = null;
renderable.set(false);
synchronized (createdLock){
created.set(false);
createdLock.notifyAll();
}
}
}

@ -0,0 +1,307 @@
/*
* Copyright (c) 2009-2012 jMonkeyEngine
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* * Neither the name of 'jMonkeyEngine' nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package com.jme3.system.jogl;
import com.jme3.system.AppSettings;
import java.awt.BorderLayout;
import java.awt.Container;
import java.awt.Dimension;
import java.awt.DisplayMode;
import java.awt.Frame;
import java.awt.Toolkit;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.lang.reflect.InvocationTargetException;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.media.opengl.GLAutoDrawable;
import javax.swing.JFrame;
import javax.swing.SwingUtilities;
public class JoglDisplay extends JoglAbstractDisplay {
private static final Logger logger = Logger.getLogger(JoglDisplay.class.getName());
protected AtomicBoolean windowCloseRequest = new AtomicBoolean(false);
protected AtomicBoolean needClose = new AtomicBoolean(false);
protected AtomicBoolean needRestart = new AtomicBoolean(false);
protected boolean wasInited = false;
protected Frame frame;
public Type getType() {
return Type.Display;
}
protected DisplayMode getFullscreenDisplayMode(DisplayMode[] modes, int width, int height, int bpp, int freq){
for (DisplayMode mode : modes){
if (mode.getWidth() == width
&& mode.getHeight() == height
&& (mode.getBitDepth() == DisplayMode.BIT_DEPTH_MULTI
|| mode.getBitDepth() == bpp
|| (mode.getBitDepth() == 32 && bpp==24))
&& mode.getRefreshRate() == freq){
return mode;
}
}
return null;
}
protected void createGLFrame(){
Container contentPane;
if (useAwt){
frame = new Frame(settings.getTitle());
contentPane = frame;
}else{
frame = new JFrame(settings.getTitle());
contentPane = ((JFrame)frame).getContentPane();
}
contentPane.setLayout(new BorderLayout());
applySettings(settings);
frame.setResizable(false);
frame.setFocusable(true);
// only add canvas after frame is visible
contentPane.add(canvas, BorderLayout.CENTER);
//frame.pack();
// frame.setSize(contentPane.getPreferredSize());
frame.setSize(settings.getWidth(),settings.getHeight());
if (device.getFullScreenWindow() == null){
// now that canvas is attached,
// determine optimal size to contain it
Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();
frame.setLocation((screenSize.width - frame.getWidth()) / 2,
(screenSize.height - frame.getHeight()) / 2);
}
frame.addWindowListener(new WindowAdapter() {
@Override
public void windowClosing(WindowEvent evt) {
windowCloseRequest.set(true);
}
@Override
public void windowActivated(WindowEvent evt) {
active.set(true);
}
@Override
public void windowDeactivated(WindowEvent evt) {
active.set(false);
}
});
}
protected void applySettings(AppSettings settings){
DisplayMode displayMode;
if (settings.getWidth() <= 0 || settings.getHeight() <= 0){
displayMode = device.getDisplayMode();
settings.setResolution(displayMode.getWidth(), displayMode.getHeight());
}else if (settings.isFullscreen()){
displayMode = getFullscreenDisplayMode(device.getDisplayModes(),
settings.getWidth(), settings.getHeight(),
settings.getBitsPerPixel(), settings.getFrequency());
if (displayMode == null)
throw new RuntimeException("Unable to find fullscreen display mode matching settings");
}else{
displayMode = new DisplayMode(settings.getWidth(), settings.getHeight(), DisplayMode.BIT_DEPTH_MULTI, DisplayMode.REFRESH_RATE_UNKNOWN);
}
// FIXME: seems to return false even though
// it is supported..
// if (!device.isDisplayChangeSupported()){
// // must use current device mode if display mode change not supported
// displayMode = device.getDisplayMode();
// settings.setResolution(displayMode.getWidth(), displayMode.getHeight());
// }
frameRate = settings.getFrameRate();
logger.log(Level.INFO, "Selected display mode: {0}x{1}x{2} @{3}",
new Object[]{displayMode.getWidth(),
displayMode.getHeight(),
displayMode.getBitDepth(),
displayMode.getRefreshRate()});
canvas.setSize(displayMode.getWidth(), displayMode.getHeight());
DisplayMode prevDisplayMode = device.getDisplayMode();
if (settings.isFullscreen() && device.isFullScreenSupported()){
frame.setUndecorated(true);
try{
device.setFullScreenWindow(frame);
if (!prevDisplayMode.equals(displayMode)
&& device.isDisplayChangeSupported()){
device.setDisplayMode(displayMode);
}
} catch (Throwable t){
logger.log(Level.SEVERE, "Failed to enter fullscreen mode", t);
device.setFullScreenWindow(null);
}
}else{
if (!device.isFullScreenSupported()){
logger.warning("Fullscreen not supported.");
}else{
frame.setUndecorated(false);
device.setFullScreenWindow(null);
}
frame.setVisible(true);
}
}
private void initInEDT(){
initGLCanvas();
createGLFrame();
startGLCanvas();
}
public void init(GLAutoDrawable drawable){
// prevent initializing twice on restart
if (!wasInited){
canvas.requestFocus();
super.internalCreate();
logger.info("Display created.");
renderer.initialize();
listener.initialize();
wasInited = true;
}
}
public void create(boolean waitFor){
try {
if (waitFor){
try{
SwingUtilities.invokeAndWait(new Runnable() {
public void run() {
initInEDT();
}
});
} catch (InterruptedException ex) {
listener.handleError("Interrupted", ex);
}
}else{
SwingUtilities.invokeLater(new Runnable() {
public void run() {
initInEDT();
}
});
}
} catch (InvocationTargetException ex) {
throw new AssertionError(); // can never happen
}
}
public void destroy(boolean waitFor){
needClose.set(true);
if (waitFor){
waitFor(false);
}
}
public void restart() {
if (created.get()){
needRestart.set(true);
}else{
throw new IllegalStateException("Display not started yet. Cannot restart");
}
}
public void setTitle(String title){
if (frame != null)
frame.setTitle(title);
}
/**
* Callback.
*/
public void display(GLAutoDrawable drawable) {
if (needClose.get()) {
listener.destroy();
animator.stop();
if (settings.isFullscreen()) {
device.setFullScreenWindow(null);
}
frame.dispose();
logger.info("Display destroyed.");
super.internalDestroy();
return;
}
if (windowCloseRequest.get()){
listener.requestClose(false);
windowCloseRequest.set(false);
}
if (needRestart.getAndSet(false)){
// for restarting contexts
if (frame.isVisible()){
animator.stop();
frame.dispose();
createGLFrame();
startGLCanvas();
}
}
// boolean flush = autoFlush.get();
// if (animator.isAnimating() != flush){
// if (flush)
// animator.stop();
// else
// animator.start();
// }
if (wasActive != active.get()){
if (!wasActive){
listener.gainFocus();
wasActive = true;
}else{
listener.loseFocus();
wasActive = false;
}
}
listener.update();
renderer.onFrame();
}
}
Loading…
Cancel
Save