git.s-ol.nu ~forks/DiligentTools / 6699190
clang-formatted NativeApp Egor Yusov 2 years ago
13 changed file(s) with 350 addition(s) and 338 deletion(s). Raw diff Collapse all Expand all
2020 * of the possibility of such damages.
2121 */
2222
23 #pragma once
23 #pragma once
2424
2525 #include <memory>
2626
3737 class AndroidAppBase : public AppBase
3838 {
3939 public:
40 int InitDisplay();
41 void SetState(android_app* state, const char* native_activity_class_name);
42 void InitSensors();
43 void ProcessSensors( int32_t id );
44 void DrawFrame();
45 bool IsReady();
46 virtual void TrimMemory() = 0;
47 virtual void TermDisplay() = 0;
40 int InitDisplay();
41 void SetState(android_app* state, const char* native_activity_class_name);
42 void InitSensors();
43 void ProcessSensors(int32_t id);
44 void DrawFrame();
45 bool IsReady();
46 virtual void TrimMemory() = 0;
47 virtual void TermDisplay() = 0;
4848 static int32_t HandleInput(android_app* app, AInputEvent* event);
49 static void HandleCmd(android_app* app, int32_t cmd);
49 static void HandleCmd(android_app* app, int32_t cmd);
50
5051 bool CheckWindowSizeChanged()
5152 {
52 auto new_window_width_ = ANativeWindow_getWidth(app_->window);
53 auto new_window_width_ = ANativeWindow_getWidth(app_->window);
5354 auto new_window_height_ = ANativeWindow_getHeight(app_->window);
54 if(new_window_width_ != window_width_ || new_window_height_ != window_height_)
55 if (new_window_width_ != window_width_ || new_window_height_ != window_height_)
5556 {
56 window_width_ = new_window_width_;
57 window_width_ = new_window_width_;
5758 window_height_ = new_window_height_;
5859 return true;
5960 }
6970
7071 virtual int Resume(ANativeWindow* window) = 0;
7172
72 virtual int32_t HandleInput(AInputEvent* event ){return 0;}
73 virtual int32_t HandleInput(AInputEvent* event) { return 0; }
7374
7475 virtual void LoadResources()
7576 {
8384 }
8485
8586 ndk_helper::DoubletapDetector doubletap_detector_;
86 ndk_helper::PinchDetector pinch_detector_;
87 ndk_helper::DragDetector drag_detector_;
88 ndk_helper::PerfMonitor monitor_;
87 ndk_helper::PinchDetector pinch_detector_;
88 ndk_helper::DragDetector drag_detector_;
89 ndk_helper::PerfMonitor monitor_;
8990
9091 //ndk_helper::TapCamera tap_camera_;
9192 android_app* app_ = nullptr;
9293 std::string native_activity_class_name_;
9394
9495 private:
95 void UpdatePosition( AInputEvent* event, int32_t iIndex, float& fX, float& fY );
96 void UpdatePosition(AInputEvent* event, int32_t iIndex, float& fX, float& fY);
9697 void SuspendSensors();
9798 void ResumeSensors();
9899 void ShowUI();
99 void UpdateFPS( float fFPS );
100 void UpdateFPS(float fFPS);
100101
101 bool initialized_resources_ = false;
102 bool has_focus_ = false;
103 int32_t window_width_ = 0;
104 int32_t window_height_ = 0;
102 bool initialized_resources_ = false;
103 bool has_focus_ = false;
104 int32_t window_width_ = 0;
105 int32_t window_height_ = 0;
105106
106 ASensorManager* sensor_manager_ = nullptr;
107 const ASensor* accelerometer_sensor_ = nullptr;
108 ASensorEventQueue* sensor_event_queue_ = nullptr;
107 ASensorManager* sensor_manager_ = nullptr;
108 const ASensor* accelerometer_sensor_ = nullptr;
109 ASensorEventQueue* sensor_event_queue_ = nullptr;
109110 };
110111
111 }
112 } // namespace Diligent
2020 * of the possibility of such damages.
2121 */
2222
23 #pragma once
23 #pragma once
2424
2525 namespace Diligent
2626 {
3030 public:
3131 virtual ~AppBase() {}
3232
33 virtual void ProcessCommandLine(const char* CmdLine) = 0;
34 virtual const char* GetAppTitle()const = 0;
35 virtual void Update(double CurrTime, double ElapsedTime) {};
36 virtual void Render() = 0;
37 virtual void Present() = 0;
38 virtual void WindowResize(int width, int height) = 0;
39 virtual void GetDesiredInitialWindowSize(int& width, int& height)
33 virtual void ProcessCommandLine(const char* CmdLine) = 0;
34 virtual const char* GetAppTitle() const = 0;
35 virtual void Update(double CurrTime, double ElapsedTime){};
36 virtual void Render() = 0;
37 virtual void Present() = 0;
38 virtual void WindowResize(int width, int height) = 0;
39 virtual void GetDesiredInitialWindowSize(int& width, int& height)
4040 {
4141 width = 0;
4242 height = 0;
4343 }
4444 };
4545
46 }
46 } // namespace Diligent
2020 * of the possibility of such damages.
2121 */
2222
23 #pragma once
23 #pragma once
2424
2525 #include "AppBase.h"
2626 #include "Timer.h"
3232 {
3333 public:
3434 using AppBase::Update;
35 void Update();
35 void Update();
3636 virtual void Initialize(int deviceType, void* layer) = 0;
37 virtual void OnTouchBegan(float x, float y){}
38 virtual void OnTouchMoved(float x, float y){}
39 virtual void OnTouchEnded(float x, float y){}
37 virtual void OnTouchBegan(float x, float y) {}
38 virtual void OnTouchMoved(float x, float y) {}
39 virtual void OnTouchEnded(float x, float y) {}
4040
4141 protected:
42 Timer timer;
42 Timer timer;
4343 double PrevTime = 0.0;
4444 };
4545
46 }
46 } // namespace Diligent
2020 * of the possibility of such damages.
2121 */
2222
23 #pragma once
23 #pragma once
2424
2525
2626 #include <GL/glx.h>
2828
2929 // Undef symbols defined by XLib
3030 #ifdef Bool
31 # undef Bool
31 # undef Bool
3232 #endif
3333 #ifdef True
34 # undef True
34 # undef True
3535 #endif
3636 #ifdef False
37 # undef False
37 # undef False
3838 #endif
3939
4040 #if VULKAN_SUPPORTED
41 #include <xcb/xcb.h>
41 # include <xcb/xcb.h>
4242 #endif
4343
4444 #include "AppBase.h"
5050 {
5151 public:
5252 virtual void OnGLContextCreated(Display* display, Window window) = 0;
53 virtual int HandleXEvent(XEvent* xev){}
53 virtual int HandleXEvent(XEvent* xev) {}
5454
5555 #if VULKAN_SUPPORTED
5656 virtual bool InitVulkan(xcb_connection_t* connection, uint32_t window) = 0;
57 virtual void HandleXCBEvent(xcb_generic_event_t* event){}
57 virtual void HandleXCBEvent(xcb_generic_event_t* event) {}
5858 #endif
5959 };
6060
61 }
61 } // namespace Diligent
2020 * of the possibility of such damages.
2121 */
2222
23 #pragma once
23 #pragma once
2424
2525 #include "AppBase.h"
2626 #include "Timer.h"
3232 {
3333 public:
3434 using AppBase::Update;
35 void Update();
35 void Update();
3636 virtual void Initialize(void* view) = 0;
3737 virtual void HandleOSXEvent(void* event, void* view){};
3838
3939 protected:
40 Timer timer;
40 Timer timer;
4141 double PrevTime = 0.0;
4242 };
4343
44 }
44 } // namespace Diligent
1919 * all other commercial damages or losses), even if such Contributor has been advised
2020 * of the possibility of such damages.
2121 */
22 #pragma once
22 #pragma once
23
24 // clang-format off
2325
2426 #if PLATFORM_WIN32
2527
7779 namespace Diligent
7880 {
7981 extern NativeAppBase* CreateApplication();
80 }
82 }
2020 * of the possibility of such damages.
2121 */
2222
23 #pragma once
23 #pragma once
2424
2525 #ifndef NOMINMAX
26 # define NOMINMAX
26 # define NOMINMAX
2727 #endif
2828 #include <Windows.h>
2929
3939 LONG WindowWidth,
4040 LONG WindowHeight) = 0;
4141
42 virtual LRESULT HandleWin32Message(HWND hWnd,
43 UINT message,
44 WPARAM wParam,
45 LPARAM lParam)
42 virtual LRESULT HandleWin32Message(HWND hWnd,
43 UINT message,
44 WPARAM wParam,
45 LPARAM lParam)
4646 {
4747 return 0;
4848 }
4949 };
5050
51 }
51 } // namespace Diligent
3434
3535 int AndroidAppBase::InitDisplay()
3636 {
37 if( !initialized_resources_ )
37 if (!initialized_resources_)
3838 {
3939 Initialize();
4040
4444 else
4545 {
4646 // initialize OpenGL ES and EGL
47 if( EGL_SUCCESS != Resume( app_->window ) )
47 if (EGL_SUCCESS != Resume(app_->window))
4848 {
4949 UnloadResources();
5050 LoadResources();
5656 //tap_camera_.SetFlip( 1.f, -1.f, -1.f );
5757 //tap_camera_.SetPinchTransformFactor( 2.f, 2.f, 8.f );
5858
59 return 0;
59 return 0;
6060 }
6161
6262 void AndroidAppBase::InitSensors()
6363 {
64 sensor_manager_ = ASensorManager_getInstance();
65 accelerometer_sensor_ = ASensorManager_getDefaultSensor( sensor_manager_, ASENSOR_TYPE_ACCELEROMETER );
66 sensor_event_queue_ = ASensorManager_createEventQueue( sensor_manager_, app_->looper, LOOPER_ID_USER, NULL, NULL );
64 sensor_manager_ = ASensorManager_getInstance();
65 accelerometer_sensor_ = ASensorManager_getDefaultSensor(sensor_manager_, ASENSOR_TYPE_ACCELEROMETER);
66 sensor_event_queue_ = ASensorManager_createEventQueue(sensor_manager_, app_->looper, LOOPER_ID_USER, NULL, NULL);
6767 }
6868
6969 //
7474 // APP_CMD_CONFIG_CHANGED event is generated seveal frames
7575 // before the screen is actually resized. The only robust way
7676 // to detect window resize is to check it very frame
77 if(CheckWindowSizeChanged())
78 WindowResize(0,0);
77 if (CheckWindowSizeChanged())
78 WindowResize(0, 0);
7979
8080 float fFPS;
81 if( monitor_.Update( fFPS ) )
82 {
83 UpdateFPS( fFPS );
81 if (monitor_.Update(fFPS))
82 {
83 UpdateFPS(fFPS);
8484 }
8585
8686 static Diligent::Timer Timer;
87 static double PrevTime = Timer.GetElapsedTime();
88 auto CurrTime = Timer.GetElapsedTime();
89 auto ElapsedTime = CurrTime - PrevTime;
87
88 static double PrevTime = Timer.GetElapsedTime();
89 auto CurrTime = Timer.GetElapsedTime();
90 auto ElapsedTime = CurrTime - PrevTime;
91
9092 PrevTime = CurrTime;
9193
9294 Update(CurrTime, ElapsedTime);
105107 //
106108 // Process the next input event.
107109 //
108 int32_t AndroidAppBase::HandleInput( android_app* app, AInputEvent* event )
110 int32_t AndroidAppBase::HandleInput(android_app* app, AInputEvent* event)
109111 {
110112 AndroidAppBase* eng = (AndroidAppBase*)app->userData;
111 return eng->HandleInput( event );
113 return eng->HandleInput(event);
112114 }
113115
114116 //
115117 // Process the next main command.
116118 //
117 void AndroidAppBase::HandleCmd( struct android_app* app, int32_t cmd )
119 void AndroidAppBase::HandleCmd(struct android_app* app, int32_t cmd)
118120 {
119121 AndroidAppBase* eng = (AndroidAppBase*)app->userData;
120 switch( cmd )
121 {
122 case APP_CMD_SAVE_STATE:
123 break;
124
125 case APP_CMD_INIT_WINDOW:
126 // The window is being shown, get it ready.
127 if( app->window != NULL )
128 {
129 eng->InitDisplay();
122 switch (cmd)
123 {
124 case APP_CMD_SAVE_STATE:
125 break;
126
127 case APP_CMD_INIT_WINDOW:
128 // The window is being shown, get it ready.
129 if (app->window != NULL)
130 {
131 eng->InitDisplay();
132 eng->DrawFrame();
133 }
134 break;
135
136 case APP_CMD_CONFIG_CHANGED:
137 case APP_CMD_WINDOW_RESIZED:
138 // This does not work as the screen resizes few frames
139 // after the event has been received
140 // eng->WindowResize(0,0);
141 break;
142
143 case APP_CMD_TERM_WINDOW:
144 // The window is being hidden or closed, clean it up.
145 eng->TermDisplay();
146 eng->has_focus_ = false;
147 break;
148
149 case APP_CMD_STOP:
150 break;
151
152 case APP_CMD_GAINED_FOCUS:
153 eng->ResumeSensors();
154 //Start animation
155 eng->has_focus_ = true;
156 break;
157
158 case APP_CMD_LOST_FOCUS:
159 eng->SuspendSensors();
160 // Also stop animating.
161 eng->has_focus_ = false;
130162 eng->DrawFrame();
131 }
132 break;
133
134 case APP_CMD_CONFIG_CHANGED:
135 case APP_CMD_WINDOW_RESIZED:
136 // This does not work as the screen resizes few frames
137 // after the event has been received
138 // eng->WindowResize(0,0);
139 break;
140
141 case APP_CMD_TERM_WINDOW:
142 // The window is being hidden or closed, clean it up.
143 eng->TermDisplay();
144 eng->has_focus_ = false;
145 break;
146
147 case APP_CMD_STOP:
148 break;
149
150 case APP_CMD_GAINED_FOCUS:
151 eng->ResumeSensors();
152 //Start animation
153 eng->has_focus_ = true;
154 break;
155
156 case APP_CMD_LOST_FOCUS:
157 eng->SuspendSensors();
158 // Also stop animating.
159 eng->has_focus_ = false;
160 eng->DrawFrame();
161 break;
162
163 case APP_CMD_LOW_MEMORY:
164 //Free up GL resources
165 eng->TrimMemory();
166 break;
163 break;
164
165 case APP_CMD_LOW_MEMORY:
166 //Free up GL resources
167 eng->TrimMemory();
168 break;
167169 }
168170 }
169171
170172 //-------------------------------------------------------------------------
171173 //Sensor handlers
172174 //-------------------------------------------------------------------------
173 void AndroidAppBase::ProcessSensors( int32_t id )
175 void AndroidAppBase::ProcessSensors(int32_t id)
174176 {
175177 // If a sensor has data, process it now.
176 if( id == LOOPER_ID_USER )
177 {
178 if( accelerometer_sensor_ != NULL )
178 if (id == LOOPER_ID_USER)
179 {
180 if (accelerometer_sensor_ != NULL)
179181 {
180182 ASensorEvent event;
181 while( ASensorEventQueue_getEvents( sensor_event_queue_, &event, 1 ) > 0 )
183 while (ASensorEventQueue_getEvents(sensor_event_queue_, &event, 1) > 0)
182184 {
183185 }
184186 }
188190 void AndroidAppBase::ResumeSensors()
189191 {
190192 // When our app gains focus, we start monitoring the accelerometer.
191 if( accelerometer_sensor_ != NULL )
192 {
193 ASensorEventQueue_enableSensor( sensor_event_queue_, accelerometer_sensor_ );
193 if (accelerometer_sensor_ != NULL)
194 {
195 ASensorEventQueue_enableSensor(sensor_event_queue_, accelerometer_sensor_);
194196 // We'd like to get 60 events per second (in us).
195 ASensorEventQueue_setEventRate( sensor_event_queue_, accelerometer_sensor_,
196 (1000L / 60) * 1000 );
197 ASensorEventQueue_setEventRate(sensor_event_queue_, accelerometer_sensor_,
198 (1000L / 60) * 1000);
197199 }
198200 }
199201
201203 {
202204 // When our app loses focus, we stop monitoring the accelerometer.
203205 // This is to avoid consuming battery while not being used.
204 if( accelerometer_sensor_ != NULL )
205 {
206 ASensorEventQueue_disableSensor( sensor_event_queue_, accelerometer_sensor_ );
206 if (accelerometer_sensor_ != NULL)
207 {
208 ASensorEventQueue_disableSensor(sensor_event_queue_, accelerometer_sensor_);
207209 }
208210 }
209211
210212 //-------------------------------------------------------------------------
211213 //Misc
212214 //-------------------------------------------------------------------------
213 void AndroidAppBase::SetState( android_app* state, const char* native_activity_class_name )
215 void AndroidAppBase::SetState(android_app* state, const char* native_activity_class_name)
214216 {
215217 app_ = state;
218
216219 native_activity_class_name_ = native_activity_class_name;
217 doubletap_detector_.SetConfiguration( app_->config );
218 drag_detector_.SetConfiguration( app_->config );
219 pinch_detector_.SetConfiguration( app_->config );
220 doubletap_detector_.SetConfiguration(app_->config);
221 drag_detector_.SetConfiguration(app_->config);
222 pinch_detector_.SetConfiguration(app_->config);
220223 }
221224
222225 bool AndroidAppBase::IsReady()
223226 {
224 if( has_focus_ )
227 if (has_focus_)
225228 return true;
226229
227230 return false;
236239
237240 void AndroidAppBase::ShowUI()
238241 {
239 JNIEnv *jni;
240 app_->activity->vm->AttachCurrentThread( &jni, NULL );
242 JNIEnv* jni;
243 app_->activity->vm->AttachCurrentThread(&jni, NULL);
241244
242245 //Default class retrieval
243 jclass clazz = jni->GetObjectClass( app_->activity->clazz );
244 jmethodID methodID = jni->GetMethodID( clazz, "showUI", "()V" );
245 jni->CallVoidMethod( app_->activity->clazz, methodID );
246 jclass clazz = jni->GetObjectClass(app_->activity->clazz);
247 jmethodID methodID = jni->GetMethodID(clazz, "showUI", "()V");
248 jni->CallVoidMethod(app_->activity->clazz, methodID);
246249
247250 app_->activity->vm->DetachCurrentThread();
248251 return;
249252 }
250253
251 void AndroidAppBase::UpdateFPS( float fFPS )
252 {
253 JNIEnv *jni;
254 app_->activity->vm->AttachCurrentThread( &jni, NULL );
254 void AndroidAppBase::UpdateFPS(float fFPS)
255 {
256 JNIEnv* jni;
257 app_->activity->vm->AttachCurrentThread(&jni, NULL);
255258
256259 //Default class retrieval
257 jclass clazz = jni->GetObjectClass( app_->activity->clazz );
258 jmethodID methodID = jni->GetMethodID( clazz, "updateFPS", "(F)V" );
259 jni->CallVoidMethod( app_->activity->clazz, methodID, fFPS );
260 jclass clazz = jni->GetObjectClass(app_->activity->clazz);
261 jmethodID methodID = jni->GetMethodID(clazz, "updateFPS", "(F)V");
262 jni->CallVoidMethod(app_->activity->clazz, methodID, fFPS);
260263
261264 app_->activity->vm->DetachCurrentThread();
262265 return;
263266 }
264267
265 }
268 } // namespace Diligent
0 /* Copyright 2015-2018 Egor Yusov
0 /* Copyright 2015-2018 Egor Yusov
11 *
22 * Licensed under the Apache License, Version 2.0 (the "License");
33 * you may not use this file except in compliance with the License.
2828 #include "NativeAppBase.h"
2929
3030
31 #define HELPER_CLASS_NAME "com/android/helper/NDKHelper" //Class name of helper function
31 #define HELPER_CLASS_NAME "com/android/helper/NDKHelper" //Class name of helper function
3232 #define NATIVEACTIVITY_CLASS_NAME "android/app/NativeActivity"
3333
3434 using namespace Diligent;
3636 // This is the main entry point of a native application that is using
3737 // android_native_app_glue. It runs in its own thread, with its own
3838 // event loop for receiving input events and doing other things.
39 void android_main( android_app* state )
39 void android_main(android_app* state)
4040 {
4141 std::unique_ptr<AndroidAppBase> theApp(CreateApplication());
42 theApp->SetState( state, NATIVEACTIVITY_CLASS_NAME );
42 theApp->SetState(state, NATIVEACTIVITY_CLASS_NAME);
4343
4444 //Init helper functions
45 ndk_helper::JNIHelper::Init( state->activity, HELPER_CLASS_NAME );
45 ndk_helper::JNIHelper::Init(state->activity, HELPER_CLASS_NAME);
4646
47 state->userData = theApp.get();
48 state->onAppCmd = AndroidAppBase::HandleCmd;
47 state->userData = theApp.get();
48 state->onAppCmd = AndroidAppBase::HandleCmd;
4949 state->onInputEvent = AndroidAppBase::HandleInput;
5050
5151 #ifdef USE_NDK_PROFILER
52 monstartup( "libEngineSandbox.so" );
52 monstartup("libEngineSandbox.so");
5353 #endif
5454
5555 // Prepare to monitor accelerometer
5656 theApp->InitSensors();
5757
5858 // loop waiting for stuff to do.
59 while( 1 )
59 while (true)
6060 {
6161 // Read all pending events.
62 int id;
63 int events;
62 int id;
63 int events;
6464 android_poll_source* source;
6565
6666 // If not animating, we will block forever waiting for events.
6767 // If animating, we loop until all events are read, then continue
6868 // to draw the next frame of animation.
69 while( (id = ALooper_pollAll( theApp->IsReady() ? 0 : -1, NULL, &events, (void**)&source )) >= 0 )
69 while ((id = ALooper_pollAll(theApp->IsReady() ? 0 : -1, NULL, &events, (void**)&source)) >= 0)
7070 {
7171 // Process this event.
72 if( source != NULL )
73 source->process( state, source );
72 if (source != NULL)
73 source->process(state, source);
7474
75 theApp->ProcessSensors( id );
75 theApp->ProcessSensors(id);
7676
7777 // Check if we are exiting.
78 if( state->destroyRequested != 0 )
78 if (state->destroyRequested != 0)
7979 {
8080 theApp->TermDisplay();
8181 return;
8282 }
8383 }
8484
85 if( theApp->IsReady() )
85 if (theApp->IsReady())
8686 {
8787 // Drawing is throttled to the screen update rate, so there
8888 // is no need to do timing here.
2828 void IOSAppBase::Update()
2929 {
3030 // Render the scene
31 auto CurrTime = timer.GetElapsedTime();
31 auto CurrTime = timer.GetElapsedTime();
3232 auto ElapsedTime = CurrTime - PrevTime;
33 PrevTime = CurrTime;
33 PrevTime = CurrTime;
3434 Update(CurrTime, ElapsedTime);
3535 }
3636
37 }
37 } // namespace Diligent
3131
3232
3333 #ifndef GLX_CONTEXT_MAJOR_VERSION_ARB
34 # define GLX_CONTEXT_MAJOR_VERSION_ARB 0x2091
34 # define GLX_CONTEXT_MAJOR_VERSION_ARB 0x2091
3535 #endif
3636
3737 #ifndef GLX_CONTEXT_MINOR_VERSION_ARB
38 # define GLX_CONTEXT_MINOR_VERSION_ARB 0x2092
38 # define GLX_CONTEXT_MINOR_VERSION_ARB 0x2092
3939 #endif
4040
4141 #ifndef GLX_CONTEXT_FLAGS_ARB
42 # define GLX_CONTEXT_FLAGS_ARB 0x2094
42 # define GLX_CONTEXT_FLAGS_ARB 0x2094
4343 #endif
4444
4545 #ifndef GLX_CONTEXT_DEBUG_BIT_ARB
46 # define GLX_CONTEXT_DEBUG_BIT_ARB 0x0001
46 # define GLX_CONTEXT_DEBUG_BIT_ARB 0x0001
4747 #endif
4848
4949 typedef GLXContext (*glXCreateContextAttribsARBProc)(Display*, GLXFBConfig, GLXContext, int, const int*);
5757
5858 namespace
5959 {
60
60
6161 class WindowTitleHelper
6262 {
6363 public:
64 WindowTitleHelper(std::string _Title) :
65 Title(std::move(_Title))
64 WindowTitleHelper(std::string _Title) :
65 Title{std::move(_Title)}
6666 {}
67
67
6868 std::string GetTitleWithFPS(double ElapsedTime)
6969 {
7070 double filterScale = 0.2;
71 FilteredFrameTime = FilteredFrameTime * (1.0 - filterScale) + filterScale * ElapsedTime;
71 FilteredFrameTime = FilteredFrameTime * (1.0 - filterScale) + filterScale * ElapsedTime;
7272 std::stringstream TitleWithFpsSS;
7373 TitleWithFpsSS << Title;
7474 TitleWithFpsSS << " - " << std::fixed << std::setprecision(1) << FilteredFrameTime * 1000;
7878
7979 private:
8080 const std::string Title;
81 double FilteredFrameTime = 0.0;
81 double FilteredFrameTime = 0.0;
8282 };
8383
84 }
84 } // namespace
8585
8686 #if VULKAN_SUPPORTED
8787
8888 // https://code.woboq.org/qt5/include/xcb/xcb_icccm.h.html
8989 enum XCB_SIZE_HINT
9090 {
91 XCB_SIZE_HINT_US_POSITION = 1 << 0,
92 XCB_SIZE_HINT_US_SIZE = 1 << 1,
93 XCB_SIZE_HINT_P_POSITION = 1 << 2,
94 XCB_SIZE_HINT_P_SIZE = 1 << 3,
95 XCB_SIZE_HINT_P_MIN_SIZE = 1 << 4,
96 XCB_SIZE_HINT_P_MAX_SIZE = 1 << 5,
97 XCB_SIZE_HINT_P_RESIZE_INC = 1 << 6,
98 XCB_SIZE_HINT_P_ASPECT = 1 << 7,
99 XCB_SIZE_HINT_BASE_SIZE = 1 << 8,
100 XCB_SIZE_HINT_P_WIN_GRAVITY = 1 << 9
91 XCB_SIZE_HINT_US_POSITION = 1 << 0,
92 XCB_SIZE_HINT_US_SIZE = 1 << 1,
93 XCB_SIZE_HINT_P_POSITION = 1 << 2,
94 XCB_SIZE_HINT_P_SIZE = 1 << 3,
95 XCB_SIZE_HINT_P_MIN_SIZE = 1 << 4,
96 XCB_SIZE_HINT_P_MAX_SIZE = 1 << 5,
97 XCB_SIZE_HINT_P_RESIZE_INC = 1 << 6,
98 XCB_SIZE_HINT_P_ASPECT = 1 << 7,
99 XCB_SIZE_HINT_BASE_SIZE = 1 << 8,
100 XCB_SIZE_HINT_P_WIN_GRAVITY = 1 << 9
101101 };
102102
103103 struct xcb_size_hints_t
104104 {
105 uint32_t flags; /** User specified flags */
106 int32_t x, y; /** User-specified position */
107 int32_t width, height; /** User-specified size */
108 int32_t min_width, min_height; /** Program-specified minimum size */
109 int32_t max_width, max_height; /** Program-specified maximum size */
110 int32_t width_inc, height_inc; /** Program-specified resize increments */
111 int32_t min_aspect_num, min_aspect_den; /** Program-specified minimum aspect ratios */
112 int32_t max_aspect_num, max_aspect_den; /** Program-specified maximum aspect ratios */
113 int32_t base_width, base_height; /** Program-specified base size */
114 uint32_t win_gravity; /** Program-specified window gravity */
105 uint32_t flags; /** User specified flags */
106 int32_t x, y; /** User-specified position */
107 int32_t width, height; /** User-specified size */
108 int32_t min_width, min_height; /** Program-specified minimum size */
109 int32_t max_width, max_height; /** Program-specified maximum size */
110 int32_t width_inc, height_inc; /** Program-specified resize increments */
111 int32_t min_aspect_num, min_aspect_den; /** Program-specified minimum aspect ratios */
112 int32_t max_aspect_num, max_aspect_den; /** Program-specified maximum aspect ratios */
113 int32_t base_width, base_height; /** Program-specified base size */
114 uint32_t win_gravity; /** Program-specified window gravity */
115115 };
116116
117117 struct XCBInfo
118118 {
119 xcb_connection_t* connection = nullptr;
120 uint32_t window = 0;
121 uint16_t width = 0;
122 uint16_t height = 0;
119 xcb_connection_t* connection = nullptr;
120 uint32_t window = 0;
121 uint16_t width = 0;
122 uint16_t height = 0;
123123 xcb_intern_atom_reply_t* atom_wm_delete_window = nullptr;
124124 };
125125
127127 {
128128 XCBInfo info;
129129
130 int scr = 0;
130 int scr = 0;
131131 info.connection = xcb_connect(nullptr, &scr);
132132 if (info.connection == nullptr || xcb_connection_has_error(info.connection))
133133 {
135135 exit(-1);
136136 }
137137
138 const xcb_setup_t* setup = xcb_get_setup(info.connection);
139 xcb_screen_iterator_t iter = xcb_setup_roots_iterator(setup);
138 const xcb_setup_t* setup = xcb_get_setup(info.connection);
139 xcb_screen_iterator_t iter = xcb_setup_roots_iterator(setup);
140140 while (scr-- > 0)
141141 xcb_screen_next(&iter);
142142
143143 auto screen = iter.data;
144144
145 info.width = WindowWidth;
145 info.width = WindowWidth;
146146 info.height = WindowHeight;
147147
148148 uint32_t value_mask, value_list[32];
149149
150150 info.window = xcb_generate_id(info.connection);
151151
152 value_mask = XCB_CW_BACK_PIXEL | XCB_CW_EVENT_MASK;
152 value_mask = XCB_CW_BACK_PIXEL | XCB_CW_EVENT_MASK;
153153 value_list[0] = screen->black_pixel;
154154 value_list[1] =
155155 XCB_EVENT_MASK_KEY_RELEASE |
156 XCB_EVENT_MASK_KEY_PRESS |
157 XCB_EVENT_MASK_EXPOSURE |
158 XCB_EVENT_MASK_STRUCTURE_NOTIFY |
159 XCB_EVENT_MASK_POINTER_MOTION |
160 XCB_EVENT_MASK_BUTTON_PRESS |
161 XCB_EVENT_MASK_BUTTON_RELEASE;
156 XCB_EVENT_MASK_KEY_PRESS |
157 XCB_EVENT_MASK_EXPOSURE |
158 XCB_EVENT_MASK_STRUCTURE_NOTIFY |
159 XCB_EVENT_MASK_POINTER_MOTION |
160 XCB_EVENT_MASK_BUTTON_PRESS |
161 XCB_EVENT_MASK_BUTTON_RELEASE;
162162
163163 xcb_create_window(info.connection, XCB_COPY_FROM_PARENT, info.window, screen->root, 0, 0, info.width, info.height, 0,
164 XCB_WINDOW_CLASS_INPUT_OUTPUT, screen->root_visual, value_mask, value_list);
164 XCB_WINDOW_CLASS_INPUT_OUTPUT, screen->root_visual, value_mask, value_list);
165165
166166 // Magic code that will send notification when window is destroyed
167167 xcb_intern_atom_cookie_t cookie = xcb_intern_atom(info.connection, 1, 12, "WM_PROTOCOLS");
168 xcb_intern_atom_reply_t* reply = xcb_intern_atom_reply(info.connection, cookie, 0);
168 xcb_intern_atom_reply_t* reply = xcb_intern_atom_reply(info.connection, cookie, 0);
169169
170170 xcb_intern_atom_cookie_t cookie2 = xcb_intern_atom(info.connection, 0, 16, "WM_DELETE_WINDOW");
171 info.atom_wm_delete_window = xcb_intern_atom_reply(info.connection, cookie2, 0);
171 info.atom_wm_delete_window = xcb_intern_atom_reply(info.connection, cookie2, 0);
172172
173173 xcb_change_property(info.connection, XCB_PROP_MODE_REPLACE, info.window, (*reply).atom, 4, 32, 1,
174174 &(*info.atom_wm_delete_window).atom);
175175 free(reply);
176176
177177 xcb_change_property(info.connection, XCB_PROP_MODE_REPLACE, info.window, XCB_ATOM_WM_NAME, XCB_ATOM_STRING,
178 8, Title.length(), Title.c_str() );
178 8, Title.length(), Title.c_str());
179179
180180 // https://stackoverflow.com/a/27771295
181181 xcb_size_hints_t hints = {};
182 hints.flags = XCB_SIZE_HINT_P_MIN_SIZE;
183 hints.min_width = MinWindowWidth;
184 hints.min_height = MinWindowHeight;
182 hints.flags = XCB_SIZE_HINT_P_MIN_SIZE;
183 hints.min_width = MinWindowWidth;
184 hints.min_height = MinWindowHeight;
185185 xcb_change_property(info.connection, XCB_PROP_MODE_REPLACE, info.window, XCB_ATOM_WM_NORMAL_HINTS, XCB_ATOM_WM_SIZE_HINTS,
186186 32, sizeof(xcb_size_hints_t), &hints);
187187
193193 xcb_configure_window(info.connection, info.window, XCB_CONFIG_WINDOW_X | XCB_CONFIG_WINDOW_Y, coords);
194194 xcb_flush(info.connection);
195195
196 xcb_generic_event_t *e;
196 xcb_generic_event_t* e;
197197 while ((e = xcb_wait_for_event(info.connection)))
198198 {
199199 if ((e->response_type & ~0x80) == XCB_EXPOSE) break;
201201 return info;
202202 }
203203
204 void DestroyXCBConnectionAndWindow(XCBInfo &info)
204 void DestroyXCBConnectionAndWindow(XCBInfo& info)
205205 {
206206 xcb_destroy_window(info.connection, info.window);
207207 xcb_disconnect(info.connection);
211211 {
212212 std::unique_ptr<NativeAppBase> TheApp(CreateApplication());
213213
214 std::string Title = TheApp->GetAppTitle();
215 auto xcbInfo = InitXCBConnectionAndWindow(Title);
216 if(!TheApp->InitVulkan(xcbInfo.connection, xcbInfo.window))
214 std::string Title = TheApp->GetAppTitle();
215 auto xcbInfo = InitXCBConnectionAndWindow(Title);
216 if (!TheApp->InitVulkan(xcbInfo.connection, xcbInfo.window))
217217 return -1;
218218
219219 xcb_flush(xcbInfo.connection);
220220
221221 Timer timer;
222 auto PrevTime = timer.GetElapsedTime();
223 Title = TheApp->GetAppTitle();
222 auto PrevTime = timer.GetElapsedTime();
223 Title = TheApp->GetAppTitle();
224224 WindowTitleHelper TitleHelper(Title);
225225
226226 while (true)
227227 {
228228 xcb_generic_event_t* event = nullptr;
229
229230 bool Quit = false;
230231 while ((event = xcb_poll_for_event(xcbInfo.connection)) != nullptr)
231232 {
238239 {
239240 Quit = true;
240241 }
241 break;
242 break;
242243
243244 case XCB_KEY_RELEASE:
244245 {
245246 const auto* keyEvent = reinterpret_cast<const xcb_key_release_event_t*>(event);
246247 switch (keyEvent->detail)
247248 {
248 #define KEY_ESCAPE 0x9
249 # define KEY_ESCAPE 0x9
249250 case KEY_ESCAPE:
250251 Quit = true;
251252 break;
255256
256257 case XCB_DESTROY_NOTIFY:
257258 Quit = true;
258 break;
259 break;
259260
260261 case XCB_CONFIGURE_NOTIFY:
261262 {
271272 }
272273 }
273274 break;
274
275
275276 default:
276277 break;
277278 }
282283 break;
283284
284285 // Render the scene
285 auto CurrTime = timer.GetElapsedTime();
286 auto CurrTime = timer.GetElapsedTime();
286287 auto ElapsedTime = CurrTime - PrevTime;
287 PrevTime = CurrTime;
288 PrevTime = CurrTime;
288289
289290 TheApp->Update(CurrTime, ElapsedTime);
290291
291292 TheApp->Render();
292
293
293294 TheApp->Present();
294295
295296 auto TitleWithFPS = TitleHelper.GetTitleWithFPS(ElapsedTime);
296297 xcb_change_property(xcbInfo.connection, XCB_PROP_MODE_REPLACE, xcbInfo.window, XCB_ATOM_WM_NAME, XCB_ATOM_STRING,
297 8, TitleWithFPS.length(), TitleWithFPS.c_str() );
298 8, TitleWithFPS.length(), TitleWithFPS.c_str());
298299 xcb_flush(xcbInfo.connection);
299300 }
300301
310311 int x_main()
311312 {
312313 std::unique_ptr<NativeAppBase> TheApp(CreateApplication());
313 Display *display = XOpenDisplay(0);
314
314 Display* display = XOpenDisplay(0);
315
316 // clang-format off
315317 static int visual_attribs[] =
316318 {
317319 GLX_RENDER_TYPE, GLX_RGBA_BIT,
333335 GLX_SAMPLES, 1,
334336 None
335337 };
336
337 int fbcount = 0;
338 GLXFBConfig *fbc = glXChooseFBConfig(display, DefaultScreen(display), visual_attribs, &fbcount);
338 // clang-format on
339
340 int fbcount = 0;
341 GLXFBConfig* fbc = glXChooseFBConfig(display, DefaultScreen(display), visual_attribs, &fbcount);
339342 if (!fbc)
340343 {
341344 LOG_ERROR_MESSAGE("Failed to retrieve a framebuffer config");
342345 return -1;
343346 }
344
345 XVisualInfo *vi = glXGetVisualFromFBConfig(display, fbc[0]);
346
347
348 XVisualInfo* vi = glXGetVisualFromFBConfig(display, fbc[0]);
349
347350 XSetWindowAttributes swa;
348 swa.colormap = XCreateColormap(display, RootWindow(display, vi->screen), vi->visual, AllocNone);
351 swa.colormap = XCreateColormap(display, RootWindow(display, vi->screen), vi->visual, AllocNone);
349352 swa.border_pixel = 0;
350 swa.event_mask =
351 StructureNotifyMask |
352 ExposureMask |
353 KeyPressMask |
353 swa.event_mask =
354 StructureNotifyMask |
355 ExposureMask |
356 KeyPressMask |
354357 KeyReleaseMask |
355 ButtonPressMask |
356 ButtonReleaseMask |
358 ButtonPressMask |
359 ButtonReleaseMask |
357360 PointerMotionMask;
358
359 Window win = XCreateWindow(display, RootWindow(display, vi->screen), 0, 0, WindowWidth, WindowHeight, 0, vi->depth, InputOutput, vi->visual, CWBorderPixel|CWColormap|CWEventMask, &swa);
361
362 Window win = XCreateWindow(display, RootWindow(display, vi->screen), 0, 0, WindowWidth, WindowHeight, 0, vi->depth, InputOutput, vi->visual, CWBorderPixel | CWColormap | CWEventMask, &swa);
360363 if (!win)
361364 {
362365 LOG_ERROR_MESSAGE("Failed to create window.");
363366 return -1;
364367 }
365
366 {
367 auto SizeHints = XAllocSizeHints();
368 SizeHints->flags = PMinSize;
369 SizeHints->min_width = MinWindowWidth;
368
369 {
370 auto SizeHints = XAllocSizeHints();
371 SizeHints->flags = PMinSize;
372 SizeHints->min_width = MinWindowWidth;
370373 SizeHints->min_height = MinWindowHeight;
371374 XSetWMNormalHints(display, win, SizeHints);
372375 XFree(SizeHints);
373376 }
374377
375378 XMapWindow(display, win);
376
379
377380 glXCreateContextAttribsARBProc glXCreateContextAttribsARB = nullptr;
378381 {
379382 // Create an oldstyle context first, to get the correct function pointer for glXCreateContextAttribsARB
380 GLXContext ctx_old = glXCreateContext(display, vi, 0, GL_TRUE);
381 glXCreateContextAttribsARB = (glXCreateContextAttribsARBProc)glXGetProcAddress((const GLubyte*)"glXCreateContextAttribsARB");
383 GLXContext ctx_old = glXCreateContext(display, vi, 0, GL_TRUE);
384 glXCreateContextAttribsARB = (glXCreateContextAttribsARBProc)glXGetProcAddress((const GLubyte*)"glXCreateContextAttribsARB");
382385 glXMakeCurrent(display, None, NULL);
383386 glXDestroyContext(display, ctx_old);
384387 }
385
388
386389 if (glXCreateContextAttribsARB == nullptr)
387390 {
388391 LOG_ERROR("glXCreateContextAttribsARB entry point not found. Aborting.");
389392 return -1;
390393 }
391
394
392395 int Flags = GLX_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB;
393396 #ifdef _DEBUG
394 Flags |= GLX_CONTEXT_DEBUG_BIT_ARB;
395 #endif
396
397 Flags |= GLX_CONTEXT_DEBUG_BIT_ARB;
398 #endif
399
397400 int major_version = 4;
398401 int minor_version = 3;
402
399403 static int context_attribs[] =
400 {
401 GLX_CONTEXT_MAJOR_VERSION_ARB, major_version,
402 GLX_CONTEXT_MINOR_VERSION_ARB, minor_version,
403 GLX_CONTEXT_FLAGS_ARB, Flags,
404 None
405 };
406
404 {
405 GLX_CONTEXT_MAJOR_VERSION_ARB, major_version,
406 GLX_CONTEXT_MINOR_VERSION_ARB, minor_version,
407 GLX_CONTEXT_FLAGS_ARB, Flags,
408 None //
409 };
410
407411 constexpr int True = 1;
408 GLXContext ctx = glXCreateContextAttribsARB(display, fbc[0], NULL, True, context_attribs);
412 GLXContext ctx = glXCreateContextAttribsARB(display, fbc[0], NULL, True, context_attribs);
409413 if (!ctx)
410414 {
411415 LOG_ERROR("Failed to create GL context.");
412416 return -1;
413417 }
414418 XFree(fbc);
415
419
416420
417421 glXMakeCurrent(display, win, ctx);
418422 TheApp->OnGLContextCreated(display, win);
419423 std::string Title = TheApp->GetAppTitle();
420
421 Timer timer;
422 auto PrevTime = timer.GetElapsedTime();
424
425 Timer timer;
426 auto PrevTime = timer.GetElapsedTime();
423427 WindowTitleHelper TitleHelper(Title);
424
425 while (true)
426 {
427 bool EscPressed = false;
428
429 while (true)
430 {
431 bool EscPressed = false;
428432 XEvent xev;
429433 // Handle all events in the queue
430 while(XCheckMaskEvent(display, 0xFFFFFFFF, &xev))
434 while (XCheckMaskEvent(display, 0xFFFFFFFF, &xev))
431435 {
432436 TheApp->HandleXEvent(&xev);
433 switch(xev.type)
437 switch (xev.type)
434438 {
435439 case KeyPress:
436440 {
437441 KeySym keysym;
438 char buffer[80];
439 int num_char = XLookupString((XKeyEvent *)&xev, buffer, _countof(buffer), &keysym, 0);
440 EscPressed = (keysym==XK_Escape);
442 char buffer[80];
443 int num_char = XLookupString((XKeyEvent*)&xev, buffer, _countof(buffer), &keysym, 0);
444 EscPressed = (keysym == XK_Escape);
441445 }
442
446
443447 case ConfigureNotify:
444448 {
445 XConfigureEvent &xce = reinterpret_cast<XConfigureEvent &>(xev);
446 if(xce.width != 0 && xce.height != 0)
449 XConfigureEvent& xce = reinterpret_cast<XConfigureEvent&>(xev);
450 if (xce.width != 0 && xce.height != 0)
447451 TheApp->WindowResize(xce.width, xce.height);
448452 break;
449453 }
450454 }
451455 }
452456
453 if(EscPressed)
457 if (EscPressed)
454458 break;
455459
456460 // Render the scene
457 auto CurrTime = timer.GetElapsedTime();
461 auto CurrTime = timer.GetElapsedTime();
458462 auto ElapsedTime = CurrTime - PrevTime;
459 PrevTime = CurrTime;
463 PrevTime = CurrTime;
460464
461465 TheApp->Update(CurrTime, ElapsedTime);
462466
463467 TheApp->Render();
464
468
465469 TheApp->Present();
466470
467471 auto TitleWithFPS = TitleHelper.GetTitleWithFPS(ElapsedTime);
469473 }
470474
471475 TheApp.reset();
472
476
473477 ctx = glXGetCurrentContext();
474478 glXMakeCurrent(display, None, NULL);
475479 glXDestroyContext(display, ctx);
477481 XCloseDisplay(display);
478482 }
479483
480 int main (int argc, char ** argv)
484 int main(int argc, char** argv)
481485 {
482486 bool UseVulkan = false;
483487
490494 if (pos != nullptr)
491495 {
492496 pos += strlen(Key);
493 while(*pos != 0 && *pos == ' ')++pos;
497 while (*pos != 0 && *pos == ' ') ++pos;
494498 if (strcasecmp(pos, "GL") == 0)
495499 {
496500 UseVulkan = false;
2828 void MacOSAppBase::Update()
2929 {
3030 // Render the scene
31 auto CurrTime = timer.GetElapsedTime();
31 auto CurrTime = timer.GetElapsedTime();
3232 auto ElapsedTime = CurrTime - PrevTime;
33 PrevTime = CurrTime;
33 PrevTime = CurrTime;
3434 Update(CurrTime, ElapsedTime);
3535 }
3636
37 }
37 } // namespace Diligent
3737 int WINAPI WinMain(HINSTANCE instance, HINSTANCE, LPSTR, int cmdShow)
3838 {
3939 #if defined(_DEBUG) || defined(DEBUG)
40 _CrtSetDbgFlag( _CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF );
40 _CrtSetDbgFlag(_CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF);
4141 #endif
4242
43 g_pTheApp.reset( CreateApplication() );
43 g_pTheApp.reset(CreateApplication());
4444
4545 const auto* cmdLine = GetCommandLineA();
4646 g_pTheApp->ProcessCommandLine(cmdLine);
4848 const auto* AppTitle = g_pTheApp->GetAppTitle();
4949
5050 #ifdef UNICODE
51 const auto* const WindowClassName = L"SampleApp";
51 const auto* const WindowClassName = L"SampleApp";
5252 #else
53 const auto* const WindowClassName = "SampleApp";
53 const auto* const WindowClassName = "SampleApp";
5454 #endif
5555
5656 // Register our window class
57 WNDCLASSEX wcex = { sizeof(WNDCLASSEX), CS_HREDRAW|CS_VREDRAW, MessageProc,
58 0L, 0L, instance, NULL, NULL, NULL, NULL, WindowClassName, NULL };
57 WNDCLASSEX wcex = {sizeof(WNDCLASSEX), CS_HREDRAW | CS_VREDRAW, MessageProc,
58 0L, 0L, instance, NULL, NULL, NULL, NULL, WindowClassName, NULL};
5959 RegisterClassEx(&wcex);
6060
61 int DesiredWidth = 0;
61 int DesiredWidth = 0;
6262 int DesiredHeight = 0;
6363 g_pTheApp->GetDesiredInitialWindowSize(DesiredWidth, DesiredHeight);
6464 // Create a window
65 LONG WindowWidth = DesiredWidth > 0 ? DesiredWidth : 1280;
65 LONG WindowWidth = DesiredWidth > 0 ? DesiredWidth : 1280;
6666 LONG WindowHeight = DesiredHeight > 0 ? DesiredHeight : 1024;
67 RECT rc = { 0, 0, WindowWidth, WindowHeight };
67 RECT rc = {0, 0, WindowWidth, WindowHeight};
6868 AdjustWindowRect(&rc, WS_OVERLAPPEDWINDOW, FALSE);
6969 HWND wnd = CreateWindowA("SampleApp", AppTitle,
70 WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT,
71 rc.right-rc.left, rc.bottom-rc.top, NULL, NULL, instance, NULL);
70 WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT,
71 rc.right - rc.left, rc.bottom - rc.top, NULL, NULL, instance, NULL);
7272 if (!wnd)
7373 {
74 MessageBoxA(NULL, "Cannot create window", "Error", MB_OK|MB_ICONERROR);
74 MessageBoxA(NULL, "Cannot create window", "Error", MB_OK | MB_ICONERROR);
7575 return 0;
7676 }
7777 ShowWindow(wnd, cmdShow);
7878 UpdateWindow(wnd);
79
79
8080 g_pTheApp->OnWindowCreated(wnd, WindowWidth, WindowHeight);
8181 AppTitle = g_pTheApp->GetAppTitle();
8282
8383 Diligent::Timer Timer;
84 auto PrevTime = Timer.GetElapsedTime();
84
85 auto PrevTime = Timer.GetElapsedTime();
8586 double filteredFrameTime = 0.0;
8687
8788 // Main message loop
9596 }
9697 else
9798 {
98 auto CurrTime = Timer.GetElapsedTime();
99 auto CurrTime = Timer.GetElapsedTime();
99100 auto ElapsedTime = CurrTime - PrevTime;
100 PrevTime = CurrTime;
101 PrevTime = CurrTime;
102
101103 g_pTheApp->Update(CurrTime, ElapsedTime);
102104
103105 g_pTheApp->Render();
105107 g_pTheApp->Present();
106108
107109 double filterScale = 0.2;
108 filteredFrameTime = filteredFrameTime * (1.0 - filterScale) + filterScale * ElapsedTime;
110 filteredFrameTime = filteredFrameTime * (1.0 - filterScale) + filterScale * ElapsedTime;
109111 std::stringstream fpsCounterSS;
110112 fpsCounterSS << AppTitle << " - " << std::fixed << std::setprecision(1) << filteredFrameTime * 1000;
111113 fpsCounterSS << " ms (" << 1.0 / filteredFrameTime << " fps)";
112114 SetWindowTextA(wnd, fpsCounterSS.str().c_str());
113115 }
114116 }
115
117
116118 g_pTheApp.reset();
117119
118120 return (int)msg.wParam;
121123 // Called every time the NativeNativeAppBase receives a message
122124 LRESULT CALLBACK MessageProc(HWND wnd, UINT message, WPARAM wParam, LPARAM lParam)
123125 {
124 if(g_pTheApp)
126 if (g_pTheApp)
125127 {
126128 auto res = g_pTheApp->HandleWin32Message(wnd, message, wParam, lParam);
127129 if (res != 0)
128130 return res;
129131 }
130132
131 switch (message)
133 switch (message)
132134 {
133135 case WM_PAINT:
134 {
135 PAINTSTRUCT ps;
136 BeginPaint(wnd, &ps);
137 EndPaint(wnd, &ps);
138 return 0;
139 }
136 {
137 PAINTSTRUCT ps;
138 BeginPaint(wnd, &ps);
139 EndPaint(wnd, &ps);
140 return 0;
141 }
140142 case WM_SIZE: // Window size has been changed
141 if( g_pTheApp )
143 if (g_pTheApp)
142144 {
143145 g_pTheApp->WindowResize(LOWORD(lParam), HIWORD(lParam));
144146 }
155157
156158 case WM_GETMINMAXINFO:
157159 {
158 LPMINMAXINFO lpMMI = (LPMINMAXINFO)lParam;
160 LPMINMAXINFO lpMMI = (LPMINMAXINFO)lParam;
159161 lpMMI->ptMinTrackSize.x = 320;
160162 lpMMI->ptMinTrackSize.y = 240;
161163 return 0;