/* Copyright (C) 2001, 2006 United States Government as represented by the Administrator of the National Aeronautics and Space Administration. All Rights Reserved. */ package gov.nasa.worldwind; import gov.nasa.worldwind.cache.*; import gov.nasa.worldwind.event.*; import gov.nasa.worldwind.geom.*; import gov.nasa.worldwind.layers.*; import gov.nasa.worldwind.pick.*; import gov.nasa.worldwind.util.Logging; import gov.nasa.worldwind.util.*; import javax.media.opengl.*; import java.beans.*; import java.util.logging.Level; /** * A non-platform specific {@link WorldWindow} class. This class can be aggregated into platform-specific classes to * provide the core functionality of World Wind. * * @author Tom Gaskins * @version $Id: WorldWindowGLAutoDrawable.java 5121 2008-04-22 17:54:54Z tgaskins $ */ public class WorldWindowGLAutoDrawable extends WorldWindowImpl implements WorldWindowGLDrawable, GLEventListener { private GLAutoDrawable drawable; private boolean shuttingDown = false; /** * Construct a new <code>WorldWindowGLCanvase</code> for a specified {@link GLDrawable}. */ public WorldWindowGLAutoDrawable() { SceneController sc = this.getSceneController(); if (sc != null) { sc.addPropertyChangeListener(this); } } public void initDrawable(GLAutoDrawable glAutoDrawable) { if (glAutoDrawable == null) { String msg = Logging.getMessage("nullValue.DrawableIsNull"); Logging.logger().severe(msg); throw new IllegalArgumentException(msg); } this.drawable = glAutoDrawable; this.drawable.setAutoSwapBufferMode(false); this.drawable.addGLEventListener(this); } public void initTextureCache(TextureCache textureCache) { if (textureCache == null) { String msg = Logging.getMessage("nullValue.TextureCacheIsNull"); Logging.logger().severe(msg); throw new IllegalArgumentException(msg); } this.setTextureCache(textureCache); } @Override /** * Causes resources used by this World Window to be freed. The resources are not freed immediately. Instead, in * order to have the OpenGL context current during clean up, a redraw of the World Window is requested and the * resources are freed when the window system requests the repaint. No actual redraw is performed during that call. */ public void shutdown() { this.shuttingDown = true; this.drawable.repaint(); // Queue a JOGL repaint request. Cleanup is done in display() while GL context current. } @Override public void propertyChange(PropertyChangeEvent propertyChangeEvent) { if (propertyChangeEvent == null) { String msg = Logging.getMessage("nullValue.PropertyChangeEventIsNull"); Logging.logger().severe(msg); throw new IllegalArgumentException(msg); } if (this.drawable != null) this.drawable.repaint(); // Queue a JOGL repaint request. } /** * See {@link GLEventListener#init(GLAutoDrawable)}. * * @param glAutoDrawable the drawable */ public void init(GLAutoDrawable glAutoDrawable) { if (!glAutoDrawable.getGL().isFunctionAvailable("glActiveTexture")) { this.firePropertyChange("gov.nasa.worldwind.UnsupportedMethod", "glActiveTexture", null); } // Clear the texture cache if the window is reinitializing, most likely with a new gl hardware context. if (this.getTextureCache() != null) this.getTextureCache().clear(); this.getSceneController().reinitialize(); if (this.getModel() != null && this.getModel().getLayers() != null) { for (Layer layer : this.getModel().getLayers()) { layer.dispose(); } } // this.drawable.setGL(new DebugGL(this.drawable.getGL())); } /** * See {@link GLEventListener#display(GLAutoDrawable)}. * * @param glAutoDrawable the drawable * @throws IllegalStateException if no {@link SceneController} exists for this canvas */ public void display(GLAutoDrawable glAutoDrawable) { if (this.shuttingDown) { try { super.shutdown(); } catch (Exception e) { Logging.logger().log(Level.SEVERE, Logging.getMessage( "WorldWindowGLCanvas.ExceptionWhileShuttingDownWorldWindow"), e); } this.shuttingDown = false; return; } try { SceneController sc = this.getSceneController(); if (sc == null) { Logging.logger().severe("WorldWindowGLCanvas.ScnCntrllerNullOnRepaint"); throw new IllegalStateException(Logging.getMessage("WorldWindowGLCanvas.ScnCntrllerNullOnRepaint")); } Position positionAtStart = this.getCurrentPosition(); PickedObject selectionAtStart = this.getCurrentSelection(); try { this.callRenderingListeners(new RenderingEvent(this.drawable, RenderingEvent.BEFORE_RENDERING)); } catch (Exception e) { Logging.logger().log(Level.SEVERE, Logging.getMessage("WorldWindowGLAutoDrawable.ExceptionDuringGLEventListenerDisplay"), e); } this.doDisplay(); try { this.callRenderingListeners(new RenderingEvent(this.drawable, RenderingEvent.BEFORE_BUFFER_SWAP)); } catch (Exception e) { Logging.logger().log(Level.SEVERE, Logging.getMessage("WorldWindowGLAutoDrawable.ExceptionDuringGLEventListenerDisplay"), e); } this.doSwapBuffers(this.drawable); Double frameTime = sc.getFrameTime(); if (frameTime != null) this.setValue(PerformanceStatistic.FRAME_TIME, frameTime); Double frameRate = sc.getFramesPerSecond(); if (frameTime != null) this.setValue(PerformanceStatistic.FRAME_RATE, frameRate); this.callRenderingListeners(new RenderingEvent(this.drawable, RenderingEvent.AFTER_BUFFER_SWAP)); // Position and selection notification occurs only on triggering conditions, not same-state conditions: // start == null, end == null: nothing selected -- don't notify // start == null, end != null: something now selected -- notify // start != null, end == null: something was selected but no longer is -- notify // start != null, end != null, start != end: something new was selected -- notify // start != null, end != null, start == end: same thing is selected -- don't notify Position positionAtEnd = this.getCurrentPosition(); if (positionAtStart != null || positionAtEnd != null) { if (positionAtStart != positionAtEnd) this.callPositionListeners(new PositionEvent(this.drawable, sc.getPickPoint(), positionAtStart, positionAtEnd)); } PickedObject selectionAtEnd = this.getCurrentSelection(); if (selectionAtStart != null || selectionAtEnd != null) { if (selectionAtStart != selectionAtEnd) this.callSelectListeners(new SelectEvent(this.drawable, SelectEvent.ROLLOVER, sc.getPickPoint(), sc.getPickedObjectList())); } } catch (Exception e) { Logging.logger().log(Level.SEVERE, Logging.getMessage( "WorldWindowGLCanvas.ExceptionAttemptingRepaintWorldWindow"), e); } } protected void doDisplay() { this.getSceneController().repaint(); } protected void doSwapBuffers(GLAutoDrawable drawable) { drawable.swapBuffers(); } /** * See {@link GLEventListener#reshape(GLAutoDrawable,int,int,int,int)}. * * @param glAutoDrawable the drawable */ public void reshape(GLAutoDrawable glAutoDrawable, int x, int y, int w, int h) { } /** * See {@link GLEventListener#displayChanged(GLAutoDrawable,boolean,boolean)}. * * @param glAutoDrawable the drawable */ public void displayChanged(GLAutoDrawable glAutoDrawable, boolean b, boolean b1) { Logging.logger().finest("WorldWindowGLCanvas.DisplayEventListenersDisplayChangedMethodCalled"); } public void redrawNow() { if (this.drawable != null) this.drawable.display(); } }