Jogamp
Add AndroidWindow implementation
[jogl.git] / src / newt / classes / jogamp / newt / driver / android / AndroidWindow.java
1 /**
2  * Copyright 2011 JogAmp Community. All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without modification, are
5  * permitted provided that the following conditions are met:
6  * 
7  *    1. Redistributions of source code must retain the above copyright notice, this list of
8  *       conditions and the following disclaimer.
9  * 
10  *    2. Redistributions in binary form must reproduce the above copyright notice, this list
11  *       of conditions and the following disclaimer in the documentation and/or other materials
12  *       provided with the distribution.
13  * 
14  * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
15  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
16  * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
17  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
18  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
19  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
20  * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
21  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
22  * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
23  * 
24  * The views and conclusions contained in the software and documentation are those of the
25  * authors and should not be interpreted as representing official policies, either expressed
26  * or implied, of JogAmp Community.
27  */
28
29 package jogamp.newt.driver.android;
30
31 import java.nio.IntBuffer;
32
33 import jogamp.newt.driver.android.event.AndroidNewtEventFactory;
34 import javax.media.nativewindow.GraphicsConfigurationFactory;
35 import javax.media.nativewindow.NativeWindowException;
36 import javax.media.nativewindow.egl.EGLGraphicsDevice;
37 import javax.media.nativewindow.util.Point;
38 import javax.media.opengl.GLException;
39
40 import com.jogamp.common.nio.Buffers;
41 import com.jogamp.newt.event.MouseEvent;
42
43 import jogamp.opengl.egl.EGL;
44 import jogamp.opengl.egl.EGLGraphicsConfiguration;
45
46 import android.content.Context;
47 import android.graphics.Canvas;
48 import android.graphics.PixelFormat;
49 import android.util.Log;
50 import android.view.MotionEvent;
51 import android.view.Surface;
52 import android.view.SurfaceHolder;
53 import android.view.SurfaceHolder.Callback2;
54 import android.view.SurfaceView;
55 import android.view.View;
56 import android.view.View.OnClickListener;
57 import android.view.View.OnTouchListener;
58
59 public class AndroidWindow extends jogamp.newt.WindowImpl implements Callback2 {
60     static {
61         AndroidDisplay.initSingleton();
62     }
63
64     int getPixelFormat() {
65         /**
66         int bpp = capsRequested.getRedBits()+
67                   capsRequested.getGreenBits()+
68                   capsRequested.getBlueBits();
69         int alpha = capsRequested.getAlphaBits();
70         
71         if(bpp <= 16) {
72             
73         }
74         switch(aDisplay.getPixelFormat()) {
75             case PixelFormat.RGBA_8888: bpp=32; break;
76             case PixelFormat.RGBX_8888: bpp=32; break;
77             case PixelFormat.RGB_888:   bpp=24; break;
78             case PixelFormat.RGB_565:   bpp=16; break;
79             case PixelFormat.RGBA_5551: bpp=16; break;
80             case PixelFormat.RGBA_4444: bpp=16; break;
81             case PixelFormat.RGB_332:   bpp= 8; break;
82             default: bpp=32;   
83         } */
84         return PixelFormat.RGBA_8888;                       
85     }
86     
87     public AndroidWindow(Context ctx) {
88         nsv = new MSurfaceView(ctx);
89         SurfaceHolder sh = nsv.getHolder();
90         sh.setFormat(getPixelFormat());
91         sh.setType(SurfaceHolder.SURFACE_TYPE_NORMAL);
92         sh.addCallback(this); 
93     }
94
95     public static Class[] getCustomConstructorArgumentTypes() {
96         return new Class[] { Context.class } ;
97     }
98     
99     public SurfaceView getView() { return nsv; }
100     
101     protected boolean canCreateNativeImpl() {
102         final boolean b = 0 != surfaceHandle;
103         Log.d(MD.TAG, "canCreateNativeImpl: "+b);
104         return b;
105     }
106
107     protected void createNativeImpl() {
108         if(0!=getParentWindowHandle()) {
109             throw new NativeWindowException("Window parenting not supported (yet)");
110         }
111         if(0==surfaceHandle) {
112             throw new InternalError("XXX");
113         }
114        
115         final EGLGraphicsDevice eglDevice = (EGLGraphicsDevice) getScreen().getDisplay().getGraphicsDevice();
116         final EGLGraphicsConfiguration eglConfig = (EGLGraphicsConfiguration) GraphicsConfigurationFactory.getFactory(eglDevice)
117                 .chooseGraphicsConfiguration(capsRequested, capsRequested, capabilitiesChooser, getScreen().getGraphicsScreen());
118         if (eglConfig == null) {
119             throw new NativeWindowException("Error choosing GraphicsConfiguration creating window: "+this);
120         }
121         // query native VisualID and pass it to Surface
122         final long eglConfigHandle = eglConfig.getNativeConfig();
123         final IntBuffer nativeVisualID = Buffers.newDirectIntBuffer(1);
124         if(!EGL.eglGetConfigAttrib(eglDevice.getHandle(), eglConfigHandle, EGL.EGL_NATIVE_VISUAL_ID, nativeVisualID)) {
125             throw new NativeWindowException("eglgetConfigAttrib EGL_NATIVE_VISUAL_ID failed eglDisplay 0x"+Long.toHexString(eglDevice.getHandle())+ 
126                                   ", error 0x"+Integer.toHexString(EGL.eglGetError()));
127         }        
128         Log.d(MD.TAG, "nativeVisualID 0x"+Integer.toHexString(nativeVisualID.get(0)));
129         setSurfaceVisualID(surfaceHandle, nativeVisualID.get(0));
130         
131         eglSurface = EGL.eglCreateWindowSurface(eglDevice.getHandle(), eglConfig.getNativeConfig(), surfaceHandle, null);
132         if (EGL.EGL_NO_SURFACE==eglSurface) {
133             throw new NativeWindowException("Creation of window surface failed: "+eglConfig+", surfaceHandle 0x"+Long.toHexString(surfaceHandle)+", error "+toHexString(EGL.eglGetError()));
134         }
135         
136         // propagate data ..
137         config = eglConfig;
138         setWindowHandle(surfaceHandle);
139     }
140
141     @Override
142     protected void closeNativeImpl() {
143         surface = null;
144         surfaceHandle = 0;
145         eglSurface = 0;        
146     }
147
148     @Override
149     public final long getSurfaceHandle() {
150         return eglSurface;
151     }
152     
153     protected void setVisibleImpl(boolean visible, int x, int y, int width, int height) {
154         reconfigureWindowImpl(x, y, width, height, false, 0, 0);
155         visibleChanged(visible);
156     }
157
158     protected void requestFocusImpl(boolean reparented) { }
159
160     protected boolean reconfigureWindowImpl(int x, int y, int width, int height, 
161                                             boolean parentChange, int fullScreenChange, int decorationChange) {
162         if(0!=getWindowHandle()) {
163             if(0!=fullScreenChange) {
164                 if( fullScreenChange > 0 ) {
165                     System.err.println("reconfigureWindowImpl.setFullscreen n/a");
166                     return false;
167                 }
168             }
169         }
170         if(width>0 || height>0) {
171             if(0!=getWindowHandle()) {
172                 System.err.println("reconfigureWindowImpl.setSize n/a");
173                 return false;
174             }
175         }
176         if(x>=0 || y>=0) {
177             System.err.println("reconfigureWindowImpl.setPos n/a");
178             return false;
179         }
180         return true;
181     }
182
183     /***
184     Canvas cLock = null;
185     
186     @Override
187     protected int lockSurfaceImpl() {
188         if (null != cLock) {
189             throw new InternalError("surface already locked");
190         }        
191         if (0 != surfaceHandle) {
192             cLock = nsv.getHolder().lockCanvas();
193         }
194         return ( null != cLock ) ? LOCK_SUCCESS : LOCK_SURFACE_NOT_READY;
195     }
196
197     @Override
198     protected void unlockSurfaceImpl() {
199         if (null == cLock) {
200             throw new InternalError("surface not locked");
201         }
202         nsv.getHolder().unlockCanvasAndPost(cLock);
203         cLock=null;
204     } */
205     
206     protected Point getLocationOnScreenImpl(int x, int y) {
207         return new Point(x,y);
208     }
209
210     //----------------------------------------------------------------------
211     // Surface Callbacks 
212     //
213     
214     public void surfaceCreated(SurfaceHolder holder) {    
215         surface = holder.getSurface();
216         surfaceHandle = getSurfaceHandle(surface);
217
218         Log.d(MD.TAG, "surfaceCreated - 0 - isValid: "+surface.isValid()+
219                     ", surfaceHandle 0x"+Long.toHexString(surfaceHandle)+
220                     ", "+nsv.getWidth()+"x"+nsv.getHeight());
221         sizeChanged(width, height, false);
222         windowRepaint(0, 0, nsv.getWidth(), nsv.getHeight());
223     }
224
225     public void surfaceChanged(SurfaceHolder holder, int format, int width,
226             int height) {
227         Log.d(MD.TAG, "surfaceChanged: f "+Integer.toString(format)+", "+width+"x"+height);
228         sizeChanged(width, height, false);
229     }
230
231     public void surfaceDestroyed(SurfaceHolder holder) {
232         Log.d(MD.TAG, "surfaceDestroyed");
233         windowDestroyNotify();
234     }
235
236     public void surfaceRedrawNeeded(SurfaceHolder holder) {
237         Log.d(MD.TAG, "surfaceRedrawNeeded");
238         windowRepaint(0, 0, getWidth(), getHeight());
239     }
240     
241     
242     MSurfaceView nsv;
243     Surface surface = null;
244     volatile long surfaceHandle = 0;
245     long eglSurface = 0;
246     
247     class MouseInterceptor implements OnClickListener, OnTouchListener {
248
249         public void onClick(View v) {
250             // TODO Auto-generated method stub
251         }
252
253         public boolean onTouch(View v, MotionEvent event) {
254             // MouseEvent event = AndroidNewtEventFactory.createMouseEvent(event, AndroidWindow.this);
255             
256             return false;
257         }
258         
259     }
260     static class MSurfaceView extends SurfaceView {
261         public MSurfaceView (Context ctx) {
262             super(ctx);
263             
264         }
265         /**
266         protected void dispatchDraw(Canvas canvas) {
267             // n/a
268         }
269         public void draw(Canvas canvas) {
270             // n/a
271         } */
272     }
273     //----------------------------------------------------------------------
274     // Internals only
275     //
276     protected static native boolean initIDs();
277     protected static native long getSurfaceHandle(Surface surface);
278     protected static native void setSurfaceVisualID(long surfaceHandle, int nativeVisualID);
279     
280 }
http://JogAmp.org git info: FAQ, tutorial and man pages.