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
This commit is contained in:
parent
1843916822
commit
9b9db3bd31
1107
engine/src/jogl/com/jme/audio/joal/JoalAudioRenderer.java
Normal file
1107
engine/src/jogl/com/jme/audio/joal/JoalAudioRenderer.java
Normal file
File diff suppressed because it is too large
Load Diff
1226
engine/src/jogl/com/jme3/renderer/jogl/JoglGL1Renderer.java
Normal file
1226
engine/src/jogl/com/jme3/renderer/jogl/JoglGL1Renderer.java
Normal file
File diff suppressed because it is too large
Load Diff
1877
engine/src/jogl/com/jme3/renderer/jogl/JoglRenderer.java
Normal file
1877
engine/src/jogl/com/jme3/renderer/jogl/JoglRenderer.java
Normal file
File diff suppressed because it is too large
Load Diff
386
engine/src/jogl/com/jme3/renderer/jogl/TextureUtil.java
Normal file
386
engine/src/jogl/com/jme3/renderer/jogl/TextureUtil.java
Normal file
@ -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];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
182
engine/src/jogl/com/jme3/system/jogl/JoglAbstractDisplay.java
Normal file
182
engine/src/jogl/com/jme3/system/jogl/JoglAbstractDisplay.java
Normal file
@ -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) {
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
129
engine/src/jogl/com/jme3/system/jogl/JoglCanvas.java
Normal file
129
engine/src/jogl/com/jme3/system/jogl/JoglCanvas.java
Normal file
@ -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) {
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
146
engine/src/jogl/com/jme3/system/jogl/JoglContext.java
Normal file
146
engine/src/jogl/com/jme3/system/jogl/JoglContext.java
Normal file
@ -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();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
307
engine/src/jogl/com/jme3/system/jogl/JoglDisplay.java
Normal file
307
engine/src/jogl/com/jme3/system/jogl/JoglDisplay.java
Normal file
@ -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…
x
Reference in New Issue
Block a user