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 EGLenum eglClientType = EGL_OPENGL_ES_API;
74 EGLint glMajorVersion = 2;
75 EGLint glMinorVersion = 0;
76 EGLint profileMask = 0;
77
78 switch (clientType)
79 {
80 case ClientType::ES1:
81 glMajorVersion = 1;
82 break;
83 case ClientType::ES2:
84 break;
85 case ClientType::ES3_0:
86 glMajorVersion = 3;
87 break;
88 case ClientType::ES3_1:
89 glMajorVersion = 3;
90 glMinorVersion = 1;
91 break;
92 case ClientType::GL3_3_CORE:
93 eglClientType = EGL_OPENGL_API;
94 glMajorVersion = 3;
95 glMinorVersion = 3;
96 profileMask = EGL_CONTEXT_OPENGL_CORE_PROFILE_BIT;
97 break;
98 case ClientType::GL3_3_COMPATIBILITY:
99 eglClientType = EGL_OPENGL_API;
100 glMajorVersion = 3;
101 glMinorVersion = 3;
102 profileMask = EGL_CONTEXT_OPENGL_COMPATIBILITY_PROFILE_BIT;
103 break;
104 case ClientType::GL4_6_CORE:
105 eglClientType = EGL_OPENGL_API;
106 glMajorVersion = 4;
107 glMinorVersion = 6;
108 profileMask = EGL_CONTEXT_OPENGL_CORE_PROFILE_BIT;
109 break;
110 case ClientType::GL4_6_COMPATIBILITY:
111 eglClientType = EGL_OPENGL_API;
112 glMajorVersion = 4;
113 glMinorVersion = 6;
114 profileMask = EGL_CONTEXT_OPENGL_COMPATIBILITY_PROFILE_BIT;
115 break;
116 default:
117 UNREACHABLE();
118 }
119
120 mOSWindow = OSWindow::New();
121
122 // Load EGL library so we can initialize the display.
123 if (useNativeGL)
124 {
125 #if defined(ANGLE_PLATFORM_WINDOWS)
126 mGLWindow = WGLWindow::New(eglClientType, glMajorVersion, glMinorVersion, profileMask);
127 mEntryPointsLib.reset(angle::OpenSharedLibrary("opengl32", angle::SearchType::SystemDir));
128 mDriverType = angle::GLESDriverType::SystemWGL;
129 #else
130 mGLWindow = EGLWindow::New(eglClientType, glMajorVersion, glMinorVersion, profileMask);
131 mEntryPointsLib.reset(angle::OpenSharedLibraryWithExtension(
132 angle::GetNativeEGLLibraryNameWithExtension(), angle::SearchType::SystemDir));
133 mDriverType = angle::GLESDriverType::SystemEGL;
134 #endif // defined(ANGLE_PLATFORM_WINDOWS)
135 }
136 else
137 {
138 #if defined(ANGLE_EXPOSE_WGL_ENTRY_POINTS)
139 mGLWindow = WGLWindow::New(eglClientType, glMajorVersion, glMinorVersion, profileMask);
140 mEntryPointsLib.reset(angle::OpenSharedLibrary("opengl32", angle::SearchType::ModuleDir));
141 mDriverType = angle::GLESDriverType::SystemWGL;
142 #else
143 mGLWindow = mEGLWindow =
144 EGLWindow::New(eglClientType, glMajorVersion, glMinorVersion, profileMask);
145 mEntryPointsLib.reset(
146 angle::OpenSharedLibrary(ANGLE_EGL_LIBRARY_NAME, angle::SearchType::ModuleDir));
147 #endif // defined(ANGLE_EXPOSE_WGL_ENTRY_POINTS)
148 }
149 }
150
~SampleApplication()151 SampleApplication::~SampleApplication()
152 {
153 GLWindowBase::Delete(&mGLWindow);
154 OSWindow::Delete(&mOSWindow);
155 }
156
initialize()157 bool SampleApplication::initialize()
158 {
159 return true;
160 }
161
destroy()162 void SampleApplication::destroy() {}
163
step(float dt,double totalTime)164 void SampleApplication::step(float dt, double totalTime) {}
165
draw()166 void SampleApplication::draw() {}
167
swap()168 void SampleApplication::swap()
169 {
170 mGLWindow->swap();
171 }
172
getWindow() const173 OSWindow *SampleApplication::getWindow() const
174 {
175 return mOSWindow;
176 }
177
getConfig() const178 EGLConfig SampleApplication::getConfig() const
179 {
180 ASSERT(mEGLWindow);
181 return mEGLWindow->getConfig();
182 }
183
getDisplay() const184 EGLDisplay SampleApplication::getDisplay() const
185 {
186 ASSERT(mEGLWindow);
187 return mEGLWindow->getDisplay();
188 }
189
getSurface() const190 EGLSurface SampleApplication::getSurface() const
191 {
192 ASSERT(mEGLWindow);
193 return mEGLWindow->getSurface();
194 }
195
getContext() const196 EGLContext SampleApplication::getContext() const
197 {
198 ASSERT(mEGLWindow);
199 return mEGLWindow->getContext();
200 }
201
run()202 int SampleApplication::run()
203 {
204 if (!mOSWindow->initialize(mName, mWidth, mHeight))
205 {
206 return -1;
207 }
208
209 mOSWindow->setVisible(true);
210
211 ConfigParameters configParams;
212 configParams.redBits = 8;
213 configParams.greenBits = 8;
214 configParams.blueBits = 8;
215 configParams.alphaBits = 8;
216 configParams.depthBits = 24;
217 configParams.stencilBits = 8;
218
219 if (!mGLWindow->initializeGL(mOSWindow, mEntryPointsLib.get(), mDriverType, mPlatformParams,
220 configParams))
221 {
222 return -1;
223 }
224
225 // Disable vsync
226 if (!mGLWindow->setSwapInterval(0))
227 {
228 return -1;
229 }
230
231 mRunning = true;
232 int result = 0;
233
234 #if defined(ANGLE_ENABLE_ASSERTS)
235 if (IsGLExtensionEnabled("GL_KHR_debug"))
236 {
237 EnableDebugCallback(nullptr, nullptr);
238 }
239 #endif
240
241 if (!initialize())
242 {
243 mRunning = false;
244 result = -1;
245 }
246
247 mTimer.start();
248 double prevTime = 0.0;
249
250 while (mRunning)
251 {
252 double elapsedTime = mTimer.getElapsedWallClockTime();
253 double deltaTime = elapsedTime - prevTime;
254
255 step(static_cast<float>(deltaTime), elapsedTime);
256
257 // Clear events that the application did not process from this frame
258 Event event;
259 while (popEvent(&event))
260 {
261 // If the application did not catch a close event, close now
262 switch (event.Type)
263 {
264 case Event::EVENT_CLOSED:
265 exit();
266 break;
267 case Event::EVENT_KEY_RELEASED:
268 onKeyUp(event.Key);
269 break;
270 case Event::EVENT_KEY_PRESSED:
271 onKeyDown(event.Key);
272 break;
273 default:
274 break;
275 }
276 }
277
278 if (!mRunning)
279 {
280 break;
281 }
282
283 draw();
284 swap();
285
286 mOSWindow->messageLoop();
287
288 prevTime = elapsedTime;
289
290 mFrameCount++;
291
292 if (mFrameCount % 100 == 0)
293 {
294 printf("Rate: %0.2lf frames / second\n",
295 static_cast<double>(mFrameCount) / mTimer.getElapsedWallClockTime());
296 }
297 }
298
299 destroy();
300 mGLWindow->destroyGL();
301 mOSWindow->destroy();
302
303 return result;
304 }
305
exit()306 void SampleApplication::exit()
307 {
308 mRunning = false;
309 }
310
popEvent(Event * event)311 bool SampleApplication::popEvent(Event *event)
312 {
313 return mOSWindow->popEvent(event);
314 }
315
onKeyUp(const Event::KeyEvent & keyEvent)316 void SampleApplication::onKeyUp(const Event::KeyEvent &keyEvent)
317 {
318 // Default no-op.
319 }
320
onKeyDown(const Event::KeyEvent & keyEvent)321 void SampleApplication::onKeyDown(const Event::KeyEvent &keyEvent)
322 {
323 // Default no-op.
324 }
325