Package ch.blackspirit.graphics.jogl2

Source Code of ch.blackspirit.graphics.jogl2.RealtimeCanvas

/*
* Copyright 2009 Markus Koller
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
*     http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package ch.blackspirit.graphics.jogl2;

import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.GraphicsDevice;
import java.awt.GraphicsEnvironment;
import java.awt.Point;
import java.awt.Toolkit;
import java.awt.event.WindowEvent;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;

import javax.media.nativewindow.AbstractGraphicsDevice;
import javax.media.opengl.GL;
import javax.media.opengl.GL2;
import javax.media.opengl.GLAutoDrawable;
import javax.media.opengl.GLCapabilities;
import javax.media.opengl.GLCapabilitiesChooser;
import javax.media.opengl.GLContext;
import javax.media.opengl.GLDrawableFactory;
import javax.media.opengl.GLException;
import javax.media.opengl.GLPbuffer;
import javax.media.opengl.GLProfile;
import javax.media.opengl.awt.GLCanvas;
import javax.media.opengl.glu.GLU;
import javax.swing.JFrame;

import ch.blackspirit.graphics.DisplayMode;
import ch.blackspirit.graphics.GraphicsListener;
import ch.blackspirit.graphics.Image;
import ch.blackspirit.graphics.ResourceManager;
import ch.blackspirit.graphics.WindowListener;

/**
* @author Markus Koller
*/
final class RealtimeCanvas extends AbstractGraphicsContext implements ch.blackspirit.graphics.RealtimeCanvas, GLExecutor, RuntimeProperties {
  private final Logger LOGGER = Logger.getLogger(this.getClass().getName());
 
  private static final GLCapabilities CAPABILITIES = new GLCapabilities(GLProfile.get(GLProfile.GL2));
  static {
    CAPABILITIES.setDepthBits(0);
    CAPABILITIES.setAlphaBits(8);
    CAPABILITIES.setDoubleBuffered(true);
//    CAPABILITIES.setPBuffer(true);
    // FSAA 4x
//    CAPABILITIES.setSampleBuffers(true);
//    CAPABILITIES.setNumSamples(4);
  }

  static GLCapabilities PBUFFER_CAPABILITIES = new GLCapabilities(GLProfile.get(GLProfile.GL2));
  static {
    PBUFFER_CAPABILITIES.setDoubleBuffered(false);
//    PBUFFER_CAPABILITIES.setAlphaBits(8);
  }
 
  private CanvasProperties properties = new CanvasProperties();
 
  private JFrame frame;
  private String title = "";
  private boolean fullscreen = false;
 
  private boolean usePBuffer = true;

  private GLContext glContext = null;
  private GLCanvas canvas;
  private GLAutoDrawable imageDrawable;
  private RenderContext canvasRenderContext = new RenderContext();
  private RenderContext imageRenderContext = new RenderContext();
 
  private final View view = new View();
  private final ch.blackspirit.graphics.jogl2.ResourceManager resourceManager =
    new ch.blackspirit.graphics.jogl2.ResourceManager(this, this);
  private final ch.blackspirit.graphics.jogl2.ImageFactory imageFactory =
    new ch.blackspirit.graphics.jogl2.ImageFactory(resourceManager);
  private GraphicsDelegate delegate;
  private CanvasGraphics canvasGraphics;
  private GraphicsListener graphicsListener;
  private CanvasGLEventListener canvasGLEventListener;

  private boolean isGlExtBlendSubtractSupported;
  private long maxImageDrawingWidth;
  private long maxImageDrawingHeight;
 
  private GLExecutableGLEventListener executableListener = new GLExecutableGLEventListener();
 
  private final ArrayList<WindowListener> windowListener = new ArrayList<WindowListener>(100);
 
