* Canvas is now using pbuffer workaround, allowing renderer to acquire renderer capabilities even if the canvas is not visible yet.
* Handling of context destruction is now handled individually for displays and canvases. For canvas, this allows it to destroy the pbuffer in addition to the display. * VertexBuffer now has better detection for data size changes, might prevent GL errors in certain cases. NOTE: VertexBuffer.updateData() is generally more stable than VertexBuffer.setUpdateNeeded(). Refrain from using setUpdateNeeded() .. its an internal call anyway. Using it directly could cause GL errors. git-svn-id: https://jmonkeyengine.googlecode.com/svn/trunk@7374 75d07b2b-3a1a-0410-a2c5-0572b91ccdca
This commit is contained in:
parent
4b52dba7f8
commit
0d0454f248
@ -225,6 +225,7 @@ public class VertexBuffer extends GLObject implements Savable, Cloneable {
|
|||||||
}
|
}
|
||||||
|
|
||||||
protected int offset = 0;
|
protected int offset = 0;
|
||||||
|
protected int lastLimit = 0;
|
||||||
protected int stride = 0;
|
protected int stride = 0;
|
||||||
protected int components = 0;
|
protected int components = 0;
|
||||||
|
|
||||||
@ -233,7 +234,6 @@ public class VertexBuffer extends GLObject implements Savable, Cloneable {
|
|||||||
*/
|
*/
|
||||||
protected transient int componentsLength = 0;
|
protected transient int componentsLength = 0;
|
||||||
protected Buffer data = null;
|
protected Buffer data = null;
|
||||||
protected transient ByteBuffer mappedData;
|
|
||||||
protected Usage usage;
|
protected Usage usage;
|
||||||
protected Type bufType;
|
protected Type bufType;
|
||||||
protected Format format;
|
protected Format format;
|
||||||
@ -303,14 +303,6 @@ public class VertexBuffer extends GLObject implements Savable, Cloneable {
|
|||||||
return data;
|
return data;
|
||||||
}
|
}
|
||||||
|
|
||||||
public ByteBuffer getMappedData() {
|
|
||||||
return mappedData;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setMappedData(ByteBuffer mappedData) {
|
|
||||||
this.mappedData = mappedData;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return The usage of this buffer. See {@link Usage} for more
|
* @return The usage of this buffer. See {@link Usage} for more
|
||||||
* information.
|
* information.
|
||||||
@ -403,6 +395,7 @@ public class VertexBuffer extends GLObject implements Savable, Cloneable {
|
|||||||
this.usage = usage;
|
this.usage = usage;
|
||||||
this.format = format;
|
this.format = format;
|
||||||
this.componentsLength = components * format.getComponentSize();
|
this.componentsLength = components * format.getComponentSize();
|
||||||
|
this.lastLimit = data.limit();
|
||||||
setUpdateNeeded();
|
setUpdateNeeded();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -424,8 +417,9 @@ public class VertexBuffer extends GLObject implements Savable, Cloneable {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// will force renderer to call glBufferData again
|
// will force renderer to call glBufferData again
|
||||||
if (this.data.capacity() != data.capacity()){
|
if (this.data.getClass() != data.getClass() || data.limit() != lastLimit){
|
||||||
dataSizeChanged = true;
|
dataSizeChanged = true;
|
||||||
|
lastLimit = data.limit();
|
||||||
}
|
}
|
||||||
this.data = data;
|
this.data = data;
|
||||||
setUpdateNeeded();
|
setUpdateNeeded();
|
||||||
@ -696,10 +690,13 @@ public class VertexBuffer extends GLObject implements Savable, Cloneable {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public VertexBuffer clone(){
|
public VertexBuffer clone(){
|
||||||
// NOTE: Superclass GLObject automatically creates shallow clone
|
// NOTE: Superclass GLObject automatically creates shallow clone
|
||||||
// e.g re-use ID.
|
// e.g re-use ID.
|
||||||
VertexBuffer vb = (VertexBuffer) super.clone();
|
VertexBuffer vb = (VertexBuffer) super.clone();
|
||||||
|
vb.handleRef = new Object();
|
||||||
|
vb.id = -1;
|
||||||
if (data != null)
|
if (data != null)
|
||||||
vb.updateData(BufferUtils.clone(data));
|
vb.updateData(BufferUtils.clone(data));
|
||||||
|
|
||||||
|
@ -73,7 +73,6 @@ public class WireFrustum extends Mesh {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
FloatBuffer b = BufferUtils.createFloatBuffer(points);
|
FloatBuffer b = BufferUtils.createFloatBuffer(points);
|
||||||
FloatBuffer a = (FloatBuffer) vb.getData();
|
FloatBuffer a = (FloatBuffer) vb.getData();
|
||||||
b.rewind();
|
b.rewind();
|
||||||
@ -81,7 +80,7 @@ public class WireFrustum extends Mesh {
|
|||||||
a.put(b);
|
a.put(b);
|
||||||
a.rewind();
|
a.rewind();
|
||||||
|
|
||||||
vb.setUpdateNeeded();
|
vb.updateData(a);
|
||||||
|
|
||||||
updateBound();
|
updateBound();
|
||||||
}
|
}
|
||||||
|
@ -417,9 +417,9 @@ public class LwjglRenderer implements Renderer {
|
|||||||
public void resetGLObjects() {
|
public void resetGLObjects() {
|
||||||
objManager.resetObjects();
|
objManager.resetObjects();
|
||||||
statistics.clearMemory();
|
statistics.clearMemory();
|
||||||
|
context.reset();
|
||||||
boundShader = null;
|
boundShader = null;
|
||||||
lastFb = null;
|
lastFb = null;
|
||||||
context.reset();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void cleanup() {
|
public void cleanup() {
|
||||||
|
@ -81,7 +81,10 @@ public abstract class LwjglAbstractDisplay extends LwjglContext implements Runna
|
|||||||
*/
|
*/
|
||||||
protected abstract void createContext(AppSettings settings) throws LWJGLException;
|
protected abstract void createContext(AppSettings settings) throws LWJGLException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Destroy the context.
|
||||||
|
*/
|
||||||
|
protected abstract void destroyContext();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Does LWJGL display initialization in the OpenGL thread
|
* Does LWJGL display initialization in the OpenGL thread
|
||||||
@ -97,10 +100,12 @@ public abstract class LwjglAbstractDisplay extends LwjglContext implements Runna
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
// For canvas, this wont happen until its initialized.
|
// For canvas, this will create a pbuffer,
|
||||||
|
// allowing us to query information.
|
||||||
|
// When the canvas context becomes available, it will
|
||||||
|
// be replaced seamlessly.
|
||||||
createContext(settings);
|
createContext(settings);
|
||||||
if (renderable.get()) // assumes createContext will set this flag
|
printContextInitInfo();
|
||||||
printContextInitInfo();
|
|
||||||
|
|
||||||
created.set(true);
|
created.set(true);
|
||||||
} catch (Exception ex){
|
} catch (Exception ex){
|
||||||
@ -137,6 +142,9 @@ public abstract class LwjglAbstractDisplay extends LwjglContext implements Runna
|
|||||||
|
|
||||||
listener.update();
|
listener.update();
|
||||||
|
|
||||||
|
// All this does is call swap buffers
|
||||||
|
// If the canvas is not active, there's no need to waste time
|
||||||
|
// doing that ..
|
||||||
if (renderable.get()){
|
if (renderable.get()){
|
||||||
assert checkGLError();
|
assert checkGLError();
|
||||||
|
|
||||||
@ -158,22 +166,16 @@ public abstract class LwjglAbstractDisplay extends LwjglContext implements Runna
|
|||||||
if (frameRate > 0)
|
if (frameRate > 0)
|
||||||
Display.sync(frameRate);
|
Display.sync(frameRate);
|
||||||
|
|
||||||
if (renderable.get() && autoFlush)
|
// Subclasses just call GLObjectManager clean up objects here
|
||||||
renderer.onFrame();
|
// it is safe .. for now.
|
||||||
|
renderer.onFrame();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* De-initialize in the OpenGL thread.
|
* De-initialize in the OpenGL thread.
|
||||||
*/
|
*/
|
||||||
protected void deinitInThread(){
|
protected void deinitInThread(){
|
||||||
if (Display.isCreated()){
|
destroyContext();
|
||||||
renderer.cleanup();
|
|
||||||
Display.destroy();
|
|
||||||
}else{
|
|
||||||
// If using canvas temporary closing, the display would
|
|
||||||
// be closed at this point
|
|
||||||
renderer.resetGLObjects();
|
|
||||||
}
|
|
||||||
|
|
||||||
listener.destroy();
|
listener.destroy();
|
||||||
logger.info("Display destroyed.");
|
logger.info("Display destroyed.");
|
||||||
|
@ -43,10 +43,10 @@ import java.util.logging.Level;
|
|||||||
import java.util.logging.Logger;
|
import java.util.logging.Logger;
|
||||||
import javax.swing.SwingUtilities;
|
import javax.swing.SwingUtilities;
|
||||||
import org.lwjgl.LWJGLException;
|
import org.lwjgl.LWJGLException;
|
||||||
import org.lwjgl.input.Controllers;
|
|
||||||
import org.lwjgl.input.Keyboard;
|
import org.lwjgl.input.Keyboard;
|
||||||
import org.lwjgl.input.Mouse;
|
import org.lwjgl.input.Mouse;
|
||||||
import org.lwjgl.opengl.Display;
|
import org.lwjgl.opengl.Display;
|
||||||
|
import org.lwjgl.opengl.Pbuffer;
|
||||||
import org.lwjgl.opengl.PixelFormat;
|
import org.lwjgl.opengl.PixelFormat;
|
||||||
|
|
||||||
public class LwjglCanvas extends LwjglAbstractDisplay implements JmeCanvasContext {
|
public class LwjglCanvas extends LwjglAbstractDisplay implements JmeCanvasContext {
|
||||||
@ -63,67 +63,72 @@ public class LwjglCanvas extends LwjglAbstractDisplay implements JmeCanvasContex
|
|||||||
private Thread renderThread;
|
private Thread renderThread;
|
||||||
private boolean runningFirstTime = true;
|
private boolean runningFirstTime = true;
|
||||||
private boolean mouseWasGrabbed = false;
|
private boolean mouseWasGrabbed = false;
|
||||||
private boolean mouseActive, keyboardActive, joyActive;
|
private boolean mouseActive, keyboardActive;
|
||||||
|
|
||||||
|
private Pbuffer pbuffer;
|
||||||
|
|
||||||
|
private class GLCanvas extends Canvas {
|
||||||
|
@Override
|
||||||
|
public void addNotify(){
|
||||||
|
super.addNotify();
|
||||||
|
|
||||||
|
if (renderThread != null && renderThread.getState() == Thread.State.TERMINATED)
|
||||||
|
return; // already destroyed.
|
||||||
|
|
||||||
|
if (renderThread == null){
|
||||||
|
logger.log(Level.INFO, "EDT: Creating OGL thread.");
|
||||||
|
|
||||||
|
// Also set some settings on the canvas here.
|
||||||
|
// So we don't do it outside the AWT thread.
|
||||||
|
canvas.setFocusable(true);
|
||||||
|
canvas.setIgnoreRepaint(true);
|
||||||
|
|
||||||
|
renderThread = new Thread(LwjglCanvas.this, "LWJGL Renderer Thread");
|
||||||
|
renderThread.start();
|
||||||
|
}else if (needClose.get()){
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
logger.log(Level.INFO, "EDT: Notifying OGL that canvas is visible..");
|
||||||
|
needRestoreCanvas.set(true);
|
||||||
|
|
||||||
|
// NOTE: no need to wait for OGL to initialize the canvas,
|
||||||
|
// it can happen at any time.
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void removeNotify(){
|
||||||
|
if (needClose.get()){
|
||||||
|
logger.log(Level.INFO, "EDT: Application is stopped. Not restoring canvas.");
|
||||||
|
super.removeNotify();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// We must tell GL context to shutdown and wait for it to
|
||||||
|
// shutdown, otherwise, issues will occur.
|
||||||
|
logger.log(Level.INFO, "EDT: Notifying OGL that canvas is about to become invisible..");
|
||||||
|
needDestroyCanvas.set(true);
|
||||||
|
try {
|
||||||
|
actionRequiredBarrier.await();
|
||||||
|
} catch (InterruptedException ex) {
|
||||||
|
logger.log(Level.SEVERE, "EDT: Interrupted! ", ex);
|
||||||
|
} catch (BrokenBarrierException ex){
|
||||||
|
logger.log(Level.SEVERE, "EDT: Broken barrier! ", ex);
|
||||||
|
}
|
||||||
|
|
||||||
|
logger.log(Level.INFO, "EDT: Acknowledged receipt of canvas death");
|
||||||
|
// GL context is dead at this point
|
||||||
|
|
||||||
|
// Reset barrier for future use
|
||||||
|
actionRequiredBarrier.reset();
|
||||||
|
|
||||||
|
super.removeNotify();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public LwjglCanvas(){
|
public LwjglCanvas(){
|
||||||
super();
|
super();
|
||||||
|
canvas = new GLCanvas();
|
||||||
canvas = new Canvas(){
|
|
||||||
@Override
|
|
||||||
public void addNotify(){
|
|
||||||
super.addNotify();
|
|
||||||
|
|
||||||
if (renderThread != null && renderThread.getState() == Thread.State.TERMINATED)
|
|
||||||
return; // already destroyed.
|
|
||||||
|
|
||||||
if (renderThread == null){
|
|
||||||
logger.log(Level.INFO, "EDT: Creating OGL thread.");
|
|
||||||
|
|
||||||
renderThread = new Thread(LwjglCanvas.this, "LWJGL Renderer Thread");
|
|
||||||
renderThread.start();
|
|
||||||
}else if (needClose.get()){
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
logger.log(Level.INFO, "EDT: Notifying OGL that canvas is visible..");
|
|
||||||
needRestoreCanvas.set(true);
|
|
||||||
|
|
||||||
// NOTE: no need to wait for OGL to initialize the canvas,
|
|
||||||
// it can happen at any time.
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void removeNotify(){
|
|
||||||
if (needClose.get()){
|
|
||||||
logger.log(Level.INFO, "EDT: Application is stopped. Not restoring canvas.");
|
|
||||||
super.removeNotify();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// We must tell GL context to shutdown and wait for it to
|
|
||||||
// shutdown, otherwise, issues will occur.
|
|
||||||
logger.log(Level.INFO, "EDT: Sending destroy request..");
|
|
||||||
needDestroyCanvas.set(true);
|
|
||||||
try {
|
|
||||||
actionRequiredBarrier.await();
|
|
||||||
} catch (InterruptedException ex) {
|
|
||||||
logger.log(Level.SEVERE, "EDT: Interrupted! ", ex);
|
|
||||||
} catch (BrokenBarrierException ex){
|
|
||||||
logger.log(Level.SEVERE, "EDT: Broken barrier! ", ex);
|
|
||||||
}
|
|
||||||
|
|
||||||
logger.log(Level.INFO, "EDT: Acknowledged receipt of destroy request!");
|
|
||||||
// GL context is dead at this point
|
|
||||||
|
|
||||||
// Reset barrier for future use
|
|
||||||
actionRequiredBarrier.reset();
|
|
||||||
|
|
||||||
super.removeNotify();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
canvas.setFocusable(true);
|
|
||||||
canvas.setIgnoreRepaint(true);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -150,6 +155,8 @@ public class LwjglCanvas extends LwjglAbstractDisplay implements JmeCanvasContex
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void restart() {
|
public void restart() {
|
||||||
|
frameRate = settings.getFrameRate();
|
||||||
|
// TODO: Handle other cases, like change of pixel format, etc.
|
||||||
}
|
}
|
||||||
|
|
||||||
public Canvas getCanvas(){
|
public Canvas getCanvas(){
|
||||||
@ -194,7 +201,6 @@ public class LwjglCanvas extends LwjglAbstractDisplay implements JmeCanvasContex
|
|||||||
private void pauseCanvas(){
|
private void pauseCanvas(){
|
||||||
mouseActive = Mouse.isCreated();
|
mouseActive = Mouse.isCreated();
|
||||||
keyboardActive = Keyboard.isCreated();
|
keyboardActive = Keyboard.isCreated();
|
||||||
joyActive = Controllers.isCreated();
|
|
||||||
|
|
||||||
if (mouseActive && Mouse.isGrabbed()){
|
if (mouseActive && Mouse.isGrabbed()){
|
||||||
Mouse.setGrabbed(false);
|
Mouse.setGrabbed(false);
|
||||||
@ -205,13 +211,11 @@ public class LwjglCanvas extends LwjglAbstractDisplay implements JmeCanvasContex
|
|||||||
Mouse.destroy();
|
Mouse.destroy();
|
||||||
if (keyboardActive)
|
if (keyboardActive)
|
||||||
Keyboard.destroy();
|
Keyboard.destroy();
|
||||||
if (joyActive)
|
|
||||||
Controllers.destroy();
|
|
||||||
|
|
||||||
logger.log(Level.INFO, "OGL: Destroying display (temporarily)");
|
|
||||||
Display.destroy();
|
|
||||||
|
|
||||||
|
logger.log(Level.INFO, "OGL: Canvas will become invisible! Destroying ..");
|
||||||
|
|
||||||
renderable.set(false);
|
renderable.set(false);
|
||||||
|
destroyContext();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -234,9 +238,10 @@ public class LwjglCanvas extends LwjglAbstractDisplay implements JmeCanvasContex
|
|||||||
createContext(settings);
|
createContext(settings);
|
||||||
|
|
||||||
// must call after createContext, as renderer might be null
|
// must call after createContext, as renderer might be null
|
||||||
renderer.resetGLObjects();
|
// renderer.resetGLObjects();
|
||||||
|
|
||||||
logger.log(Level.INFO, "OGL: Waiting for display to become active..");
|
logger.log(Level.INFO, "OGL: Waiting for display to become active..");
|
||||||
|
// NOTE: A deadlock will happen here if createContext had an exception
|
||||||
while (!Display.isCreated()){
|
while (!Display.isCreated()){
|
||||||
try {
|
try {
|
||||||
Thread.sleep(10);
|
Thread.sleep(10);
|
||||||
@ -269,33 +274,101 @@ public class LwjglCanvas extends LwjglAbstractDisplay implements JmeCanvasContex
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Makes sure the pbuffer is available and ready for use
|
||||||
|
*/
|
||||||
|
protected void makePbufferAvailable() throws LWJGLException{
|
||||||
|
if (pbuffer == null || pbuffer.isBufferLost()){
|
||||||
|
if (pbuffer != null && pbuffer.isBufferLost()){
|
||||||
|
pbuffer.releaseContext();
|
||||||
|
pbuffer.destroy();
|
||||||
|
}
|
||||||
|
pbuffer = new Pbuffer(1, 1, new PixelFormat(0, 0, 0), null);
|
||||||
|
logger.log(Level.INFO, "OGL: Pbuffer has been created");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This is called:
|
||||||
|
* 1) When the context thread ends
|
||||||
|
* 2) Any time the canvas becomes non-displayable
|
||||||
|
*/
|
||||||
|
protected void destroyContext(){
|
||||||
|
try {
|
||||||
|
renderer.resetGLObjects();
|
||||||
|
if (Display.isCreated()){
|
||||||
|
Display.releaseContext();
|
||||||
|
Display.destroy();
|
||||||
|
}
|
||||||
|
} catch (LWJGLException ex) {
|
||||||
|
listener.handleError("Failed to destroy context", ex);
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
// The canvas is no longer visible,
|
||||||
|
// but the context thread is still running.
|
||||||
|
if (!needClose.get()){
|
||||||
|
// MUST make sure there's still a context current here ..
|
||||||
|
// Display is dead, make pbuffer available to the system
|
||||||
|
makePbufferAvailable();
|
||||||
|
|
||||||
|
// pbuffer is now available, make it current
|
||||||
|
pbuffer.makeCurrent();
|
||||||
|
}else{
|
||||||
|
// The context thread is no longer running.
|
||||||
|
// Destroy pbuffer.
|
||||||
|
if (pbuffer != null){
|
||||||
|
pbuffer.destroy();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (LWJGLException ex) {
|
||||||
|
listener.handleError("Failed make pbuffer available", ex);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This is called:
|
||||||
|
* 1) When the context thread starts
|
||||||
|
* 2) Any time the canvas becomes displayable again.
|
||||||
|
*/
|
||||||
@Override
|
@Override
|
||||||
protected void createContext(AppSettings settings) {
|
protected void createContext(AppSettings settings) {
|
||||||
// In case canvas is not visible, we still take framerate
|
// In case canvas is not visible, we still take framerate
|
||||||
// from settings to prevent "100% CPU usage"
|
// from settings to prevent "100% CPU usage"
|
||||||
frameRate = settings.getFrameRate();
|
frameRate = settings.getFrameRate();
|
||||||
|
|
||||||
if (!renderable.get())
|
try {
|
||||||
return;
|
// First create the pbuffer, if it is needed.
|
||||||
|
makePbufferAvailable();
|
||||||
|
|
||||||
Display.setVSyncEnabled(settings.isVSync());
|
if (renderable.get()){
|
||||||
|
if (pbuffer.isCurrent()){
|
||||||
|
pbuffer.releaseContext();
|
||||||
|
}
|
||||||
|
|
||||||
try{
|
Display.setVSyncEnabled(settings.isVSync());
|
||||||
Display.setParent(canvas);
|
Display.setParent(canvas);
|
||||||
PixelFormat pf = new PixelFormat(settings.getBitsPerPixel(),
|
PixelFormat pf = new PixelFormat(settings.getBitsPerPixel(),
|
||||||
0,
|
0,
|
||||||
settings.getDepthBits(),
|
settings.getDepthBits(),
|
||||||
settings.getStencilBits(),
|
settings.getStencilBits(),
|
||||||
settings.getSamples());
|
settings.getSamples());
|
||||||
Display.create(pf);
|
Display.create(pf, pbuffer);
|
||||||
Display.makeCurrent();
|
Display.makeCurrent();
|
||||||
|
}else{
|
||||||
|
pbuffer.makeCurrent();
|
||||||
|
}
|
||||||
|
// At this point, the OpenGL context is active.
|
||||||
|
|
||||||
if (runningFirstTime){
|
if (runningFirstTime){
|
||||||
|
// THIS is the part that creates the renderer.
|
||||||
|
// It must always be called, now that we have the pbuffer workaround.
|
||||||
initContextFirstTime();
|
initContextFirstTime();
|
||||||
runningFirstTime = false;
|
runningFirstTime = false;
|
||||||
}
|
}
|
||||||
}catch (LWJGLException ex){
|
} catch (LWJGLException ex) {
|
||||||
listener.handleError("Failed to parent canvas to display", ex);
|
listener.handleError("Failed to initialize OpenGL context", ex);
|
||||||
|
// TODO: Fix deadlock that happens after the error (throw runtime exception?)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -115,8 +115,6 @@ public abstract class LwjglContext implements JmeContext {
|
|||||||
}
|
}
|
||||||
|
|
||||||
protected void initContextFirstTime(){
|
protected void initContextFirstTime(){
|
||||||
assert renderable.get();
|
|
||||||
|
|
||||||
if (GLContext.getCapabilities().OpenGL20){
|
if (GLContext.getCapabilities().OpenGL20){
|
||||||
renderer = new LwjglRenderer();
|
renderer = new LwjglRenderer();
|
||||||
}else{
|
}else{
|
||||||
|
@ -133,6 +133,16 @@ public class LwjglDisplay extends LwjglAbstractDisplay {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected void destroyContext(){
|
||||||
|
try {
|
||||||
|
renderer.cleanup();
|
||||||
|
Display.releaseContext();
|
||||||
|
Display.destroy();
|
||||||
|
} catch (LWJGLException ex) {
|
||||||
|
listener.handleError("Failed to destroy context", ex);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public void create(boolean waitFor){
|
public void create(boolean waitFor){
|
||||||
if (created.get()){
|
if (created.get()){
|
||||||
|
@ -34,6 +34,7 @@ package com.jme3.system.lwjgl;
|
|||||||
|
|
||||||
import com.jme3.math.FastMath;
|
import com.jme3.math.FastMath;
|
||||||
import com.jme3.system.Timer;
|
import com.jme3.system.Timer;
|
||||||
|
import java.util.logging.Level;
|
||||||
import java.util.logging.Logger;
|
import java.util.logging.Logger;
|
||||||
import org.lwjgl.Sys;
|
import org.lwjgl.Sys;
|
||||||
|
|
||||||
@ -81,7 +82,7 @@ public class LwjglTimer extends Timer {
|
|||||||
reset();
|
reset();
|
||||||
|
|
||||||
//print timer resolution info
|
//print timer resolution info
|
||||||
logger.info("Timer resolution: " + LWJGL_TIMER_RES + " ticks per second");
|
logger.log(Level.INFO, "Timer resolution: {0} ticks per second", LWJGL_TIMER_RES);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void reset() {
|
public void reset() {
|
||||||
|
@ -1,11 +1,7 @@
|
|||||||
package com.jme3.math;
|
package com.jme3.math;
|
||||||
|
|
||||||
import static org.junit.Assert.assertEquals;
|
import static org.junit.Assert.assertEquals;
|
||||||
import static org.junit.Assert.assertTrue;
|
|
||||||
import static org.junit.Assert.fail;
|
|
||||||
|
|
||||||
import com.jme3.math.FastMath;
|
|
||||||
import com.jme3.math.Vector2f;
|
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
|
|
||||||
public class TrigonometryTest {
|
public class TrigonometryTest {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user