OpenGL ES SDK for Android ARM Developer Center
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
EGLRuntime.cpp
Go to the documentation of this file.
1 /* Copyright (c) 2012-2017, ARM Limited and Contributors
2  *
3  * SPDX-License-Identifier: MIT
4  *
5  * Permission is hereby granted, free of charge,
6  * to any person obtaining a copy of this software and associated documentation files (the "Software"),
7  * to deal in the Software without restriction, including without limitation the rights to
8  * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software,
9  * and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
10  *
11  * The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
12  *
13  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
14  * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
16  * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
17  * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
19  */
20 
21 #include "EGLRuntime.h"
22 #include "Platform.h"
23 
24 #include <cstdlib>
25 
26 namespace MaliSDK
27 {
29 
30  EGLDisplay EGLRuntime::display;
31  EGLContext EGLRuntime::context;
32  EGLSurface EGLRuntime::surface;
33  EGLConfig EGLRuntime::config;
34 
36  {
37  /* DO NOT MODIFY. */
38  /* These attributes are in a known order and may be re-written at initialization according to application requests. */
39  EGL_SAMPLES, 4,
40 
41  EGL_ALPHA_SIZE, 0,
42 #if defined(__arm__)
43  EGL_RED_SIZE, 8,
44  EGL_GREEN_SIZE, 8,
45  EGL_BLUE_SIZE, 8,
46  EGL_BUFFER_SIZE, 32,
47 #else
48  EGL_RED_SIZE, 8,
49  EGL_GREEN_SIZE, 8,
50  EGL_BLUE_SIZE, 8,
51  EGL_BUFFER_SIZE, 32,
52 #endif
53  EGL_STENCIL_SIZE, 0,
54  EGL_RENDERABLE_TYPE, 0, /* This field will be completed according to application request. */
55 
56  EGL_SURFACE_TYPE, EGL_WINDOW_BIT ,
57 
58  EGL_DEPTH_SIZE, 16,
59 
60  /* MODIFY BELOW HERE. */
61  /* If you need to add or override EGL attributes from above, do it below here. */
62 
63  EGL_NONE
64  };
65 
67  {
68  EGL_CONTEXT_CLIENT_VERSION, 0, /* This field will be completed according to application request. */
69  EGL_NONE
70  };
71 
76  {
77  EGL_NONE
78  /*
79  * Uncomment and remove EGL_NONE above to specify EGL_RENDER_BUFFER value to eglCreateWindowSurface.
80  * EGL_RENDER_BUFFER, EGL_BACK_BUFFER,
81  * EGL_NONE
82  */
83  };
84 
85  EGLConfig EGLRuntime::findConfig(bool strictMatch)
86  {
87  EGLConfig *configsArray = NULL;
88  EGLint numberOfConfigs = 0;
89  EGLBoolean success = EGL_FALSE;
90 
91  /* Enumerate available EGL configurations which match or exceed our required attribute list. */
92  success = eglChooseConfig(display, configAttributes, NULL, 0, &numberOfConfigs);
93  if(success != EGL_TRUE)
94  {
95  EGLint error = eglGetError();
96  LOGE("eglGetError(): %i (0x%.4x)\n", (int)error, (int)error);
97  LOGE("Failed to enumerate EGL configs at %s:%i\n", __FILE__, __LINE__);
98  exit(1);
99  }
100 
101  LOGD("Number of configs found is %d\n", numberOfConfigs);
102 
103  if (numberOfConfigs == 0)
104  {
105  LOGD("Disabling AntiAliasing to try and find a config.\n");
106  configAttributes[1] = EGL_DONT_CARE;
107  success = eglChooseConfig(display, configAttributes, NULL, 0, &numberOfConfigs);
108  if(success != EGL_TRUE)
109  {
110  EGLint error = eglGetError();
111  LOGE("eglGetError(): %i (0x%.4x)\n", (int)error, (int)error);
112  LOGE("Failed to enumerate EGL configs at %s:%i\n", __FILE__, __LINE__);
113  exit(1);
114  }
115 
116  if (numberOfConfigs == 0)
117  {
118  LOGE("No configs found with the requested attributes.\n");
119  exit(1);
120  }
121  else
122  {
123  LOGD("Configs found when antialiasing disabled.\n ");
124  }
125  }
126 
127  /* Allocate space for all EGL configs available and get them. */
128  configsArray = (EGLConfig *)calloc(numberOfConfigs, sizeof(EGLConfig));
129  if(configsArray == NULL)
130  {
131  LOGE("Out of memory at %s:%i\n", __FILE__, __LINE__);
132  exit(1);
133  }
134  success = eglChooseConfig(display, configAttributes, configsArray, numberOfConfigs, &numberOfConfigs);
135  if(success != EGL_TRUE)
136  {
137  EGLint error = eglGetError();
138  LOGE("eglGetError(): %i (0x%.4x)\n", (int)error, (int)error);
139  LOGE("Failed to enumerate EGL configs at %s:%i\n", __FILE__, __LINE__);
140  exit(1);
141  }
142 
143  bool matchFound = false;
144  int matchingConfig = -1;
145 
146  if (strictMatch)
147  {
148  /*
149  * Loop through the EGL configs to find a color depth match.
150  * Note: This is necessary, since EGL considers a higher color depth than requested to be 'better'
151  * even though this may force the driver to use a slow color conversion blitting routine.
152  */
153  EGLint redSize = configAttributes[5];
154  EGLint greenSize = configAttributes[7];
155  EGLint blueSize = configAttributes[9];
156 
157  for(int configsIndex = 0; (configsIndex < numberOfConfigs) && !matchFound; configsIndex++)
158  {
159  EGLint attributeValue = 0;
160 
161  success = eglGetConfigAttrib(display, configsArray[configsIndex], EGL_RED_SIZE, &attributeValue);
162  if(success != EGL_TRUE)
163  {
164  EGLint error = eglGetError();
165  LOGE("eglGetError(): %i (0x%.4x)\n", (int)error, (int)error);
166  LOGE("Failed to get EGL attribute at %s:%i\n", __FILE__, __LINE__);
167  exit(1);
168  }
169 
170  if(attributeValue == redSize)
171  {
172  success = eglGetConfigAttrib(display, configsArray[configsIndex], EGL_GREEN_SIZE, &attributeValue);
173  if(success != EGL_TRUE)
174  {
175  EGLint error = eglGetError();
176  LOGE("eglGetError(): %i (0x%.4x)\n", (int)error, (int)error);
177  LOGE("Failed to get EGL attribute at %s:%i\n", __FILE__, __LINE__);
178  exit(1);
179  }
180 
181  if(attributeValue == greenSize)
182  {
183  success = eglGetConfigAttrib(display, configsArray[configsIndex], EGL_BLUE_SIZE, &attributeValue);
184  if(success != EGL_TRUE)
185  {
186  EGLint error = eglGetError();
187  LOGE("eglGetError(): %i (0x%.4x)\n", (int)error, (int)error);
188  LOGE("Failed to get EGL attribute at %s:%i\n", __FILE__, __LINE__);
189  exit(1);
190  }
191 
192  if(attributeValue == blueSize)
193  {
194  matchFound = true;
195  matchingConfig = configsIndex;
196  }
197  }
198  }
199  }
200  }
201  else
202  {
203  /* If not strict we can use any matching config. */
204  matchingConfig = 0;
205  matchFound = true;
206  }
207 
208  if(!matchFound)
209  {
210  LOGE("Failed to find matching EGL config at %s:%i\n", __FILE__, __LINE__);
211  exit(1);
212  }
213 
214  /* Return the matching config. */
215  EGLConfig configToReturn = configsArray[matchingConfig];
216 
217  free(configsArray);
218  configsArray = NULL;
219 
220  return configToReturn;
221  }
222 
223  void EGLRuntime::initializeEGL(OpenGLESVersion requestedAPIVersion)
224  {
225  EGLBoolean success = EGL_FALSE;
226 
227 #if defined(_WIN32)
228  /* Win32 */
229  display = eglGetDisplay(platform->deviceContext);
230 #elif defined(__arm__)
231  /* Linux on ARM */
232  display = eglGetDisplay(EGL_DEFAULT_DISPLAY);
233 #else
234  /* Desktop Linux */
235  platform->display = XOpenDisplay(NULL);
236  display = eglGetDisplay(platform->display);
237 #endif
238 
239  if(display == EGL_NO_DISPLAY)
240  {
241  EGLint error = eglGetError();
242  LOGE("eglGetError(): %i (0x%.4x)\n", (int)error, (int)error);
243  LOGE("No EGL Display available at %s:%i\n", __FILE__, __LINE__);
244  exit(1);
245  }
246 
247  /* Initialize EGL. */
248  success = eglInitialize(display, NULL, NULL);
249  if(success != EGL_TRUE)
250  {
251  EGLint error = eglGetError();
252  LOGE("eglGetError(): %i (0x%.4x)\n", (int)error, (int)error);
253  LOGE("Failed to initialize EGL at %s:%i\n", __FILE__, __LINE__);
254  exit(1);
255  }
256 
257  /* Depending on app-requested EGL attributes, tweak the attributes we pass to EGL. */
258  if(requestedAPIVersion == OPENGLES1)
259  {
260  configAttributes[15] = EGL_OPENGL_ES_BIT;
261  contextAttributes[1] = 1;
262  }
263  else if(requestedAPIVersion == OPENGLES2)
264  {
265  configAttributes[15] = EGL_OPENGL_ES2_BIT;
266  contextAttributes[1] = 2;
267  }
268  /*
269  * Despite the fact an OpenGL ES 3.0 config is required, we request configs using the OpenGL_ES2_BIT.
270  * At the time of writing there is no OpenGL_ES3_BIT, and so platforms return
271  * OpenGL ES 3.0 configs with the OpenGL_ES2_BIT set.
272  * We request a context with EGL_CONTEXT_CLIENT_VERSION of 3 (OpenGL ES 3.0) which will ensure that
273  * OpenGL ES 3.0 features are supported.
274  */
275  else if (requestedAPIVersion == OPENGLES3)
276  {
277  configAttributes[15] = EGL_OPENGL_ES2_BIT;
278  contextAttributes[1] = 3;
279  }
280 
281  /*
282  * Find a matching config and store it in our static variable.
283  * On ARM devices perform a strict match to ensure we get the best performance.
284  * On desktop devices perform a loose match to ensure greatest compatability.
285  */
286 #if defined(__arm__)
287  config = findConfig(true);
288 #else
289  config = findConfig(false);
290 #endif
291 
292 #if defined(__linux__) && !defined(__arm__)
293  ((DesktopLinuxPlatform*)(platform))->createX11Window();
294 #endif
295 
296  /* Create a surface. */
297  surface = eglCreateWindowSurface(display, config, (EGLNativeWindowType)(platform->window), windowAttributes);
298  if(surface == EGL_NO_SURFACE)
299  {
300  EGLint error = eglGetError();
301  LOGE("eglGetError(): %i (0x%.4x)\n", (int)error, (int)error);
302  LOGE("Failed to create EGL surface at %s:%i\n", __FILE__, __LINE__);
303  exit(1);
304  }
305 
306  /* Unconditionally bind to OpenGL ES API as we exit this function, since it's the default. */
307  eglBindAPI(EGL_OPENGL_ES_API);
308 
309  context = eglCreateContext(display, config, EGL_NO_CONTEXT, contextAttributes);
310  if(context == EGL_NO_CONTEXT)
311  {
312  EGLint error = eglGetError();
313  LOGE("eglGetError(): %i (0x%.4x)\n", (int)error, (int)error);
314  LOGE("Failed to create EGL context at %s:%i\n", __FILE__, __LINE__);
315  exit(1);
316  }
317  }
318 
319  void EGLRuntime::setEGLSamples(EGLint requiredEGLSamples)
320  {
321  configAttributes[1] = requiredEGLSamples;
322  }
323 
325  {
326  /* Shut down EGL. */
327  eglBindAPI(EGL_OPENGL_ES_API);
328  eglMakeCurrent(display, EGL_NO_SURFACE, EGL_NO_SURFACE, context);
329  eglMakeCurrent(display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
330  eglDestroyContext(display, context);
331  eglDestroySurface(display, surface);
332  eglTerminate(display);
333  }
334 }
static EGLint contextAttributes[]
Used to specify the EGL attributes we require from a context.
Definition: EGLRuntime.h:67
static EGLSurface surface
The EGL surface in use.
Definition: EGLRuntime.h:121
static EGLint configAttributes[]
Used to specify the EGL attributes we require from a configuration.
Definition: EGLRuntime.h:60
static void setEGLSamples(EGLint requiredEGLSamples)
Set the value of EGL_SAMPLES (AntiAliasing level) to be requested.
Definition: EGLRuntime.cpp:319
static EGLConfig findConfig(bool strictMatch)
Search for an EGL config with the attributes set in configAttributes.
Definition: EGLRuntime.cpp:85
static Platform * getInstance(void)
Definition: Platform.cpp:28
#define LOGD(...)
Definition: AstcTextures.h:28
Abstract class to hide the complexity of multiple build targets.
Definition: Platform.h:36
static EGLDisplay display
The EGL display in use (a platform native window handle).
Definition: EGLRuntime.h:100
static EGLContext context
The EGL context in use.
Definition: EGLRuntime.h:108
static void terminateEGL(void)
Shuts down EGL.
Definition: EGLRuntime.cpp:324
static void initializeEGL(OpenGLESVersion requestedAPIVersion)
Setup EGL environment.
Definition: EGLRuntime.cpp:223
static EGLint windowAttributes[]
Used to specify the EGL attributes we require from a window surface.
Definition: EGLRuntime.h:74
static EGLConfig config
The selected EGL config which matches the required attributes.
Definition: EGLRuntime.h:113
#define LOGE(...)
Definition: AstcTextures.h:30
OpenGLESVersion
An enum to define OpenGL ES versions.
Definition: EGLRuntime.h:93
Platform * platform
Definition: EGLRuntime.cpp:28