  public RealtimeCanvas(DisplayMode displayMode, CanvasProperties properties) {
    this.properties = properties;
   
    // initialize view size and camera
    if(displayMode == null) {
      // use current mode to initialize
      GraphicsEnvironment env = GraphicsEnvironment.getLocalGraphicsEnvironment();
      GraphicsDevice dev = env.getDefaultScreenDevice();
      java.awt.DisplayMode mode = dev.getDisplayMode();
      view.setSize(mode.getWidth(), mode.getHeight());
    } else {
      view.setSize(displayMode.getWidth(), displayMode.getHeight());
    }
    view.setCamera(0, 0, 0);

    setFullscreen(displayMode);
    initializeGraphics();
  }
  public RealtimeCanvas(int width, int height, CanvasProperties properties) {
    this.properties = properties;

    // initialize view size and camera
    view.setSize(width, height);
    view.setCamera(0, 0, 0);
   
    setWindow(width, height);
    initializeGraphics();
  }
 
  public int getScreenLocationX() {
    return canvas.getLocationOnScreen().x;
  }
  public int getScreenLocationY() {
    return canvas.getLocationOnScreen().y;
  }
 
  private void initializeGraphics() {
    delegate = new JOGLGraphicsDelegate(canvasRenderContext, resourceManager, this);
    canvasGraphics = new CanvasGraphics(delegate, view);
        canvasGLEventListener = new CanvasGLEventListener(this, resourceManager, imageFactory, view, canvasGraphics);
        canvasGLEventListener.setDebugGL(properties.isDebugGL());
        canvasGLEventListener.setTrace(properties.isTraceEnabled());
        canvasGLEventListener.setTraceLevel(properties.getTraceLogLevel());
    canvasRenderContext.setMainGLEventListener(canvasGLEventListener);
       
        executableListener.setDebugGL(properties.isDebugGL());
        executableListener.setTrace(properties.isTraceEnabled());
        executableListener.setTraceLevel(properties.getTraceLogLevel());
       
    SupportGLExecutable supportGLExecutable = new SupportGLExecutable();
    execute(supportGLExecutable);
    isGlExtBlendSubtractSupported = supportGLExecutable.isGlExtBlendSubtractSupported;
    LOGGER.info("Graphics Card info: " + supportGLExecutable.vendor +
        " - " + supportGLExecutable.renderer +
        " - " +  supportGLExecutable.version);
    LOGGER.info("DrawingMode.SUBTRACT supported: " + isGlExtBlendSubtractSupported);
  }
 
  public boolean execute(GLExecutable glExecutable) {
    try {
      GL2 gl = (GL2)GLU.getCurrentGL();
      glExecutable.execute(GLContext.getCurrent().getGLDrawable(), gl);
    } catch(GLException e) {
      // no context current
      try {
        imageDrawable.setAutoSwapBufferMode(false);
        imageRenderContext.setGLEventListener(executableListener);
        executableListener.executable = glExecutable;
        imageDrawable.display();
        imageDrawable.setAutoSwapBufferMode(true);
        imageRenderContext.resetGLEventListener();
      } catch(GLException e2) {
        // TODO This maybe is a real exception due to a problem not just because no canvas is visible
        return false;
      }
    }
    return true;
  }

