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 com.jogamp.nativewindow.DefaultGraphicsScreen;
32 
33 import jogamp.newt.MonitorModeProps;
34 import jogamp.newt.MonitorModeProps.Cache;
35 
36 import android.content.Context;
37 import android.graphics.PixelFormat;
38 import android.util.DisplayMetrics;
39 import android.view.Surface;
40 import android.view.WindowManager;
41 
42 import com.jogamp.newt.MonitorDevice;
43 import com.jogamp.newt.MonitorMode;
44 
45 public class ScreenDriver extends jogamp.newt.ScreenImpl {
46 
47     static {
DisplayDriver.initSingleton()48         DisplayDriver.initSingleton();
49     }
50 
ScreenDriver()51     public ScreenDriver() {
52     }
53 
54     @Override
createNativeImpl()55     protected void createNativeImpl() {
56         aScreen = new DefaultGraphicsScreen(getDisplay().getGraphicsDevice(), screen_idx);
57     }
58 
59     @Override
closeNativeImpl()60     protected void closeNativeImpl() { }
61 
62     @Override
validateScreenIndex(final int idx)63     protected int validateScreenIndex(final int idx) {
64         return 0; // FIXME: only one screen available ?
65     }
66 
getModeImpl(final Cache cache, final android.view.Display aDisplay, final DisplayMetrics outMetrics, final int modeIdx, final int screenSizeNRot, final int nrot)67     private final MonitorMode getModeImpl(final Cache cache, final android.view.Display aDisplay, final DisplayMetrics outMetrics, final int modeIdx, final int screenSizeNRot, final int nrot) {
68         final int[] props = new int[MonitorModeProps.NUM_MONITOR_MODE_PROPERTIES_ALL];
69         int i = 0;
70         props[i++] = MonitorModeProps.NUM_MONITOR_MODE_PROPERTIES_ALL;
71         i = getScreenSize(outMetrics, screenSizeNRot, props, i); // width, height
72         i = getBpp(aDisplay, props, i); // bpp
73         props[i++] = (int) ( aDisplay.getRefreshRate() * 100.0f ); // Hz * 100
74         props[i++] = 0; // flags
75         props[i++] = modeIdx; // modeId;
76         props[i++] = nrot;
77         return MonitorModeProps.streamInMonitorMode(null, cache, props, 0);
78     }
79 
80     @Override
collectNativeMonitorModesAndDevicesImpl(final Cache cache)81     protected void collectNativeMonitorModesAndDevicesImpl(final Cache cache) {
82         // FIXME: Multi Monitor Implementation missing [for newer Android version ?]
83 
84         final Context ctx = jogamp.common.os.android.StaticContext.getContext();
85         final WindowManager wmgr = (WindowManager) ctx.getSystemService(Context.WINDOW_SERVICE);
86         final DisplayMetrics outMetrics = new DisplayMetrics();
87         final android.view.Display aDisplay = wmgr.getDefaultDisplay();
88         aDisplay.getMetrics(outMetrics);
89 
90         final int arot = aDisplay.getRotation();
91         final int nrot = androidRotation2NewtRotation(arot);
92 
93         final int modeIdx=0; // no native modeId in use - use 0
94         MonitorMode currentMode = null;
95         for(int r=0; r<4; r++) { // for all rotations
96             final int nrot_i = r*MonitorMode.ROTATE_90;
97             final MonitorMode mode = getModeImpl(cache, aDisplay, outMetrics, modeIdx, 0, nrot_i);
98             if( nrot == nrot_i ) {
99                 currentMode = mode;
100             }
101         }
102 
103         final int[] props = new int[MonitorModeProps.MIN_MONITOR_DEVICE_PROPERTIES - 1 - MonitorModeProps.NUM_MONITOR_MODE_PROPERTIES];
104         int i = 0;
105         props[i++] = props.length;
106         props[i++] = 0; // crt_idx
107         props[i++] = 0; // is-clone
108         props[i++] = 1; // is-primary
109         i = getScreenSizeMM(outMetrics, props, i); // sizeMM
110         props[i++] = 0; // rotated viewport x pixel-units
111         props[i++] = 0; // rotated viewport y pixel-units
112         props[i++] = outMetrics.widthPixels; // rotated viewport width pixel-units
113         props[i++] = outMetrics.heightPixels; // rotated viewport height pixel-units
114         props[i++] = 0; // rotated viewport x window-units
115         props[i++] = 0; // rotated viewport y window-units
116         props[i++] = outMetrics.widthPixels; // rotated viewport width window-units
117         props[i++] = outMetrics.heightPixels; // rotated viewport height window-units
118         MonitorModeProps.streamInMonitorDevice(cache, this, currentMode, null, cache.monitorModes, props, 0, null);
119     }
120 
121     @Override
queryCurrentMonitorModeImpl(final MonitorDevice monitor)122     protected MonitorMode queryCurrentMonitorModeImpl(final MonitorDevice monitor) {
123         final Context ctx = jogamp.common.os.android.StaticContext.getContext();
124         final WindowManager wmgr = (WindowManager) ctx.getSystemService(Context.WINDOW_SERVICE);
125         final DisplayMetrics outMetrics = new DisplayMetrics();
126         final android.view.Display aDisplay = wmgr.getDefaultDisplay();
127         aDisplay.getMetrics(outMetrics);
128 
129         final int currNRot = androidRotation2NewtRotation(aDisplay.getRotation());
130         return getModeImpl(null, aDisplay, outMetrics, 0, currNRot, currNRot);
131     }
132 
133     @Override
setCurrentMonitorModeImpl(final MonitorDevice monitor, final MonitorMode mode)134     protected boolean setCurrentMonitorModeImpl(final MonitorDevice monitor, final MonitorMode mode) {
135         return false;
136     }
137 
138     //----------------------------------------------------------------------
139     // Internals only
140     //
androidRotation2NewtRotation(final int arot)141     static int androidRotation2NewtRotation(final int arot) {
142         switch(arot) {
143             case Surface.ROTATION_270: return MonitorMode.ROTATE_270;
144             case Surface.ROTATION_180: return MonitorMode.ROTATE_180;
145             case Surface.ROTATION_90: return MonitorMode.ROTATE_90;
146             case Surface.ROTATION_0:
147         }
148         return MonitorMode.ROTATE_0;
149     }
getScreenSize(final DisplayMetrics outMetrics, final int nrot, final int[] props, int offset)150     static int getScreenSize(final DisplayMetrics outMetrics, final int nrot, final int[] props, int offset) {
151         // swap width and height, since Android reflects rotated dimension, we don't
152         if (MonitorMode.ROTATE_90 == nrot || MonitorMode.ROTATE_270 == nrot) {
153             props[offset++] = outMetrics.heightPixels;
154             props[offset++] = outMetrics.widthPixels;
155         } else {
156             props[offset++] = outMetrics.widthPixels;
157             props[offset++] = outMetrics.heightPixels;
158         }
159         return offset;
160     }
getBpp(final android.view.Display aDisplay, final int[] props, int offset)161     static int getBpp(final android.view.Display aDisplay, final int[] props, int offset) {
162         int bpp;
163         switch(aDisplay.getPixelFormat()) {
164             case PixelFormat.RGBA_8888: bpp=32; break;
165             case PixelFormat.RGBX_8888: bpp=32; break;
166             case PixelFormat.RGB_888:   bpp=24; break;
167             case PixelFormat.RGB_565:   bpp=16; break;
168             case PixelFormat.RGBA_5551: bpp=16; break;
169             case PixelFormat.RGBA_4444: bpp=16; break;
170             case PixelFormat.RGB_332:   bpp= 8; break;
171             default: bpp=32;
172         }
173         props[offset++] = bpp;
174         return offset;
175     }
getScreenSizeMM(final DisplayMetrics outMetrics, final int[] props, int offset)176     static int getScreenSizeMM(final DisplayMetrics outMetrics, final int[] props, int offset) {
177         final float inW = outMetrics.widthPixels / outMetrics.xdpi;
178         final float inH = outMetrics.heightPixels / outMetrics.ydpi;
179         final float mmpi = 25.4f;
180         final float mmW = inW * mmpi;
181         final float mmH = inH * mmpi;
182         if( DEBUG ) {
183             System.err.println("Screen A screen "+outMetrics.widthPixels+" x "+outMetrics.heightPixels);
184             System.err.println("Screen A xy dpi "+outMetrics.xdpi+" x "+outMetrics.ydpi);
185             System.err.println("Screen A densityDPI "+outMetrics.densityDpi);
186             System.err.println("Screen A density "+outMetrics.density);
187             System.err.println("Screen N xy inch "+inW+" x "+inH);
188             System.err.println("Screen N xy mm "+mmW+" x "+mmH);
189         }
190         props[offset++] = Math.round(mmW);
191         props[offset++] = Math.round(mmH);
192         return offset;
193     }
194 }
195 
196