FazBrowse GitHub Viewer
|
Trending
|
URL:
|
Home
Tools:
[Download Repo ZIP]
[View Raw Code]
[Original HTTPS Page]
SFML/src/SFML/Window/EglContext.cpp at master · criptych/SFML · GitHub
criptych
/
SFML
Public
forked from
SFML/SFML
Notifications
You must be signed in to change notification settings
Fork
0
Star
1
Code
Pull requests
0
Actions
Projects
Wiki
Security and quality
0
Insights
Additional navigation options
Code
Pull requests
Actions
Projects
Wiki
Security and quality
Insights
Expand file tree
Breadcrumbs
SFML
/
src
/
SFML
/
Window
/
EglContext.cpp
Copy path
More file actions
More file actions
Latest commit
History
History
History
429 lines (330 loc) · 14 KB
Breadcrumbs
SFML
/
src
/
SFML
/
Window
/
EglContext.cpp
Copy path
File metadata and controls
429 lines (330 loc) · 14 KB
Raw
Copy raw file
Download raw file
Open symbols panel
Edit and raw actions
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
//
//////////////////////////////////////////////////////////
//
//
SFML - Simple and Fast Multimedia Library
//
Copyright (C) 2013 Jonathan De Wachter (dewachter.jonathan@gmail.com)
//
//
This software is provided 'as-is', without any express or implied warranty.
//
In no event will the authors be held liable for any damages arising from the use of this software.
//
//
Permission is granted to anyone to use this software for any purpose,
//
including commercial applications, and to alter it and redistribute it freely,
//
subject to the following restrictions:
//
//
1. The origin of this software must not be misrepresented;
//
you must not claim that you wrote the original software.
//
If you use this software in a product, an acknowledgment
//
in the product documentation would be appreciated but is not required.
//
//
2. Altered source versions must be plainly marked as such,
//
and must not be misrepresented as being the original software.
//
//
3. This notice may not be removed or altered from any source distribution.
//
//
//////////////////////////////////////////////////////////
//
//////////////////////////////////////////////////////////
//
Headers
//
//////////////////////////////////////////////////////////
#
include
<
SFML/Window/EglContext.hpp
>
#
include
<
SFML/Window/WindowImpl.hpp
>
#
include
<
SFML/System/Err.hpp
>
#
include
<
SFML/System/Sleep.hpp
>
#
include
<
array
>
#
include
<
memory
>
#
include
<
mutex
>
#
include
<
ostream
>
#
ifdef
SFML_SYSTEM_ANDROID
#
include
<
SFML/System/Android/Activity.hpp
>
#
endif
#
if
defined(SFML_SYSTEM_LINUX) && !defined(SFML_USE_DRM)
#
include
<
SFML/Window/Unix/Utils.hpp
>
#
include
<
X11/Xlib.h
>
#
endif
//
We check for this definition in order to avoid multiple definitions of GLAD
//
entities during unity builds of SFML.
#
ifndef
SF_GLAD_EGL_IMPLEMENTATION_INCLUDED
#
define
SF_GLAD_EGL_IMPLEMENTATION_INCLUDED
#
define
SF_GLAD_EGL_IMPLEMENTATION
#
include
<
glad/egl.h
>
#
endif
namespace
{
//
A nested named namespace is used here to allow unity builds of SFML.
namespace
EglContextImpl
{
EGLDisplay
getInitializedDisplay
()
{
#
if
defined(SFML_SYSTEM_ANDROID)
//
On Android, its native activity handles this for us
sf::priv::ActivityStates& states =
sf::priv::getActivity
();
const
std::lock_guard
lock
(states.
mutex
);
return
states.
display
;
#
endif
static
EGLDisplay display =
EGL_NO_DISPLAY
;
if
(display ==
EGL_NO_DISPLAY
)
{
display =
eglCheck
(
eglGetDisplay
(
EGL_DEFAULT_DISPLAY
));
eglCheck
(
eglInitialize
(display,
nullptr
,
nullptr
));
}
return
display;
}
//
//////////////////////////////////////////////////////////
void
ensureInit
()
{
static
std::once_flag flag;
std::call_once
(flag,
[]
{
if
(!
gladLoaderLoadEGL
(
EGL_NO_DISPLAY
))
{
//
At this point, the failure is unrecoverable
//
Dump a message to the console and let the application terminate
sf::err
() <<
"
Failed to load EGL entry points
"
<< std::endl;
assert
(
false
);
return
false
;
}
//
Continue loading with a display
gladLoaderLoadEGL
(
getInitializedDisplay
());
return
true
;
});
}
}
//
namespace EglContextImpl
}
//
namespace
namespace
sf
::priv
{
//
//////////////////////////////////////////////////////////
EglContext::EglContext
(EglContext* shared)
{
EglContextImpl::ensureInit
();
//
Get the initialized EGL display
m_display =
EglContextImpl::getInitializedDisplay
();
//
Get the best EGL config matching the default video settings
m_config =
getBestConfig
(m_display,
VideoMode::getDesktopMode
().
bitsPerPixel
,
ContextSettings
());
updateSettings
();
//
Note: The EGL specs say that attribList can be a null pointer when passed to eglCreatePbufferSurface,
//
but this is resulting in a segfault. Bug in Android?
static
constexpr
std::array attribList = {
EGL_WIDTH
,
1
,
EGL_HEIGHT
,
1
,
EGL_NONE
};
m_surface =
eglCheck
(
eglCreatePbufferSurface
(m_display, m_config, attribList.
data
()));
//
Create EGL context
createContext
(shared);
}
//
//////////////////////////////////////////////////////////
EglContext::EglContext
(EglContext* shared,
const
ContextSettings& settings,
[[maybe_unused]]
const
WindowImpl& owner,
unsigned
int
bitsPerPixel)
{
EglContextImpl::ensureInit
();
#
ifdef
SFML_SYSTEM_ANDROID
//
On Android, we must save the created context
ActivityStates& states =
getActivity
();
const
std::lock_guard
lock
(states.
mutex
);
states.
context
=
this
;
#
endif
//
Get the initialized EGL display
m_display =
EglContextImpl::getInitializedDisplay
();
//
Get the best EGL config matching the requested video settings
m_config =
getBestConfig
(m_display, bitsPerPixel, settings);
updateSettings
();
//
Create EGL context
createContext
(shared);
#
if
!defined(SFML_SYSTEM_ANDROID)
//
Create EGL surface (except on Android because the window is created
//
asynchronously, its activity manager will call it for us)
createSurface
(owner.
getNativeHandle
());
#
endif
}
//
//////////////////////////////////////////////////////////
EglContext::EglContext
(EglContext*
/*
shared
*/
,
const
ContextSettings&
/*
settings
*/
, Vector2u
/*
size
*/
)
{
EglContextImpl::ensureInit
();
sf::err
() <<
"
Warning: context has not been initialized. The constructor EglContext(shared, settings, size) is
"
"
currently not implemented.
"
<< std::endl;
}
//
//////////////////////////////////////////////////////////
EglContext::~EglContext
()
{
//
Notify unshared OpenGL resources of context destruction
cleanupUnsharedResources
();
//
Deactivate the current context
const
EGLContext currentContext =
eglCheck
(
eglGetCurrentContext
());
if
(currentContext == m_context)
{
eglCheck
(
eglMakeCurrent
(m_display,
EGL_NO_SURFACE
,
EGL_NO_SURFACE
,
EGL_NO_CONTEXT
));
}
//
Destroy context
if
(m_context !=
EGL_NO_CONTEXT
)
{
eglCheck
(
eglDestroyContext
(m_display, m_context));
}
//
Destroy surface
if
(m_surface !=
EGL_NO_SURFACE
)
{
eglCheck
(
eglDestroySurface
(m_display, m_surface));
}
}
//
//////////////////////////////////////////////////////////
GlFunctionPointer
EglContext::getFunction
(
const
char
* name)
{
EglContextImpl::ensureInit
();
return
eglGetProcAddress
(name);
}
//
//////////////////////////////////////////////////////////
bool
EglContext::makeCurrent
(
bool
current)
{
if
(m_surface ==
EGL_NO_SURFACE
)
return
false
;
if
(current)
return
EGL_FALSE
!=
eglCheck
(
eglMakeCurrent
(m_display, m_surface, m_surface, m_context));
return
EGL_FALSE
!=
eglCheck
(
eglMakeCurrent
(m_display,
EGL_NO_SURFACE
,
EGL_NO_SURFACE
,
EGL_NO_CONTEXT
));
}
//
//////////////////////////////////////////////////////////
void
EglContext::display
()
{
if
(m_surface !=
EGL_NO_SURFACE
)
eglCheck
(
eglSwapBuffers
(m_display, m_surface));
}
//
//////////////////////////////////////////////////////////
void
EglContext::setVerticalSyncEnabled
(
bool
enabled)
{
eglCheck
(
eglSwapInterval
(m_display, enabled));
}
//
//////////////////////////////////////////////////////////
void
EglContext::createContext
(EglContext* shared)
{
static
constexpr
std::array contextVersion = {
EGL_CONTEXT_CLIENT_VERSION
,
1
,
EGL_NONE
};
const
EGLContext toShared = shared ? shared->
m_context
:
EGL_NO_CONTEXT
;
if
(toShared !=
EGL_NO_CONTEXT
)
eglCheck
(
eglMakeCurrent
(m_display,
EGL_NO_SURFACE
,
EGL_NO_SURFACE
,
EGL_NO_CONTEXT
));
//
Create EGL context
m_context =
eglCheck
(
eglCreateContext
(m_display, m_config, toShared, contextVersion.
data
()));
}
//
//////////////////////////////////////////////////////////
void
EglContext::createSurface
(EGLNativeWindowType window)
{
m_surface =
eglCheck
(
eglCreateWindowSurface
(m_display, m_config, window,
nullptr
));
}
//
//////////////////////////////////////////////////////////
void
EglContext::destroySurface
()
{
//
Ensure that this context is no longer active since our surface is going to be destroyed
setActive
(
false
);
eglCheck
(
eglDestroySurface
(m_display, m_surface));
m_surface =
EGL_NO_SURFACE
;
}
//
//////////////////////////////////////////////////////////
EGLConfig
EglContext::getBestConfig
(EGLDisplay display,
unsigned
int
bitsPerPixel,
const
ContextSettings& settings)
{
EglContextImpl::ensureInit
();
//
Determine the number of available configs
EGLint configCount =
0
;
eglCheck
(
eglGetConfigs
(display,
nullptr
,
0
, &configCount));
//
Retrieve the list of available configs
//
NOLINTNEXTLINE(cppcoreguidelines-avoid-c-arrays,modernize-avoid-c-arrays)
const
auto
configs = std::make_unique<EGLConfig[]>(
static_cast
<std::
size_t
>(configCount));
eglCheck
(
eglGetConfigs
(display, configs.
get
(), configCount, &configCount));
//
Evaluate all the returned configs, and pick the best one
int
bestScore =
0x7FFFFFFF
;
EGLConfig bestConfig{};
for
(std::
size_t
i =
0
; i <
static_cast
<std::
size_t
>(configCount); ++i)
{
//
Check mandatory attributes
int
surfaceType =
0
;
int
renderableType =
0
;
eglCheck
(
eglGetConfigAttrib
(display, configs[i],
EGL_SURFACE_TYPE
, &surfaceType));
eglCheck
(
eglGetConfigAttrib
(display, configs[i],
EGL_RENDERABLE_TYPE
, &renderableType));
if
(!(surfaceType & (
EGL_WINDOW_BIT
|
EGL_PBUFFER_BIT
)) || !(renderableType &
EGL_OPENGL_ES_BIT
))
continue
;
//
Extract the components of the current config
int
red =
0
;
int
green =
0
;
int
blue =
0
;
int
alpha =
0
;
int
depth =
0
;
int
stencil =
0
;
int
multiSampling =
0
;
int
samples =
0
;
int
caveat =
0
;
eglCheck
(
eglGetConfigAttrib
(display, configs[i],
EGL_RED_SIZE
, &red));
eglCheck
(
eglGetConfigAttrib
(display, configs[i],
EGL_GREEN_SIZE
, &green));
eglCheck
(
eglGetConfigAttrib
(display, configs[i],
EGL_BLUE_SIZE
, &blue));
eglCheck
(
eglGetConfigAttrib
(display, configs[i],
EGL_ALPHA_SIZE
, &alpha));
eglCheck
(
eglGetConfigAttrib
(display, configs[i],
EGL_DEPTH_SIZE
, &depth));
eglCheck
(
eglGetConfigAttrib
(display, configs[i],
EGL_STENCIL_SIZE
, &stencil));
eglCheck
(
eglGetConfigAttrib
(display, configs[i],
EGL_SAMPLE_BUFFERS
, &multiSampling));
eglCheck
(
eglGetConfigAttrib
(display, configs[i],
EGL_SAMPLES
, &samples));
eglCheck
(
eglGetConfigAttrib
(display, configs[i],
EGL_CONFIG_CAVEAT
, &caveat));
//
Evaluate the config
const
int
color = red + green + blue + alpha;
const
int
score =
evaluateFormat
(bitsPerPixel,
settings,
color,
depth,
stencil,
multiSampling ? samples :
0
,
caveat ==
EGL_NONE
,
false
);
//
If it's better than the current best, make it the new best
if
(score < bestScore)
{
bestScore = score;
bestConfig = configs[i];
}
}
assert
(bestScore <
0x7FFFFFFF
&&
"
Failed to calculate best config
"
);
return
bestConfig;
}
//
//////////////////////////////////////////////////////////
void
EglContext::updateSettings
()
{
m_settings.
majorVersion
=
1
;
m_settings.
minorVersion
=
1
;
m_settings.
attributeFlags
= ContextSettings::Default;
m_settings.
depthBits
=
0
;
m_settings.
stencilBits
=
0
;
m_settings.
antiAliasingLevel
=
0
;
EGLint tmp =
0
;
//
Update the internal context settings with the current config
if
(
eglCheck
(
eglGetConfigAttrib
(m_display, m_config,
EGL_DEPTH_SIZE
, &tmp)) !=
EGL_FALSE
)
m_settings.
depthBits
=
static_cast
<
unsigned
int
>(tmp);
if
(
eglCheck
(
eglGetConfigAttrib
(m_display, m_config,
EGL_STENCIL_SIZE
, &tmp)) !=
EGL_FALSE
)
m_settings.
stencilBits
=
static_cast
<
unsigned
int
>(tmp);
if
(
eglCheck
(
eglGetConfigAttrib
(m_display, m_config,
EGL_SAMPLE_BUFFERS
, &tmp)) !=
EGL_FALSE
&& tmp &&
eglCheck
(
eglGetConfigAttrib
(m_display, m_config,
EGL_SAMPLES
, &tmp)) !=
EGL_FALSE
)
m_settings.
antiAliasingLevel
=
static_cast
<
unsigned
int
>(tmp);
}
#
if
defined(SFML_SYSTEM_LINUX) && !defined(SFML_USE_DRM)
//
//////////////////////////////////////////////////////////
XVisualInfo
EglContext::selectBestVisual
(::Display* xDisplay,
unsigned
int
bitsPerPixel,
const
ContextSettings& settings)
{
EglContextImpl::ensureInit
();
//
Get the initialized EGL display
EGLDisplay display =
EglContextImpl::getInitializedDisplay
();
//
Get the best EGL config matching the default video settings
EGLConfig config =
getBestConfig
(display, bitsPerPixel, settings);
//
Retrieve the visual id associated with this EGL config
EGLint nativeVisualId =
0
;
eglCheck
(
eglGetConfigAttrib
(display, config,
EGL_NATIVE_VISUAL_ID
, &nativeVisualId));
if
(nativeVisualId ==
0
)
{
//
Should never happen...
err
() <<
"
No EGL visual found. You should check your graphics driver
"
<< std::endl;
return
{};
}
XVisualInfo vTemplate;
vTemplate.
visualid
=
static_cast
<VisualID>(nativeVisualId);
//
Get X11 visuals compatible with this EGL config
int
visualCount =
0
;
//
NOLINTNEXTLINE(cppcoreguidelines-avoid-c-arrays,modernize-avoid-c-arrays)
const
auto
availableVisuals = X11Ptr<XVisualInfo[]>(
XGetVisualInfo
(xDisplay, VisualIDMask, &vTemplate, &visualCount));
if
(visualCount ==
0
)
{
//
Can't happen...
err
() <<
"
No X11 visual found. Bug in your EGL implementation ?
"
<< std::endl;
return
{};
}
//
Pick up the best one
return
availableVisuals[
0
];
}
#
endif
}
//
namespace sf::priv
Back
|
FazBrowse Home
|
New Git URL