  private void initialize(int width, int height) {
    GLDrawableFactory drawableFactory = GLDrawableFactory.getFactory(GLProfile.get(GLProfile.GL2));
    AbstractGraphicsDevice graphicsDevice = drawableFactory.getDefaultDevice();

    if(!drawableFactory.canCreateGLPbuffer(graphicsDevice)) {
      throw new RuntimeException("PBuffer not supported but required in this implementation!");
    }
   
    int imageDrawingWidth = properties.getImageDrawingWidth();
    int imageDrawingHeight = properties.getImageDrawingHeight();
    LOGGER.info("Requested image drawing size: " + imageDrawingWidth + "x" + imageDrawingHeight);
   
    if(!(imageDrawable instanceof GLPbuffer)) imageDrawable = null;
    if(imageDrawable == null) {
      boolean cannotCreatePBuffer = !drawableFactory.canCreateGLPbuffer(graphicsDevice);
      // debug fallback
      if(!properties.isPBuffer()) cannotCreatePBuffer = true;
      if(!usePBuffer) cannotCreatePBuffer = true;
      if(!cannotCreatePBuffer) {
        try {
          imageDrawable = drawableFactory.createGLPbuffer(graphicsDevice, PBUFFER_CAPABILITIES, null, imageDrawingWidth, imageDrawingHeight, glContext);
          glContext = imageDrawable.getContext();
          imageRenderContext.setDrawable(imageDrawable);
         
          SupportGLExecutable supportGLExecutable = new SupportGLExecutable();
          execute(supportGLExecutable);
          String vendor = supportGLExecutable.vendor;
          if (vendor != null && vendor.toLowerCase().contains("intel")) {
            imageDrawable.getContext().destroy();
            imageDrawable = null;
            glContext = null;
            usePBuffer = false;
            cannotCreatePBuffer = true;
          }
        } catch(Exception e) {
          cannotCreatePBuffer = true;
          imageDrawable = null;
          glContext = null;
        }
      }
      if(cannotCreatePBuffer)  {
        if (usePBuffer)
          LOGGER.info("Unable to create pbuffer. Using frame buffer for image drawing.");
        else
          LOGGER.info("Not using pbuffer with Intel graphics cards. Using frame buffer for image drawing.");
        imageRenderContext.setDelegateRenderContext(canvasRenderContext);
      }
    }

    if(canvas != null) canvas.getContext().destroy();
    canvas = new NoPaintGLCanvas(CAPABILITIES, null, glContext, null);
    if(glContext == null) glContext = canvas.getContext();
    canvasRenderContext.setDrawable(canvas);
        canvas.setFocusable(false);
        canvas.setFocusTraversalKeysEnabled(false);
        canvas.setEnabled(false);
        canvas.setAutoSwapBufferMode(true);

        if(imageDrawable == null) {
          imageDrawingHeight = height;
          imageDrawingWidth = width;
          imageDrawable = canvas;
        }

        LOGGER.info("Actual image drawing size: " + imageDrawingWidth + "x" + imageDrawingHeight);
        maxImageDrawingHeight = imageDrawingHeight;
        maxImageDrawingWidth = imageDrawingWidth;
  }
 
