Merge "Change SetNativeImageSource() to SetSource()" into devel/master
[platform/core/uifw/dali-adaptor.git] / adaptors / emscripten / sdl-application.cpp
1 // EXTERNAL INCLUDES
2 #include "sdl-application.h"
3
4 #include <SDL.h>
5 #include <SDL_image.h>
6 #include <X11/Xlib.h>
7 #include <EGL/egl.h>
8 #include <SDL_syswm.h>
9 #include <stdio.h>
10 #include <sys/select.h>
11 #include <sys/ioctl.h>
12 #include <termios.h>
13 #include <stropts.h>
14 #include <unistd.h>
15
16 #include <dali/public-api/dali-core.h>
17 #include <dali/integration-api/events/touch-event-integ.h>
18
19 // INTERNAL INCLUDES
20 #include "integration-api/egl-interface.h"
21 #include "base/separate-update-render/frame-time.h"
22 #include <gl/egl-implementation.h>
23
24 #include "platform-abstractions/emscripten/emscripten-callbacks.h"
25
26 // emscripten are using SDL version 1.3 that isnt available for download
27 // but version 2.0 is close to version 1.3 but version 1.2 support removed.
28 // This is one way it isnt.
29 #if SDL_MAJOR_VERSION == 2
30 # define VIDEO_FLAGS SDL_WINDOW_OPENGL
31 #else
32 # define VIDEO_FLAGS SDL_OPENGL
33 #endif
34
35 namespace
36 {
37
38 int _kbhit()
39 {
40   static const int STDIN = 0;
41   static bool initialized = false;
42
43   if (! initialized)
44   {
45     // Use termios to turn off line buffering
46     termios term;
47     tcgetattr(STDIN, &term);
48     term.c_lflag &= ~ICANON;
49     tcsetattr(STDIN, TCSANOW, &term);
50     setbuf(stdin, NULL);
51     initialized = true;
52   }
53
54   int bytesWaiting;
55   ioctl(STDIN, FIONREAD, &bytesWaiting);
56   return bytesWaiting;
57 }
58
59
60 void LogFunction(Dali::Integration::Log::DebugPriority priority, std::string& message)
61 {
62   printf("%s", message.c_str());
63   EM_ASM( console.log( message.c_str() ) );
64 }
65
66 }
67
68 namespace Dali
69 {
70
71 typedef ::Pixmap XPixmap;
72 typedef ::Window XWindow;
73 typedef ::Display XDisplay;
74 typedef ::Screen XScreen;
75
76 const unsigned int SdlApplication::DEFAULT_SURFACE_WIDTH = 600;
77 const unsigned int SdlApplication::DEFAULT_SURFACE_HEIGHT= 480;
78
79
80 SdlApplication::SdlApplication( size_t surfaceWidth,
81                                 size_t surfaceHeight,
82                                 float  horizontalDpi,
83                                 float  verticalDpi )
84   : mCore( NULL ),
85     mSurfaceWidth( surfaceWidth ),
86     mSurfaceHeight( surfaceHeight ),
87     mFrame( 0u ),
88     mSeconds(0),
89     mMicroSeconds(0)
90 {
91
92   EGLNativeDisplayType  display        = (EGLNativeDisplayType)XOpenDisplay(NULL);
93   bool                  isOwnSurface   = true;
94   mEglImplementation.InitializeGles( display, isOwnSurface );
95
96   SdlCreateWindow(surfaceWidth, surfaceHeight, "Dali");
97
98   bool                  isWindowType      = true;
99   Dali::ColorDepth      depth             = Dali::COLOR_DEPTH_32;
100   mEglImplementation.ChooseConfig( isWindowType, depth );
101
102   EGLNativeWindowType window = NULL;
103
104   mEglImplementation.CreateSurfaceWindow( window, depth );
105
106   mEglImplementation.CreateContext();
107
108   mEglImplementation.MakeContextCurrent();
109
110   //
111   // SDL/EGL setup, now create core
112   //
113   mCore = Dali::Integration::Core::New(
114     mRenderController,
115     mPlatformAbstraction,
116     mGlAbstraction,
117     mGlSyncAbstraction,
118     mGestureManager,
119     ResourcePolicy::DataRetention::DALI_RETAINS_ALL_DATA);
120
121   mCore->ContextCreated();
122   mCore->SurfaceResized( mSurfaceWidth, mSurfaceHeight );
123   mCore->SetDpi( horizontalDpi, verticalDpi );
124
125   Dali::Integration::Log::InstallLogFunction( LogFunction );
126
127   mCore->SceneCreated();
128 }
129
130 SdlApplication::~SdlApplication()
131 {
132   Dali::Integration::Log::UninstallLogFunction();
133   delete mCore;
134   SDL_Quit();
135 }
136
137 void SdlApplication::SdlCreateWindow(size_t surfaceWidth,
138                                      size_t surfaceHeight,
139                                      const std::string &title)
140 {
141   if( SDL_Init( SDL_INIT_VIDEO ) < 0 )
142   {
143     DALI_LOG_WARNING("SDL_Init Err: %s\n", SDL_GetError() );
144     DALI_ASSERT_ALWAYS(!"Couldn't initialize SDL");
145   }
146
147   // load support for the JPG and PNG image formats
148   int flags    = IMG_INIT_JPG | IMG_INIT_PNG;
149   int initted  = IMG_Init(flags);
150   if( (initted & flags) != flags)
151   {
152     DALI_LOG_WARNING("IMG_Init Err:%s\n", IMG_GetError());
153     DALI_ASSERT_ALWAYS("!IMG_Init: Failed to init required jpg and png support!\n");
154   }
155
156   float gamma      = 0.0;
157   int bpp          = 0; // 0 means current display bpp
158
159   Uint32 video_flags = VIDEO_FLAGS;
160
161   SDL_Surface *surface = SDL_SetVideoMode( static_cast<int>(surfaceWidth),
162                                            static_cast<int>(surfaceHeight),
163                                            bpp,
164                                            video_flags );
165
166   if ( surface == NULL )
167   {
168     DALI_LOG_WARNING("Couldn't set GL mode: %s\n", SDL_GetError());
169     DALI_ASSERT_ALWAYS("Couldn't set GL mode");
170     SDL_Quit();
171     exit(1);
172   }
173
174   /* Set the window manager title bar */
175   SDL_WM_SetCaption( title.c_str(), "daliweb" );
176
177   /* Set the gamma for the window */
178   if ( gamma != 0.0 )
179   {
180     SDL_SetGamma(gamma, gamma, gamma);
181   }
182
183 }
184
185 void SdlApplication::DoUpdate( void )
186 {
187   // pump events
188   mCore->ProcessEvents();
189
190   // Update Time values
191   static Internal::Adaptor::FrameTime frameTime;
192   static bool init = false;
193   if( !init )
194   {
195     frameTime.SetMinimumFrameTimeInterval( 16667 );
196     init = true;
197   }
198
199   static unsigned int frameNo = 0;
200   frameNo++;
201   frameTime.SetSyncTime(frameNo);
202
203   float lastFrameDelta( 0.0f );
204   unsigned int lastSyncTime( 0 );
205   unsigned int nextSyncTime( 0 );
206   frameTime.PredictNextSyncTime( lastFrameDelta, lastSyncTime, nextSyncTime );
207
208   Integration::UpdateStatus status;
209
210   mCore->Update( lastFrameDelta, lastSyncTime, nextSyncTime, status );
211
212   Dali::Internal::Emscripten::stats.lastFrameDeltaSeconds = lastFrameDelta;
213   Dali::Internal::Emscripten::stats.lastSyncTimeMilliseconds = lastSyncTime;
214   Dali::Internal::Emscripten::stats.nextSyncTimeMilliseconds = nextSyncTime;
215
216   Dali::Internal::Emscripten::stats.keepUpdating = status.keepUpdating;
217   Dali::Internal::Emscripten::stats.needsNotification = status.needsNotification;
218   Dali::Internal::Emscripten::stats.secondsFromLastFrame = status.secondsFromLastFrame;
219
220 }
221
222
223 void SdlApplication::DoRender()
224 {
225   // render
226   mCore->Render( mRenderStatus );
227
228   mFrame++;
229
230   Dali::Internal::Emscripten::stats.frameCount = mFrame;
231
232   mEglImplementation.SwapBuffers();
233
234 }
235
236 void SdlApplication::SendTouchEvent(double x, double y, int mouseState)
237 {
238   TouchPoint::State state = TouchPoint::Up;
239   if( 0 == mouseState )
240   {
241     state = TouchPoint::Down;
242   }
243   else if( 1 == mouseState )
244   {
245     state = TouchPoint::Up;
246   }
247   else if( 2 == mouseState )
248   {
249     state = TouchPoint::Motion;
250   }
251
252   Dali::Integration::TouchEvent e;
253   e.AddPoint( TouchPoint( 0,
254                           state,
255                           static_cast<float>(x),
256                           static_cast<float>(y) ) );
257
258   mCore->QueueEvent(e);
259 }
260
261 void SdlApplication::SetSurfaceWidth( unsigned int width, unsigned height )
262 {
263   mSurfaceWidth = width;
264   mSurfaceHeight = height;
265
266   mCore->SurfaceResized( mSurfaceWidth, mSurfaceHeight );
267 }
268
269 }