1 //
2 // Copyright 2013 The ANGLE Project Authors. All rights reserved.
3 // Use of this source code is governed by a BSD-style license that can be
4 // found in the LICENSE file.
5 //
6
7 #include "SampleApplication.h"
8
9 #include "common/debug.h"
10 #include "util/EGLWindow.h"
11 #include "util/gles_loader_autogen.h"
12 #include "util/random_utils.h"
13 #include "util/shader_utils.h"
14 #include "util/test_utils.h"
15 #include "util/util_gl.h"
16
17 #include <string.h>
18 #include <iostream>
19 #include <utility>
20
21 #if defined(ANGLE_PLATFORM_WINDOWS)
22 # include "util/windows/WGLWindow.h"
23 #endif // defined(ANGLE_PLATFORM_WINDOWS)
24
25 namespace
26 {
27 const char *kUseAngleArg = "--use-angle=";
28 const char *kUseGlArg = "--use-gl=native";
29 } // anonymous namespace
30
IsGLExtensionEnabled(const std::string & extName)31 bool IsGLExtensionEnabled(const std::string &extName)
32 {
33 return angle::CheckExtensionExists(reinterpret_cast<const char *>(glGetString(GL_EXTENSIONS)),
34 extName);
35 }
36
SampleApplication(std::string name,int argc,char ** argv,ClientType clientType,uint32_t width,uint32_t height)37 SampleApplication::SampleApplication(std::string name,
38 int argc,
39 char **argv,
40 ClientType clientType,
41 uint32_t width,
42 uint32_t height)
43 : mName(std::move(name)),
44 mWidth(width),
45 mHeight(height),
46 mRunning(false),
47 mFrameCount(0),
48 mGLWindow(nullptr),
49 mEGLWindow(nullptr),
50 mOSWindow(nullptr),
51 mDriverType(angle::GLESDriverType::AngleEGL)
52 {
53 mPlatformParams.renderer = EGL_PLATFORM_ANGLE_TYPE_DEFAULT_ANGLE;
54 bool useNativeGL = false;
55
56 for (int argIndex = 1; argIndex < argc; argIndex++)
57 {
58 if (strncmp(argv[argIndex], kUseAngleArg, strlen(kUseAngleArg)) == 0)
59 {
60 const char *arg = argv[argIndex] + strlen(kUseAngleArg);
61 mPlatformParams.renderer =
62 angle::GetPlatformANGLETypeFromArg(arg, EGL_PLATFORM_ANGLE_TYPE_DEFAULT_ANGLE);
63 mPlatformParams.deviceType = angle::GetANGLEDeviceTypeFromArg(
64 arg, EGL_PLATFORM_ANGLE_DEVICE_TYPE_HARDWARE_ANGLE);
65 }
66
67 if (strncmp(argv[argIndex], kUseGlArg, strlen(kUseGlArg)) == 0)
68 {
69 useNativeGL = true;
70 }
71 }
72
73 EGLint glMajorVersion = 2;
74 EGLint glMinorVersion = 0;
75
76 switch (clientType)
77 {
78 case ClientType::ES1:
79 glMajorVersion = 1;
80 break;
81 case ClientType::ES2:
82 break;
83 case ClientType::ES3_0:
84 glMajorVersion = 3;
85 break;
86 case ClientType::ES3_1:
87 glMajorVersion = 3;
88 glMinorVersion = 1;
89 break;
90 default:
91 UNREACHABLE();
92 }
93
94 mOSWindow = OSWindow::New();
95
96 // Load EGL library so we can initialize the display.
97 if (useNativeGL)
98 {
99 #if defined(ANGLE_PLATFORM_WINDOWS)
100 mGLWindow = WGLWindow::New(glMajorVersion, glMinorVersion);
101 mEntryPointsLib.reset(angle::OpenSharedLibrary("opengl32", angle::SearchType::SystemDir));
102 mDriverType = angle::GLESDriverType::SystemWGL;
103 #else
104 mGLWindow = EGLWindow::New(glMajorVersion, glMinorVersion);
105 mEntryPointsLib.reset(angle::OpenSharedLibraryWithExtension(
106 angle::GetNativeEGLLibraryNameWithExtension(), angle::SearchType::SystemDir));
107 mDriverType = angle::GLESDriverType::SystemEGL;
108 #endif // defined(ANGLE_PLATFORM_WINDOWS)
109 }
110 else
111 {
112 mGLWindow = mEGLWindow = EGLWindow::New(glMajorVersion, glMinorVersion);
113 mEntryPointsLib.reset(
114 angle::OpenSharedLibrary(ANGLE_EGL_LIBRARY_NAME, angle::SearchType::ModuleDir));
115 }
116 }
117
~SampleApplication()118 SampleApplication::~SampleApplication()
119 {
120 GLWindowBase::Delete(&mGLWindow);
121 OSWindow::Delete(&mOSWindow);
122 }
123
initialize()124 bool SampleApplication::initialize()
125 {
126 return true;
127 }
128
destroy()129 void SampleApplication::destroy() {}
130
step(float dt,double totalTime)131 void SampleApplication::step(float dt, double totalTime) {}
132
draw()133 void SampleApplication::draw() {}
134
swap()135 void SampleApplication::swap()
136 {
137 mGLWindow->swap();
138 }
139
getWindow() const140 OSWindow *SampleApplication::getWindow() const
141 {
142 return mOSWindow;
143 }
144
getConfig() const145 EGLConfig SampleApplication::getConfig() const
146 {
147 ASSERT(mEGLWindow);
148 return mEGLWindow->getConfig();
149 }
150
getDisplay() const151 EGLDisplay SampleApplication::getDisplay() const
152 {
153 ASSERT(mEGLWindow);
154 return mEGLWindow->getDisplay();
155 }
156
getSurface() const157 EGLSurface SampleApplication::getSurface() const
158 {
159 ASSERT(mEGLWindow);
160 return mEGLWindow->getSurface();
161 }
162
getContext() const163 EGLContext SampleApplication::getContext() const
164 {
165 ASSERT(mEGLWindow);
166 return mEGLWindow->getContext();
167 }
168
run()169 int SampleApplication::run()
170 {
171 if (!mOSWindow->initialize(mName, mWidth, mHeight))
172 {
173 return -1;
174 }
175
176 mOSWindow->setVisible(true);
177
178 ConfigParameters configParams;
179 configParams.redBits = 8;
180 configParams.greenBits = 8;
181 configParams.blueBits = 8;
182 configParams.alphaBits = 8;
183 configParams.depthBits = 24;
184 configParams.stencilBits = 8;
185
186 if (!mGLWindow->initializeGL(mOSWindow, mEntryPointsLib.get(), mDriverType, mPlatformParams,
187 configParams))
188 {
189 return -1;
190 }
191
192 // Disable vsync
193 if (!mGLWindow->setSwapInterval(0))
194 {
195 return -1;
196 }
197
198 mRunning = true;
199 int result = 0;
200
201 #if defined(ANGLE_ENABLE_ASSERTS)
202 if (IsGLExtensionEnabled("GL_KHR_debug"))
203 {
204 EnableDebugCallback(nullptr, nullptr);
205 }
206 #endif
207
208 if (!initialize())
209 {
210 mRunning = false;
211 result = -1;
212 }
213
214 mTimer.start();
215 double prevTime = 0.0;
216
217 while (mRunning)
218 {
219 double elapsedTime = mTimer.getElapsedWallClockTime();
220 double deltaTime = elapsedTime - prevTime;
221
222 step(static_cast<float>(deltaTime), elapsedTime);
223
224 // Clear events that the application did not process from this frame
225 Event event;
226 while (popEvent(&event))
227 {
228 // If the application did not catch a close event, close now
229 switch (event.Type)
230 {
231 case Event::EVENT_CLOSED:
232 exit();
233 break;
234 case Event::EVENT_KEY_RELEASED:
235 onKeyUp(event.Key);
236 break;
237 case Event::EVENT_KEY_PRESSED:
238 onKeyDown(event.Key);
239 break;
240 default:
241 break;
242 }
243 }
244
245 if (!mRunning)
246 {
247 break;
248 }
249
250 draw();
251 swap();
252
253 mOSWindow->messageLoop();
254
255 prevTime = elapsedTime;
256
257 mFrameCount++;
258
259 if (mFrameCount % 100 == 0)
260 {
261 printf("Rate: %0.2lf frames / second\n",
262 static_cast<double>(mFrameCount) / mTimer.getElapsedWallClockTime());
263 }
264 }
265
266 destroy();
267 mGLWindow->destroyGL();
268 mOSWindow->destroy();
269
270 return result;
271 }
272
exit()273 void SampleApplication::exit()
274 {
275 mRunning = false;
276 }
277
popEvent(Event * event)278 bool SampleApplication::popEvent(Event *event)
279 {
280 return mOSWindow->popEvent(event);
281 }
282
onKeyUp(const Event::KeyEvent & keyEvent)283 void SampleApplication::onKeyUp(const Event::KeyEvent &keyEvent)
284 {
285 // Default no-op.
286 }
287
onKeyDown(const Event::KeyEvent & keyEvent)288 void SampleApplication::onKeyDown(const Event::KeyEvent &keyEvent)
289 {
290 // Default no-op.
291 }
292