  private JFrame createFrame() {
    JFrame frame = new JFrame();
    frame.setCursor(Toolkit.getDefaultToolkit().createCustomCursor(
        Toolkit.getDefaultToolkit().getImage(""),
        new Point(0,0),
        "invisible"));
    frame.setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE);
    frame.addWindowListener(new DelegateWindowListener(windowListener));
    frame.setTitle(title);
    return frame;
  }
 
  public void setFullscreen(DisplayMode displayMode) {
    GraphicsEnvironment env = GraphicsEnvironment.getLocalGraphicsEnvironment();
    GraphicsDevice dev = env.getDefaultScreenDevice();

    java.awt.DisplayMode setup = null;
    if(displayMode != null) {
      for(java.awt.DisplayMode mode :dev.getDisplayModes()) {
        if(mode.getWidth() == displayMode.getWidth() &&
            mode.getHeight() == displayMode.getHeight() &&
            mode.getBitDepth() == displayMode.getColorDepth() &&
            mode.getRefreshRate() == displayMode.getRefreshRate()) {
          setup = mode;
        }
      }
      if(setup == null) {
        LOGGER.severe("No Mode with resolution: " + displayMode.getWidth() + "x" + displayMode.getHeight() + " available. Choosing unavailable resolutions should not be possible.");
        throw new RuntimeException("No Mode with resolution: " + displayMode.getWidth() + "x" + displayMode.getHeight() + " available. Choosing unavailable resolutions should not be possible.");
      }
      LOGGER.info("Fullscreen: Width=" + setup.getWidth() +
          " Height=" + setup.getHeight() +
          " BitDepth=" +   setup.getBitDepth() +
          " RefreshRate=" + setup.getRefreshRate());
    }
   
    // Switch to new frame
    JFrame old = frame;
    frame = createFrame();
    if(old != null) {
      old.setVisible(false);
      old.getContentPane().remove(canvas);
      frame.getContentPane().add(canvas);
      old.dispose();
    } else {
      int width;
      int height;
      if(displayMode != null) {
        width = displayMode.getWidth();
        height = displayMode.getHeight();
      } else {
        java.awt.DisplayMode currentMode = dev.getDisplayMode();
        width = currentMode.getWidth();
        height = currentMode.getHeight();
      }
      initialize(width, height);
      frame.getContentPane().add(canvas);
    }
    frame.setUndecorated(true);
    frame.setResizable(false);
    frame.pack();
    frame.setVisible(true);

    dev.setFullScreenWindow(frame);
    if(displayMode!=null) {
      try {
        if(dev.isDisplayChangeSupported()) dev.setDisplayMode(setup);
      } catch(Exception e) {
        LOGGER.log(Level.SEVERE, "Failed to change display mode", e);
      }
    }
    fullscreen = true;
 
  public void setWindow(int width, int height) {
    // Disable fullscreen rendering
    GraphicsEnvironment env = GraphicsEnvironment.getLocalGraphicsEnvironment();
    GraphicsDevice dev = env.getDefaultScreenDevice();
    if(fullscreen) {
      dev.setFullScreenWindow(null);
    }
   
    // Switch to new frame
    JFrame old = frame;
    frame = createFrame();
    if(old != null) {
      old.setVisible(false);
      old.getContentPane().remove(canvas);
      frame.getContentPane().add(canvas);
      old.dispose();
    } else {
      initialize(width, height);
      frame.getContentPane().add(canvas);
    }
    frame.getContentPane().setPreferredSize(new Dimension(width, height));

    // Resizable must be set before pack for proper sizes
    frame.setResizable(false);
    frame.pack();
    frame.setVisible(true);
 
    fullscreen = false;

    LOGGER.info("Window: Width=" + width +
        " Height=" + height);
  }
  public void setWindowTitle(String title) {
    this.title = title;
    if(frame != null) {
      frame.setTitle(title);
    }
  }
  public String getWindowTitle() {
    return title;
  }
  public boolean isFullscreen() {
    return fullscreen;
  }
 
 
//  public void init(GLAutoDrawable arg0) {
//      gl.glLoadIdentity();
//
//    // Lighting
//    gl.glShadeModel(GL.GL_SMOOTH);
//    gl.glLightfv(GL.GL_LIGHT0, GL.GL_SPECULAR, new float[] {1.0f, 1.0f, 1.0f, 1.0f}, 0);
//    gl.glLightfv(GL.GL_LIGHT0, GL.GL_POSITION, new float[] {100.0f, 100.0f, 50.0f, 0.1f}, 0);
//    gl.glEnable(GL.GL_LIGHT0);
//  }

  public int getWidth() {
    return canvas.getWidth();
  }

  public int getHeight() {
    return canvas.getHeight();
  }

  public ch.blackspirit.graphics.ImageFactory getImageFactory() {
    return imageFactory;
  }
  public void addWindowListener(WindowListener windowListener) {
    synchronized (this.windowListener) {
      this.windowListener.add(windowListener);
    }
  }
  public void removeWindowListener(WindowListener windowListener) {
    synchronized (this.windowListener) {
      this.windowListener.remove(windowListener);
    }
  }
  public List<WindowListener> getWindowListeners() {
    return Collections.unmodifiableList(this.windowListener);
  }
 
  public boolean getVSync() {
    return canvasGLEventListener.getVSync();
  }

  public boolean setVSync(boolean enabled) {
    return canvasGLEventListener.setVSync(enabled);
  }
 
  public void dispose() {
    canvas.getContext().destroy();
    imageDrawable.getContext().destroy();
    frame.dispose();
    canvas = null;
    frame = null;
    imageDrawable = null;
  }
  public ResourceManager getResourceManager() {
    return resourceManager;
  }
  public void setFullscreen() {
    setFullscreen(null);
  }
 
  public void draw() {
    if(frame.isVisible()) canvas.display();
    if (canvasGLEventListener.getError() != null) {
      throw canvasGLEventListener.getError();
    } else if (canvasGLEventListener.getRuntimeException() != null) {
      throw canvasGLEventListener.getRuntimeException();
    }
  }
  public GraphicsListener getGraphicsListener() {
    return graphicsListener;
  }
  public void setGraphicsListener(GraphicsListener listener) {
    this.graphicsListener = listener;
    this.canvasGLEventListener.setInitiated(false);
  }
 
  public ch.blackspirit.graphics.ImageGraphicsContext createImageGraphicsContext(Image image) {
    if (!(image instanceof Image)) throw new RuntimeException("Image has not been created by the JOGL Blackspirit Graphics implementation!");
    ch.blackspirit.graphics.jogl2.Image joglImage = (ch.blackspirit.graphics.jogl2.Image)image;
    return new ImageGraphicsContext(joglImage, imageRenderContext, resourceManager, this, properties);
  }

 
  private static final class DelegateWindowListener implements java.awt.event.WindowListener{
    private ArrayList<WindowListener> listener;
    public DelegateWindowListener(ArrayList<WindowListener> listener) {
      this.listener = listener;
    }
    public void windowActivated(WindowEvent e) {
      synchronized ( listener) {
        for(int i = 0; i < listener.size(); i++) {
          listener.get(i).windowActivated();
        }
      }
    }
    public void windowClosed(WindowEvent e) {}
    public void windowClosing(WindowEvent e) {
      synchronized ( listener) {
        for(int i = 0; i < listener.size(); i++) {
          listener.get(i).windowClosing();
        }
      }
    }
    public void windowDeactivated(WindowEvent e) {
      synchronized ( listener) {
        for(int i = 0; i < listener.size(); i++) {
          listener.get(i).windowDeactivated();
        }
      }
    }
    public void windowDeiconified(WindowEvent e) {
      synchronized ( listener) {
        for(int i = 0; i < listener.size(); i++) {
          listener.get(i).windowDeiconified();
        }
      }
    }
    public void windowIconified(WindowEvent e) {
      synchronized ( listener) {
        for(int i = 0; i < listener.size(); i++) {
          listener.get(i).windowIconified();
        }
      }
    }
    public void windowOpened(WindowEvent e) {}
  }

  public boolean getPropertyBoolean(String property) {
    if(Properties.IS_DRAWING_MODE_SUBTRACT_SUPPORTED.equals(property)) {
      return isGlExtBlendSubtractSupported;
    }
    throw new IllegalArgumentException("No such property: " + property);
  }
  public float getPropertyFloat(String property) {
    throw new IllegalArgumentException("No such property: " + property);
  }
  public long getPropertyLong(String property) {
    if(Properties.MAX_IMAGE_DRAWING_HEIGHT.equals(property)) {
      return maxImageDrawingHeight;
    } else if(Properties.MAX_IMAGE_DRAWING_WIDTH.equals(property)) {
      return maxImageDrawingWidth;
    }
    throw new IllegalArgumentException("No such property: " + property);
  }
 
  /**
   * It is important that no other thread displays the canvas.
   * Otherwise control over threading gets lost!
   */
  private static class NoPaintGLCanvas extends GLCanvas {
    private static final long serialVersionUID = 1L;
    /*public NoPaintGLCanvas() {
      super();
    }*/
    public NoPaintGLCanvas(GLCapabilities capabilities,
        GLCapabilitiesChooser chooser, GLContext shareWith,
        GraphicsDevice device) {
      super(capabilities, chooser, shareWith, device);
    }
    /*public NoPaintGLCanvas(GLCapabilities capabilities) {
      super(capabilities);
    }*/
    // Paint does nothing!
    public void paint(Graphics g) {}
  }
}
TOP

Related Classes of ch.blackspirit.graphics.jogl2.RealtimeCanvas

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.