licensing cleanup (GPLv2)
[org.ibex.core.git] / src / org / ibex / plat / Darwin.java
1 // Copyright 2000-2005 the Contributors, as shown in the revision logs.
2 // Licensed under the GNU General Public License version 2 ("the License").
3 // You may not use this file except in compliance with the License.
4
5 // Authors: Brian Alliet and Evan Jones
6
7 package org.ibex.plat;
8
9 import gnu.gcj.RawData;
10 import org.ibex.util.*;
11 import org.ibex.js.*;
12 import org.ibex.graphics.*;
13 import org.ibex.core.*;
14 import org.ibex.net.*;
15
16 public class Darwin extends POSIX {
17     public static void main(String[] s) throws Exception { org.ibex.core.Main.main(s); }
18     private static final Class openGLClass = OpenGL.class;
19     static Darwin singleton;
20     private CarbonOpenGL openGL;
21     boolean jaguar; // true if we are on OS X >= 10.2
22     
23     // General Methods
24     protected String _getAltKeyName() { return "Option"; }
25     protected boolean _needsAutoClick() { return false; }
26     protected boolean _needsAutoDoubleClick() { return false; }
27     protected String getDescriptiveName() { return "GCJ Darwin Binary"; }
28     protected boolean _isCaseSensitive() { return false; /* Well, not always, could be UFS */ }
29     
30     
31     // Native Methods
32     protected int    _getScreenWidth() { return cgScreenWidth(); }
33     protected int    _getScreenHeight() { return cgScreenHeight(); }
34     private native static int cgScreenWidth();
35     private native static int cgScreenHeight();
36     protected native void   _newBrowserWindow(String url);
37     protected native HTTP.Proxy   natDetectProxy();
38     private   native void    natInit();
39
40     private native String natGetClipBoard();
41     private native void natSetClipBoard(String text);
42     protected void _setClipBoard(final String text) { CarbonMessage.add(new CarbonMessage() { public void perform() { natSetClipBoard(text); } }); }
43     protected String _getClipBoard() {
44         final Semaphore sem = new Semaphore();
45         final String[] result = new String[1]; // Kind of like a pointer
46         CarbonMessage.add(new CarbonMessage() { public void perform() { result[0] = natGetClipBoard(); sem.release(); } });
47         sem.block();
48         return result[0];
49     }
50     
51     private static class FileDialogHelper {
52         public FileDialogHelper(boolean save) { this.save = save; }
53         public boolean save;
54         public Semaphore sem = new Semaphore();
55         public String fileName;
56         public String saveName;
57     }
58     private native void natFileDialog(FileDialogHelper helper, String suggestedFileName, boolean write);
59     protected String _fileDialog(final String fn, final boolean w) {
60         final FileDialogHelper helper = new FileDialogHelper(w);
61         CarbonMessage.add(new CarbonMessage() { public void perform() { natFileDialog(helper,fn,w); } });
62         helper.sem.block();
63         if(w)
64             return helper.fileName + "/" + helper.saveName;
65         else
66             return helper.fileName;
67     }
68
69     
70     static void abort(String err) {
71         throw new Error(err);
72     }
73     
74     public Darwin() {
75         synchronized(Darwin.class) {
76             if(singleton != null) abort("Tried to instansiate Darwin more than once");
77             singleton = this;
78         }
79     }
80     
81     protected synchronized HTTP.Proxy _detectProxy() {
82         return natDetectProxy();
83     }
84     
85     private static native final boolean isJaguar();
86     
87     public void postInit() {
88         jaguar = isJaguar();
89         try {
90             openGL = new CarbonOpenGL();
91             openGL.init();
92         } catch(OpenGL.NotSupportedException e) {
93             Log.info(this,"WARNING: OpenGL support not available: " + e);
94             // FEATURE: fall back to quartz 2d
95             throw new Error("No OpenGL support");
96         }
97         natInit();
98     }
99     
100     protected Scheduler _getScheduler() { return new DarwinScheduler(); }
101     protected native void runApplicationEventLoop();
102     private class DarwinScheduler extends org.ibex.core.Scheduler {
103         public void run() {
104             new Thread() { public void run() { defaultRun(); } }.start();
105             runApplicationEventLoop();
106         }
107     }
108     
109     private final class CarbonOpenGL extends OpenGL {
110         public RawData rawPixelFormat;
111         public RawData rawSharedContext;
112         public int maxAglSurfaceTexSize;
113         public int maxSurfaceWidth;
114         public int maxSurfaceHeight;
115         
116         private native boolean initPixelFormat();
117         private native void initSharedContext();
118         
119         public CarbonOpenGL() throws NotSupportedException {
120             if(!jaguar)
121                 throw new NotSupportedException("OpenGL requires Mac OS X 10.2 or greater");
122             if(!initPixelFormat())
123                 throw new NotSupportedException("Couldn't get an acceptable pixel format");
124             initSharedContext();
125         }
126         
127         public void init() throws NotSupportedException {
128             super.init();
129             maxAglSurfaceTexSize = rectangularTextures ? maxRectTexSize : maxTexSize;
130             if(renderer.startsWith("ATI Radeon 7500")) {
131                 maxAglSurfaceTexSize = Math.min(rectangularTextures ? 1600 : 1024,maxAglSurfaceTexSize);
132                 Log.info(this,"Working around Radeon 7500 bug: maxAglSurfaceTexSize: " + maxAglSurfaceTexSize);
133             }
134             maxSurfaceWidth = maxSurfaceHeight = maxAglSurfaceTexSize;
135         }
136         protected native void activateSharedContext();
137     }
138     
139     static abstract class CarbonSurface extends Surface.DoubleBufferedSurface {  
140         RawData rawWindowRef;
141         int modifiers;
142         int winWidth;
143         int winHeight;
144         
145         boolean pendingResize;
146          
147         private native void natSetInvisible(boolean i);
148         public void setInvisible(final boolean i) { CarbonMessage.add(new CarbonMessage() { public void perform() { natSetInvisible(i); } }); }
149         private native void nat_setMaximized(boolean b);
150         public void _setMaximized(final boolean b) { CarbonMessage.add(new CarbonMessage() { public void perform() { nat_setMaximized(b); } }); }
151         private native void nat_setMinimized(boolean b);
152         public void _setMinimized(final boolean b) { CarbonMessage.add(new CarbonMessage() { public void perform() { nat_setMinimized(b); } }); }
153         private native void natSetIcon(Picture p);
154         public void setIcon(final Picture p) { CarbonMessage.add(new CarbonMessage() { public void perform() { natSetIcon(p); } }); }
155         private native void natSetTitleBarText(String s);
156         public void setTitleBarText(final String s) { CarbonMessage.add(new CarbonMessage() { public void perform() { natSetTitleBarText(s); } }); }
157         private native void natSetSize(int w, int h);
158         public void _setSize(final int w, final int h) { CarbonMessage.add(new CarbonMessage() { public void perform() { natSetSize(w,h); } }); }
159         private native void natSetLocation();
160         public void setLocation() { CarbonMessage.add(new CarbonMessage() { public void perform() { natSetLocation(); } }); }
161         private native void natToFront();
162         public void toFront() { CarbonMessage.add(new CarbonMessage() { public void perform() { natToFront(); } }); }
163         private native void natToBack();
164         public void toBack() { CarbonMessage.add(new CarbonMessage() { public void perform() { natToBack(); } }); }
165         private native void natSetLimits(int minWidth, int minHeight, int maxWidth, int maxHeight);
166         public void setLimits(final int mnw, final int mnh, final int mxw, final int mxh) {
167             if(Darwin.singleton.jaguar)
168                 CarbonMessage.add(new CarbonMessage() { public void perform() { natSetLimits(mnw,mnh,mxw,mxh); } });
169         }
170         private native void natSyncCursor(int n);
171         public void syncCursor() {
172             int n;
173             if(cursor.equals("default")) n = 0;
174             else if(cursor.equals("wait")) n = 1;
175             else if(cursor.equals("crosshair")) n = 2;
176             else if(cursor.equals("text")) n = 3;
177             else if(cursor.equals("hand")) n = 4;
178             else if(cursor.equals("move")) n = 5;
179             else if(cursor.equals("east") || cursor.equals("west")) n = 6;
180             else n = 0; 
181             final int n_ = n;
182             CarbonMessage.add(new CarbonMessage() { public void perform() { natSyncCursor(n_); } });
183         }
184        
185         /* Drawing stuff */
186         public abstract void blit(PixelBuffer s, int sx, int sy, int dx, int dy, int dx2, int dy2);
187
188         public final void _dispose() { CarbonMessage.add(new CarbonMessage() { public void perform() { natDispose(); } }); }
189         public native void natDispose();
190         
191         public final native void natInit(boolean framed);
192         
193         public CarbonSurface(Box root, final boolean framed) {
194             super(root);
195             final Semaphore sem = new Semaphore();
196             CarbonMessage.add(new CarbonMessage() { public void perform() { CarbonSurface.this.natInit(framed); sem.release(); } });
197             sem.block();
198         }
199         
200         public void needsReshape() { }
201         protected static native void blitLock();
202         protected static native void blitUnlock();
203         protected static native void blitWait();
204     }
205     
206     static class GLCarbonPixelBuffer extends OpenGL.GLPixelBuffer {
207         RawData rawCTX;
208         RawData rawWindowRef;
209         int textureName;
210         boolean rectTexture;
211         CarbonOpenGL gl;
212         
213         private native void natInit();
214         private static native void natCleanup(RawData rawWindowRef, RawData rawCTX);
215         
216         
217         private static final int fixupDimension(CarbonOpenGL gl, int n) {
218             if(!gl.rectangularTextures) n = OpenGL.roundToPowerOf2(n);
219             return Math.min(n,gl.maxAglSurfaceTexSize);
220         }
221         public GLCarbonPixelBuffer(int w, int h, final CarbonOpenGL gl) {
222             super(fixupDimension(gl,w),fixupDimension(gl,h));
223             this.gl = gl;
224             rectTexture = gl.hasRectangularTextures();
225             final Semaphore sem = new Semaphore();
226             CarbonMessage.add(new CarbonMessage() { public void perform() { GLCarbonPixelBuffer.this.natInit(); sem.release(); } });
227             sem.block();
228         }
229         public native void activateContext();
230         protected void finalize() {
231             CarbonMessage.add(new CarbonMessage() { public void perform() { natCleanup(rawWindowRef,rawCTX); } });
232             gl.deleteTexture(textureName);
233         }
234     }
235     
236     static class GLCarbonSurface extends CarbonSurface {
237         RawData rawCTX;
238         CarbonOpenGL gl;
239         boolean needsReshape;
240                 
241         private final native void natInit();
242         private final native void flush();
243         private final native void clear();
244         
245         public GLCarbonSurface(Box root, boolean framed, CarbonOpenGL gl) {
246             super(root,framed);
247             this.gl = gl;
248             natInit();
249         }
250         
251         public void setLimits(int mnw,int mnh, int mxw, int mxh) {
252             mxw = Math.min(mxw,gl.maxSurfaceWidth);
253             mxh = Math.min(mxh,gl.maxSurfaceHeight);
254             super.setLimits(mnw,mnh,mxw,mxh);
255         }
256         
257         public void _setSize(int w, int h) {
258             w = Math.min(w,gl.maxSurfaceWidth);
259             h = Math.min(h,gl.maxSurfaceWidth);
260             super._setSize(w,h);
261         }
262         
263         private native void natBlit(GLCarbonPixelBuffer db, int sx, int sy, int dx, int dy, int dx2, int dy2);
264         public void blit(PixelBuffer db, int sx, int sy, int dx, int dy, int dx2, int dy2) {
265             natBlit((GLCarbonPixelBuffer)db,sx,sy,dx,dy,dx2,dy2);
266         }
267         
268         
269         // The blit_lock ensures the window size does not change through the entire blit operation.
270         public void render() {
271             /*
272             blitLock();
273             while(pendingResize) blitWait();
274             */
275             if(needsReshape) {
276                 needsReshape = false;
277                 
278                 reshape(winWidth,winHeight);
279                 clear();
280                 Dirty(0,0,winWidth,winHeight);
281             }
282             super.render();
283             flush();
284             /*
285             blitUnlock();
286             */
287         }
288         
289         private native void reshape(int w, int h);
290         // blit_lock is assumed to be held
291         public void needsReshape() { needsReshape = true; }
292
293         public native void natDispose();
294     }
295
296     /*private class QZCarbonPixelBuffer extends PixelBuffer {
297         
298         public QZCarbonPixelBuffer(int width, int height) {
299         }
300     }
301        private class QZCarbonSurface extends CarbonSurface {
302         public QZCarbonSurface(Box root, boolean framed) {
303             super(b,root);
304         }
305         public native void blit(PixelBuffer s, int sx, int sy, int dx, int dy, int dx2, int dy2);
306     }
307     
308     private class QZCarbonPicture extends Picture {
309         int width;
310         int height;
311         
312         public final int getWidth() { return width; }
313         public final int getHeight() { return height; }
314                 
315         public QZCarbonPicture(int w, int h) {
316             this.width = w;
317             this.height = h;
318         }
319     }*/
320     
321     protected PixelBuffer _createPixelBuffer(int w, int h, Surface owner) {
322         if(openGL != null)
323             return new GLCarbonPixelBuffer(w,h,openGL);
324         else
325             return /*new QZCarbonPixelBuffer(w,h)*/ null;
326     }
327     protected Surface _createSurface(Box b, boolean framed) {
328         if(openGL != null)
329             return new GLCarbonSurface(b,framed, openGL);
330         else
331             return /*new QZCarbonSufrace(b,framed)*/ null;
332     }
333     protected Picture _createPicture(JS r) {
334         if(openGL != null)
335             return openGL._createPicture(r, true);
336         else
337             return /*new QZCarbonPicture(data,w,h);*/ null;
338     }
339     protected org.ibex.graphics.Font.Glyph  _createGlyph(org.ibex.graphics.Font f, char c) {
340         if(openGL != null)
341             return openGL._createGlyph(f, c);
342         else
343             return super.createGlyph(f, c);
344     }
345     
346     /* A message that is sent through the carbon event queue */
347     private static abstract class CarbonMessage {
348         public abstract void perform();
349         
350         static { natInit(); }
351         public static native void natInit();
352         public static native void add(CarbonMessage m);
353     }
354 }