451ae1cc466bc01a7b8f0aef6a5f844af0d38425
[scilab.git] / scilab / modules / gui / src / java / org / scilab / modules / gui / bridge / canvas / SwingScilabCanvasImpl.java
1 /*
2  * Scilab ( http://www.scilab.org/ ) - This file is part of Scilab
3  * Copyright (C) 2008 - DIGITEO - Bruno JOFRET
4  * Copyright (C) 2012 - Scilab Enterprises - Bruno JOFRET
5  *
6  * This file must be used under the terms of the CeCILL.
7  * This source file is licensed as described in the file COPYING, which
8  * you should have received as part of this distribution.  The terms
9  * are also available at
10  * http://www.cecill.info/licences/Licence_CeCILL_V2-en.txt
11  *
12  */
13
14 package org.scilab.modules.gui.bridge.canvas;
15
16 import java.awt.Component;
17 import java.awt.Frame;
18 import java.awt.Graphics;
19 import java.awt.HeadlessException;
20 import java.util.Calendar;
21 import java.util.StringTokenizer;
22
23 import javax.media.opengl.GL;
24 import javax.media.opengl.GLCapabilities;
25 import javax.media.opengl.GLException;
26 import javax.media.opengl.GLProfile;
27 import javax.media.opengl.awt.GLCanvas;
28 import javax.media.opengl.awt.GLJPanel;
29
30 import org.scilab.modules.action_binding.InterpreterManagement;
31 import org.scilab.modules.commons.OS;
32 import org.scilab.modules.gui.utils.Debug;
33 import org.scilab.modules.localization.Messages;
34
35 public class SwingScilabCanvasImpl {
36
37     private static final long serialVersionUID = -3110280842744630282L;
38
39     static boolean forceGLCanvas = false;
40     static boolean noGLJPanel = false;
41     static boolean testCanvasAtStartup = false;
42
43     static {
44         if (testCanvasAtStartup && OS.get() != OS.MAC) {
45             long lastTime = Calendar.getInstance().getTimeInMillis();
46
47             Debug.DEBUG("SwingScilabCanvasImpl", "=======================================");
48             String OS_NAME = System.getProperty("os.name");
49             Debug.DEBUG("SwingScilabCanvasImpl", "os.name=" + OS_NAME);
50             String OS_ARCH = System.getProperty("os.arch");
51             Debug.DEBUG("SwingScilabCanvasImpl", "os.arch=" + OS_ARCH);
52             Debug.DEBUG("SwingScilabCanvasImpl", "=======================================");
53
54             /*
55              * Bug #7526: moved out of the try/catch block since it contains
56              * no OpenGL calls.
57              */
58
59             if ( OS_NAME.contains("Windows") && OS_ARCH.equals("amd64") ) {
60                 // bug 3919 : JOGL x64 doesn't like x64 remote desktop on Windows
61                 // @TODO : bug report to JOGL
62                 String REMOTEDESKTOP = System.getenv("SCILAB_MSTS_SESSION");
63                 if (REMOTEDESKTOP != null) {
64                     if ( REMOTEDESKTOP.equals("OK") ) {
65                         noGLJPanel = true;
66                     }
67                 }
68
69                 if (noGLJPanel) {
70                     /** Inform the users */
71                     InterpreterManagement.requestScilabExec(
72                             String.format("disp(\"%s\"), disp(\"%s\")",
73                                     String.format(Messages.gettext("WARNING: Due to your configuration limitations, Scilab switched in a mode where mixing uicontrols and graphics is not available. Type %s for more information."), "\"\"help usecanvas\"\""),
74                                     String.format(Messages.gettext("In some cases, %s fixes the issue"), "\"\"system_setproperty(''jogl.gljpanel.nohw'','''');\"\"")
75                                     )
76                             );
77                 }
78             }
79
80             /*
81              * Bug #7526: this code block causes a crash on Windows and Intel Graphic HD cards
82              * with graphics drivers older than 8.15.10.2279 and is therefore not executed if
83              * Windows is the OS (the tests on driver and OpenGL versions are Linux-specific).
84              * Consequently, updateMaxCanvasSize, which determines the canvas size, is not called
85              * any more on Windows. However, it is still called when an actual graphics window is created
86              * (by the renderer module's SciRenderer init method), which still allows getting the maximum
87              * canvas dimensions, so this should not be an issue.
88              */
89             if (!OS_NAME.contains("Windows")) {
90
91                 try {
92                     GLCanvas tmpCanvas = new GLCanvas(new GLCapabilities(GLProfile.getDefault()));
93                     Frame tmpFrame = new Frame();
94                     tmpFrame.add(tmpCanvas);
95                     tmpFrame.setVisible(true);
96
97                     tmpCanvas.getContext().makeCurrent();
98                     GL gl = tmpCanvas.getGL();
99
100                     String GL_VENDOR = gl.glGetString(GL.GL_VENDOR);
101                     Debug.DEBUG("SwingScilabCanvasImpl", "GL_VENDOR=" + GL_VENDOR);
102                     String GL_RENDERER = gl.glGetString(GL.GL_RENDERER);
103                     Debug.DEBUG("SwingScilabCanvasImpl", "GL_RENDERER=" + GL_RENDERER);
104                     String GL_VERSION = gl.glGetString(GL.GL_VERSION);
105                     Debug.DEBUG("SwingScilabCanvasImpl", "GL_VERSION=" + GL_VERSION);
106                     //Debug.DEBUG("SwingScilabCanvasImpl", "GL_EXTENSIONS="+gl.glGetString(GL.GL_EXTENSIONS));
107                     Debug.DEBUG("SwingScilabCanvasImpl", "=======================================");
108                     //System.getProperties().list(System.err);
109
110                     // get maximum axes size
111                     //RenderingCapabilities.updateMaxCanvasSize(gl);
112
113                     tmpCanvas.getContext().release();
114                     tmpFrame.remove(tmpCanvas);
115                     tmpFrame.setVisible(false);
116                     tmpFrame.dispose();
117                     Debug.DEBUG("SwingScilabCanvasImpl", "Testing time = " + (Calendar.getInstance().getTimeInMillis() - lastTime) + "ms");
118
119                     noGLJPanel = false;
120
121                     // By default disable GLJPanel on Linux
122                     if (OS_NAME.contains("Linux")) {
123                         noGLJPanel = true;
124                         // Linux && NVIDIA
125                         if (GL_VENDOR.contains("NVIDIA")) {
126                             noGLJPanel = false;
127                         }
128                         // Linux && ATI
129                         if (GL_VENDOR.contains("ATI")) {
130                             StringTokenizer stSpace = new StringTokenizer(GL_VERSION, " ");
131                             StringTokenizer stDot = new StringTokenizer(stSpace.nextToken(), ".");
132                             int majorVersion = Integer.parseInt(stDot.nextToken());
133                             int minorVersion = Integer.parseInt(stDot.nextToken());
134                             int releaseVersion = Integer.parseInt(stDot.nextToken());
135                             // Only OpenGL version newer than 2.1.7873 works
136                             // available through ATI 8.8 installer
137                             // and driver newer than 8.52.3
138                             Debug.DEBUG("SwingScilabCanvasImpl", "majorVersion = "
139                                     + majorVersion + " minorVersion = " + minorVersion
140                                     + " releaseVersion = " + releaseVersion);
141                             if (majorVersion > 2
142                                     || majorVersion == 2 && minorVersion > 1
143                                     || majorVersion == 2 && minorVersion == 1 && releaseVersion >= 7873) {
144                                 noGLJPanel = false;
145                             }
146                         }
147                     }
148
149                     if (noGLJPanel) {
150                         /** Inform the users */
151                         InterpreterManagement.requestScilabExec(
152                                 String.format("disp(\"%s\"), disp(\"%s\")",
153                                         String.format(Messages.gettext("WARNING: Due to your configuration limitations, Scilab switched in a mode where mixing uicontrols and graphics is not available. Type %s for more information."), "\"\"help usecanvas\"\""),
154                                         String.format(Messages.gettext("In some cases, %s fixes the issue"), "\"\"system_setproperty(''jogl.gljpanel.nohw'','''');\"\"")
155                                         )
156                                 );
157                     }
158                 } catch (GLException e) {
159                     noGLJPanel = true;
160                     /** Inform the users */
161                     InterpreterManagement.requestScilabExec(
162                             String.format("disp(\"%s\"), disp(\"%s\")",
163                                     Messages.gettext("Due to your video card drivers limitations, that are not able to manage OpenGL, Scilab will not be able to draw any graphics. Please update your driver."),
164                                     String.format(Messages.gettext("In some cases, %s fixes the issue"), "\"\"system_setproperty(''jogl.gljpanel.nohw'','''');\"\"")
165                                     )
166                             );
167                 } catch (HeadlessException e) {
168                     // do not print anything on a CLI only environment
169                     noGLJPanel = true;
170                 }
171
172             }
173         }
174
175     }
176
177     static boolean enableGLCanvas = forceGLCanvas || noGLJPanel;
178
179     /**
180      * Change Global property forceGLCanvas
181      * if no GLJPanel is available, GLCanvas is forced
182      */
183     public static boolean switchToGLCanvas(boolean onOrOff) {
184         Debug.DEBUG("SwingScilabCanvasImpl", "switchToGLCanvas " + onOrOff);
185         if (!onOrOff && noGLJPanel) {
186             InterpreterManagement.requestScilabExec(Messages.gettext("disp(\"WARNING: Despite of our previous warning, you choose to use Scilab with advanced graphics capabilities. Type \"\"help usecanvas\"\" for more information.\")"));
187         }
188         enableGLCanvas = onOrOff;
189         return enableGLCanvas;
190     }
191
192     /**
193      * Get Global property forceGLCanvas
194      * if no GLJPanel is available, GLCanvas is forced
195      */
196     public static boolean isGLCanvasEnabled() {
197         return enableGLCanvas;
198     }
199
200     /*
201      * Using SafeGLJPanel for all platform to catch some EDT deletion/creation.
202      * Some buffer can be lost causing JoGL to crash
203      * http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=6503420
204      */
205     private final class SafeGLJPanel extends GLJPanel {
206         private static final long serialVersionUID = -6166986369022555750L;
207
208         public void display() {
209             try {
210                 super.display();
211             } catch (Exception e) {
212                 // Catch JoGL Exceptions and hide it ...
213                 // Make another try
214                 //System.err.println("[SafeGLJPanel.display] catching "+e.toString());
215                 super.reshape(getX(),getY(),getWidth(),getHeight());
216                 super.display();
217             }
218         }
219
220         // protected void paintComponent(final Graphics g) {
221         //     try {
222         //         super.paintComponent(g);
223         //     } catch (Exception e) {
224         //         // Catch JoGL Exceptions and hide it ...
225         //         // Make another try
226         //         System.err.println("[SafeGLJPanel.paintComponent] catching "+e.toString());
227         //     }
228         // }
229     }
230     
231     /*
232     * Empty class to allow xlick/xgetmouse
233     * catch same cannonical name
234     */
235     private final class SafeGLCanvas extends GLCanvas {
236         private static final long serialVersionUID = -3315164314205693678L;
237     }
238
239     private static SwingScilabCanvasImpl me = null;
240
241     public static SwingScilabCanvasImpl getInstance() {
242         if (me == null) {
243             me = new SwingScilabCanvasImpl();
244         }
245
246         return me;
247     }
248
249     public Component createOpenGLComponent() {
250         if (enableGLCanvas) {
251             return new SafeGLCanvas();
252         } else {
253             return new SafeGLJPanel();
254         }
255     }
256
257     public SwingScilabCanvasImpl() {}
258 }