• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
30 using DisplayTypeInfo = std::pair<const char *, EGLint>;
31 
32 const DisplayTypeInfo kDisplayTypes[] = {
33     {"d3d9", EGL_PLATFORM_ANGLE_TYPE_D3D9_ANGLE},
34     {"d3d11", EGL_PLATFORM_ANGLE_TYPE_D3D11_ANGLE},
35     {"gl", EGL_PLATFORM_ANGLE_TYPE_OPENGL_ANGLE},
36     {"gles", EGL_PLATFORM_ANGLE_TYPE_OPENGLES_ANGLE},
37     {"metal", EGL_PLATFORM_ANGLE_TYPE_METAL_ANGLE},
38     {"null", EGL_PLATFORM_ANGLE_TYPE_NULL_ANGLE},
39     {"swiftshader", EGL_PLATFORM_ANGLE_TYPE_VULKAN_ANGLE},
40     {"vulkan", EGL_PLATFORM_ANGLE_TYPE_VULKAN_ANGLE},
41 };
42 
GetDisplayTypeFromArg(const char * displayTypeArg)43 EGLint GetDisplayTypeFromArg(const char *displayTypeArg)
44 {
45     for (const auto &displayTypeInfo : kDisplayTypes)
46     {
47         if (strcmp(displayTypeInfo.first, displayTypeArg) == 0)
48         {
49             std::cout << "Using ANGLE back-end API: " << displayTypeInfo.first << std::endl;
50             return displayTypeInfo.second;
51         }
52     }
53 
54     std::cout << "Unknown ANGLE back-end API: " << displayTypeArg << std::endl;
55     return EGL_PLATFORM_ANGLE_TYPE_DEFAULT_ANGLE;
56 }
57 
GetDeviceTypeFromArg(const char * displayTypeArg)58 EGLint GetDeviceTypeFromArg(const char *displayTypeArg)
59 {
60     if (strcmp(displayTypeArg, "swiftshader") == 0)
61     {
62         return EGL_PLATFORM_ANGLE_DEVICE_TYPE_SWIFTSHADER_ANGLE;
63     }
64     else
65     {
66         return EGL_PLATFORM_ANGLE_DEVICE_TYPE_HARDWARE_ANGLE;
67     }
68 }
69 }  // anonymous namespace
70 
IsGLExtensionEnabled(const std::string & extName)71 bool IsGLExtensionEnabled(const std::string &extName)
72 {
73     return angle::CheckExtensionExists(reinterpret_cast<const char *>(glGetString(GL_EXTENSIONS)),
74                                        extName);
75 }
76 
SampleApplication(std::string name,int argc,char ** argv,EGLint glesMajorVersion,EGLint glesMinorVersion,uint32_t width,uint32_t height)77 SampleApplication::SampleApplication(std::string name,
78                                      int argc,
79                                      char **argv,
80                                      EGLint glesMajorVersion,
81                                      EGLint glesMinorVersion,
82                                      uint32_t width,
83                                      uint32_t height)
84     : mName(std::move(name)),
85       mWidth(width),
86       mHeight(height),
87       mRunning(false),
88       mFrameCount(0),
89       mGLWindow(nullptr),
90       mEGLWindow(nullptr),
91       mOSWindow(nullptr),
92       mDriverType(angle::GLESDriverType::AngleEGL)
93 {
94     mPlatformParams.renderer = EGL_PLATFORM_ANGLE_TYPE_DEFAULT_ANGLE;
95     bool useNativeGL         = false;
96 
97     for (int argIndex = 1; argIndex < argc; argIndex++)
98     {
99         if (strncmp(argv[argIndex], kUseAngleArg, strlen(kUseAngleArg)) == 0)
100         {
101             const char *arg            = argv[argIndex] + strlen(kUseAngleArg);
102             mPlatformParams.renderer   = GetDisplayTypeFromArg(arg);
103             mPlatformParams.deviceType = GetDeviceTypeFromArg(arg);
104         }
105 
106         if (strncmp(argv[argIndex], kUseGlArg, strlen(kUseGlArg)) == 0)
107         {
108             useNativeGL = true;
109         }
110     }
111 
112     mOSWindow = OSWindow::New();
113 
114     // Load EGL library so we can initialize the display.
115     if (useNativeGL)
116     {
117 #if defined(ANGLE_PLATFORM_WINDOWS)
118         mGLWindow = WGLWindow::New(glesMajorVersion, glesMinorVersion);
119         mEntryPointsLib.reset(angle::OpenSharedLibrary("opengl32", angle::SearchType::SystemDir));
120         mDriverType = angle::GLESDriverType::SystemWGL;
121 #else
122         mGLWindow = EGLWindow::New(glesMajorVersion, glesMinorVersion);
123         mEntryPointsLib.reset(angle::OpenSharedLibraryWithExtension(
124             angle::GetNativeEGLLibraryNameWithExtension(), angle::SearchType::SystemDir));
125         mDriverType = angle::GLESDriverType::SystemEGL;
126 #endif  // defined(ANGLE_PLATFORM_WINDOWS)
127     }
128     else
129     {
130         mGLWindow = mEGLWindow = EGLWindow::New(glesMajorVersion, glesMinorVersion);
131         mEntryPointsLib.reset(
132             angle::OpenSharedLibrary(ANGLE_EGL_LIBRARY_NAME, angle::SearchType::ModuleDir));
133     }
134 }
135 
~SampleApplication()136 SampleApplication::~SampleApplication()
137 {
138     GLWindowBase::Delete(&mGLWindow);
139     OSWindow::Delete(&mOSWindow);
140 }
141 
initialize()142 bool SampleApplication::initialize()
143 {
144     return true;
145 }
146 
destroy()147 void SampleApplication::destroy() {}
148 
step(float dt,double totalTime)149 void SampleApplication::step(float dt, double totalTime) {}
150 
draw()151 void SampleApplication::draw() {}
152 
swap()153 void SampleApplication::swap()
154 {
155     mGLWindow->swap();
156 }
157 
getWindow() const158 OSWindow *SampleApplication::getWindow() const
159 {
160     return mOSWindow;
161 }
162 
getConfig() const163 EGLConfig SampleApplication::getConfig() const
164 {
165     ASSERT(mEGLWindow);
166     return mEGLWindow->getConfig();
167 }
168 
getDisplay() const169 EGLDisplay SampleApplication::getDisplay() const
170 {
171     ASSERT(mEGLWindow);
172     return mEGLWindow->getDisplay();
173 }
174 
getSurface() const175 EGLSurface SampleApplication::getSurface() const
176 {
177     ASSERT(mEGLWindow);
178     return mEGLWindow->getSurface();
179 }
180 
getContext() const181 EGLContext SampleApplication::getContext() const
182 {
183     ASSERT(mEGLWindow);
184     return mEGLWindow->getContext();
185 }
186 
run()187 int SampleApplication::run()
188 {
189     if (!mOSWindow->initialize(mName, mWidth, mHeight))
190     {
191         return -1;
192     }
193 
194     mOSWindow->setVisible(true);
195 
196     ConfigParameters configParams;
197     configParams.redBits     = 8;
198     configParams.greenBits   = 8;
199     configParams.blueBits    = 8;
200     configParams.alphaBits   = 8;
201     configParams.depthBits   = 24;
202     configParams.stencilBits = 8;
203 
204     if (!mGLWindow->initializeGL(mOSWindow, mEntryPointsLib.get(), mDriverType, mPlatformParams,
205                                  configParams))
206     {
207         return -1;
208     }
209 
210     // Disable vsync
211     if (!mGLWindow->setSwapInterval(0))
212     {
213         return -1;
214     }
215 
216     mRunning   = true;
217     int result = 0;
218 
219 #if defined(ANGLE_ENABLE_ASSERTS)
220     if (IsGLExtensionEnabled("GL_KHR_debug"))
221     {
222         EnableDebugCallback(nullptr, nullptr);
223     }
224 #endif
225 
226     if (!initialize())
227     {
228         mRunning = false;
229         result   = -1;
230     }
231 
232     mTimer.start();
233     double prevTime = 0.0;
234 
235     while (mRunning)
236     {
237         double elapsedTime = mTimer.getElapsedWallClockTime();
238         double deltaTime   = elapsedTime - prevTime;
239 
240         step(static_cast<float>(deltaTime), elapsedTime);
241 
242         // Clear events that the application did not process from this frame
243         Event event;
244         while (popEvent(&event))
245         {
246             // If the application did not catch a close event, close now
247             switch (event.Type)
248             {
249                 case Event::EVENT_CLOSED:
250                     exit();
251                     break;
252                 case Event::EVENT_KEY_RELEASED:
253                     onKeyUp(event.Key);
254                     break;
255                 case Event::EVENT_KEY_PRESSED:
256                     onKeyDown(event.Key);
257                     break;
258                 default:
259                     break;
260             }
261         }
262 
263         if (!mRunning)
264         {
265             break;
266         }
267 
268         draw();
269         swap();
270 
271         mOSWindow->messageLoop();
272 
273         prevTime = elapsedTime;
274 
275         mFrameCount++;
276 
277         if (mFrameCount % 100 == 0)
278         {
279             printf("Rate: %0.2lf frames / second\n",
280                    static_cast<double>(mFrameCount) / mTimer.getElapsedWallClockTime());
281         }
282     }
283 
284     destroy();
285     mGLWindow->destroyGL();
286     mOSWindow->destroy();
287 
288     return result;
289 }
290 
exit()291 void SampleApplication::exit()
292 {
293     mRunning = false;
294 }
295 
popEvent(Event * event)296 bool SampleApplication::popEvent(Event *event)
297 {
298     return mOSWindow->popEvent(event);
299 }
300 
onKeyUp(const Event::KeyEvent & keyEvent)301 void SampleApplication::onKeyUp(const Event::KeyEvent &keyEvent)
302 {
303     // Default no-op.
304 }
305 
onKeyDown(const Event::KeyEvent & keyEvent)306 void SampleApplication::onKeyDown(const Event::KeyEvent &keyEvent)
307 {
308     // Default no-op.
309 }
310