sync with latest
[sdk/emulator/qemu.git] / tizen / src / skin / client / src / org / tizen / emulator / skin / EmulatorShmSkin.java
1 /**
2  * Emulator Skin Process
3  *
4  * Copyright (C) 2011 - 2013 Samsung Electronics Co., Ltd. All rights reserved.
5  *
6  * Contact:
7  * GiWoong Kim <giwoong.kim@samsung.com>
8  * YeongKyoon Lee <yeongkyoon.lee@samsung.com>
9  *
10  * This program is free software; you can redistribute it and/or
11  * modify it under the terms of the GNU General Public License
12  * as published by the Free Software Foundation; either version 2
13  * of the License, or (at your option) any later version.
14  *
15  * This program is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU General Public License for more details.
19  *
20  * You should have received a copy of the GNU General Public License
21  * along with this program; if not, write to the Free Software
22  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
23  *
24  * Contributors:
25  * - S-Core Co., Ltd
26  *
27  */
28
29 package org.tizen.emulator.skin;
30
31 import java.util.logging.Level;
32 import java.util.logging.Logger;
33
34 import org.eclipse.swt.SWT;
35 import org.eclipse.swt.events.PaintEvent;
36 import org.eclipse.swt.events.PaintListener;
37 import org.eclipse.swt.graphics.Image;
38 import org.eclipse.swt.graphics.ImageData;
39 import org.eclipse.swt.graphics.PaletteData;
40 import org.eclipse.swt.graphics.Transform;
41 import org.eclipse.swt.widgets.Display;
42 import org.tizen.emulator.skin.config.EmulatorConfig;
43 import org.tizen.emulator.skin.config.EmulatorConfig.ArgsConstants;
44 import org.tizen.emulator.skin.exception.ScreenShotException;
45 import org.tizen.emulator.skin.image.ImageRegistry.IconName;
46 import org.tizen.emulator.skin.info.SkinInformation;
47 import org.tizen.emulator.skin.log.SkinLogger;
48 import org.tizen.emulator.skin.screenshot.ShmScreenShotWindow;
49 import org.tizen.emulator.skin.util.SkinUtil;
50
51 public class EmulatorShmSkin extends EmulatorSkin {
52         private Logger logger = SkinLogger.getSkinLogger(
53                         EmulatorShmSkin.class).getLogger();
54
55         public static final int RED_MASK = 0x00FF0000;
56         public static final int GREEN_MASK = 0x0000FF00;
57         public static final int BLUE_MASK = 0x000000FF;
58         public static final int COLOR_DEPTH = 24; /* no need to Alpha channel */
59
60         /* define JNI functions */
61         public native int shmget(int shmkey, int size);
62         public native int shmdt();
63         public native int getPixels(int[] array);
64
65         private PaletteData paletteData;
66         private PollFBThread pollThread;
67
68         class PollFBThread extends Thread {
69                 private Display display;
70                 private int widthFB;
71                 private int heightFB;
72                 private int[] arrayFramebuffer;
73                 private ImageData imageData;
74                 private Image framebuffer;
75
76                 private volatile boolean stopRequest;
77                 private Runnable runnable;
78                 private int intervalWait;
79
80                 public PollFBThread(int widthFB, int heightFB) {
81                         this.display = Display.getDefault();
82                         this.widthFB = widthFB;
83                         this.heightFB = heightFB;
84                         this.arrayFramebuffer = new int[widthFB * heightFB];
85                         this.imageData = new ImageData(widthFB, heightFB, COLOR_DEPTH, paletteData);
86                         this.framebuffer = new Image(Display.getDefault(), imageData);
87
88                         setDaemon(true);
89                         setWaitIntervalTime(30);
90
91                         this.runnable = new Runnable() {
92                                 @Override
93                                 public void run() {
94                                         // logger.info("update display framebuffer");
95                                         if (lcdCanvas.isDisposed() == false) {
96                                                 lcdCanvas.redraw();
97                                         }
98                                 }
99                         };
100                 }
101
102                 public synchronized void setWaitIntervalTime(int ms) {
103                         intervalWait = ms;
104                 }
105
106                 public synchronized int getWaitIntervalTime() {
107                         return intervalWait;
108                 }
109
110                 @Override
111                 public void run() {
112                         stopRequest = false;
113
114                         Image temp;
115                         int sizeFramebuffer = widthFB * heightFB;
116
117                         while (!stopRequest) {
118                                 synchronized(this) {
119                                         try {
120                                                 this.wait(intervalWait); /* ms */
121                                         } catch (InterruptedException e) {
122                                                 e.printStackTrace();
123                                                 break;
124                                         }
125                                 }
126
127                                 int result = getPixels(arrayFramebuffer); /* from shared memory */
128                                 //logger.info("getPixels native function returned " + result);
129
130                                 imageData.setPixels(0, 0, sizeFramebuffer, arrayFramebuffer, 0);
131
132                                 display.syncExec(new Runnable() {
133                                         @Override
134                                         public void run() {
135                                                 framebuffer.dispose();
136                                                 framebuffer = new Image(display, imageData);
137                                         }
138                                 });
139
140                                 if (display.isDisposed() == false) {
141                                         /* redraw canvas */
142                                         display.asyncExec(runnable);
143                                 }
144                         }
145
146                         logger.info("PollFBThread is stopped");
147
148                         int result = shmdt();
149                         logger.info("shmdt native function returned " + result);
150                 }
151
152                 public void stopRequest() {
153                         stopRequest = true;
154
155                         synchronized(pollThread) {
156                                 pollThread.notify();
157                         }
158                 }
159         }
160
161         /**
162          *  Constructor
163          */
164         public EmulatorShmSkin(EmulatorSkinState state, EmulatorFingers finger,
165                         EmulatorConfig config, SkinInformation skinInfo, boolean isOnTop) {
166                 super(state, finger, config, skinInfo, SWT.NONE, isOnTop);
167                 this.paletteData = new PaletteData(RED_MASK, GREEN_MASK, BLUE_MASK);
168         }
169
170         protected void skinFinalize() {
171                 pollThread.stopRequest();
172
173                 super.finger.setMultiTouchEnable(0);
174                 super.finger.clearFingerSlot();
175                 super.finger.cleanup_multiTouchState();
176
177                 super.skinFinalize();
178         }
179
180         public long initLayout() {
181                 super.initLayout();
182
183                 /* base + 1 = sdb port */
184                 /* base + 2 = shared memory key */
185                 int shmkey = config.getArgInt(ArgsConstants.NET_BASE_PORT) + 2;
186                 logger.info("shmkey = " + shmkey);
187
188                 /* initialize shared memory */
189                 int result = shmget(shmkey,
190                                 currentState.getCurrentResolutionWidth() *
191                                 currentState.getCurrentResolutionHeight() * 4);
192                 logger.info("shmget native function returned " + result);
193
194                 /* update lcd thread */
195                 pollThread = new PollFBThread(
196                                 currentState.getCurrentResolutionWidth(),
197                                 currentState.getCurrentResolutionHeight());
198
199                 lcdCanvas.addPaintListener(new PaintListener() {
200                         public void paintControl(PaintEvent e) { //TODO: optimize
201                                 /* e.gc.setAdvanced(true);
202                                 if (!e.gc.getAdvanced()) {
203                                         logger.info("Advanced graphics not supported");
204                                 } */
205
206                                 int x = lcdCanvas.getSize().x;
207                                 int y = lcdCanvas.getSize().y;
208
209                                 if (pollThread.getWaitIntervalTime() == 0) {
210                                         logger.info("draw black screen");
211
212                                         e.gc.drawRectangle(-1, -1, x + 1, y + 1);
213                                         return;
214                                 }
215
216                                 if (currentState.getCurrentAngle() == 0) { /* portrait */
217                                         e.gc.drawImage(pollThread.framebuffer,
218                                                         0, 0, pollThread.widthFB, pollThread.heightFB,
219                                                         0, 0, x, y);
220
221                                         if (finger.getMultiTouchEnable() == 1) {
222                                                 finger.rearrangeFingerPoints(currentState.getCurrentResolutionWidth(), 
223                                                                 currentState.getCurrentResolutionHeight(), 
224                                                                 currentState.getCurrentScale(), 
225                                                                 currentState.getCurrentRotationId());
226                                         }
227
228                                         finger.drawImage(e, currentState.getCurrentAngle());
229                                         return;
230                                 }
231
232                                 Transform transform = new Transform(lcdCanvas.getDisplay());
233                                 Transform oldtransform = new Transform(lcdCanvas.getDisplay());
234                                 transform.rotate(currentState.getCurrentAngle());
235
236                                 if (currentState.getCurrentAngle() == 90) { /* reverse landscape */
237                                         int temp;
238                                         temp = x;
239                                         x = y;
240                                         y = temp;
241                                         transform.translate(0, y * -1);
242                                 } else if (currentState.getCurrentAngle() == 180) { /* reverse portrait */
243                                         transform.translate(x * -1, y * -1);
244                                 } else if (currentState.getCurrentAngle() == -90) { /* landscape */
245                                         int temp;
246                                         temp = x;
247                                         x = y;
248                                         y = temp;
249                                         transform.translate(x * -1, 0);
250                                 }
251
252                                 /* draw finger image for when rotate while use multitouch */
253                                 if (finger.getMultiTouchEnable() == 1) {
254                                         finger.rearrangeFingerPoints(currentState.getCurrentResolutionWidth(), 
255                                                         currentState.getCurrentResolutionHeight(), 
256                                                         currentState.getCurrentScale(), 
257                                                         currentState.getCurrentRotationId());
258                                 }
259                                 /* save current transform as "oldtransform" */
260                                 e.gc.getTransform(oldtransform);
261                                 /* set to new transfrom */
262                                 e.gc.setTransform(transform);
263                                 e.gc.drawImage(pollThread.framebuffer,
264                                                 0, 0, pollThread.widthFB, pollThread.heightFB,
265                                                 0, 0, x, y);
266                                 /* back to old transform */
267                                 e.gc.setTransform(oldtransform);
268
269                                 transform.dispose();
270                                 finger.drawImage(e, currentState.getCurrentAngle());
271                         }
272                 });
273
274                 pollThread.start();
275
276                 return 0;
277         }
278
279         @Override
280         public void displayOn() {
281                 logger.info("display on");
282
283                 if (pollThread.isAlive()) {
284                         pollThread.setWaitIntervalTime(30);
285
286                         synchronized(pollThread) {
287                                 pollThread.notify();
288                         }
289                 }
290         }
291
292         @Override
293         public void displayOff() {
294                 logger.info("display off");
295
296                 if (pollThread.isAlive()) {
297                         pollThread.setWaitIntervalTime(0);
298
299                         shell.getDisplay().asyncExec(new Runnable() {
300                                 @Override
301                                 public void run() {
302                                         lcdCanvas.redraw();
303                                 }
304                         });
305                 }
306         }
307
308         @Override
309         protected void openScreenShotWindow() {
310                 if (screenShotDialog != null) {
311                         logger.info("screenshot window was already opened");
312                         return;
313                 }
314
315                 try {
316                         screenShotDialog = new ShmScreenShotWindow(shell, communicator, this, config,
317                                         imageRegistry.getIcon(IconName.SCREENSHOT));
318                         screenShotDialog.open();
319
320                 } catch (ScreenShotException ex) {
321                         screenShotDialog = null;
322                         logger.log(Level.SEVERE, ex.getMessage(), ex);
323
324                         SkinUtil.openMessage(shell, null,
325                                         "Fail to create a screen shot.", SWT.ICON_ERROR, config);
326
327                 } catch (Exception ex) {
328                         screenShotDialog = null;
329                         logger.log(Level.SEVERE, ex.getMessage(), ex);
330
331                         SkinUtil.openMessage(shell, null, "ScreenShot is not ready.\n" +
332                                         "Please wait until the emulator is completely boot up.",
333                                         SWT.ICON_WARNING, config);
334                 }
335         }
336 }