1
/****************************************************************************
3
** Copyright (C) 2012 Digia Plc and/or its subsidiary(-ies).
4
** Contact: http://www.qt-project.org/legal
6
** This file is part of the plugins of the Qt Toolkit.
8
** $QT_BEGIN_LICENSE:LGPL$
9
** Commercial License Usage
10
** Licensees holding valid commercial Qt licenses may use this file in
11
** accordance with the commercial license agreement provided with the
12
** Software or, alternatively, in accordance with the terms contained in
13
** a written agreement between you and Digia. For licensing terms and
14
** conditions see http://qt.digia.com/licensing. For further information
15
** use the contact form at http://qt.digia.com/contact-us.
17
** GNU Lesser General Public License Usage
18
** Alternatively, this file may be used under the terms of the GNU Lesser
19
** General Public License version 2.1 as published by the Free Software
20
** Foundation and appearing in the file LICENSE.LGPL included in the
21
** packaging of this file. Please review the following information to
22
** ensure the GNU Lesser General Public License version 2.1 requirements
23
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
25
** In addition, as a special exception, Digia gives you certain additional
26
** rights. These rights are described in the Digia Qt LGPL Exception
27
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
29
** GNU General Public License Usage
30
** Alternatively, this file may be used under the terms of the GNU
31
** General Public License version 3.0 as published by the Free Software
32
** Foundation and appearing in the file LICENSE.GPL included in the
33
** packaging of this file. Please review the following information to
34
** ensure the GNU General Public License version 3.0 requirements will be
35
** met: http://www.gnu.org/copyleft/gpl.html.
40
****************************************************************************/
44
#include "qeglconvenience_p.h"
48
QVector<EGLint> q_createConfigAttributesFromFormat(const QSurfaceFormat &format)
50
int redSize = format.redBufferSize();
51
int greenSize = format.greenBufferSize();
52
int blueSize = format.blueBufferSize();
53
int alphaSize = format.alphaBufferSize();
54
int depthSize = format.depthBufferSize();
55
int stencilSize = format.stencilBufferSize();
56
int sampleCount = format.samples();
58
// We want to make sure 16-bit configs are chosen over 32-bit configs as they will provide
59
// the best performance. The EGL config selection algorithm is a bit stange in this regard:
60
// The selection criteria for EGL_BUFFER_SIZE is "AtLeast", so we can't use it to discard
61
// 32-bit configs completely from the selection. So it then comes to the sorting algorithm.
62
// The red/green/blue sizes have a sort priority of 3, so they are sorted by first. The sort
63
// order is special and described as "by larger _total_ number of color bits.". So EGL will
64
// put 32-bit configs in the list before the 16-bit configs. However, the spec also goes on
65
// to say "If the requested number of bits in attrib_list for a particular component is 0,
66
// then the number of bits for that component is not considered". This part of the spec also
67
// seems to imply that setting the red/green/blue bits to zero means none of the components
68
// are considered and EGL disregards the entire sorting rule. It then looks to the next
69
// highest priority rule, which is EGL_BUFFER_SIZE. Despite the selection criteria being
70
// "AtLeast" for EGL_BUFFER_SIZE, it's sort order is "smaller" meaning 16-bit configs are
71
// put in the list before 32-bit configs. So, to make sure 16-bit is preffered over 32-bit,
72
// we must set the red/green/blue sizes to zero. This has an unfortunate consequence that
73
// if the application sets the red/green/blue size to 5/6/5 on the QSurfaceFormat,
74
// they will probably get a 32-bit config, even when there's an RGB565 config available.
76
// // Now normalize the values so -1 becomes 0
77
// redSize = redSize > 0 ? redSize : 0;
78
// greenSize = greenSize > 0 ? greenSize : 0;
79
// blueSize = blueSize > 0 ? blueSize : 0;
80
// alphaSize = alphaSize > 0 ? alphaSize : 0;
81
// depthSize = depthSize > 0 ? depthSize : 0;
82
// stencilSize = stencilSize > 0 ? stencilSize : 0;
83
// sampleCount = sampleCount > 0 ? sampleCount : 0;
85
QVector<EGLint> configAttributes;
87
configAttributes.append(EGL_RED_SIZE);
88
configAttributes.append(redSize > 0 ? redSize : 0);
90
configAttributes.append(EGL_GREEN_SIZE);
91
configAttributes.append(greenSize > 0 ? greenSize : 0);
93
configAttributes.append(EGL_BLUE_SIZE);
94
configAttributes.append(blueSize > 0 ? blueSize : 0);
96
configAttributes.append(EGL_ALPHA_SIZE);
97
configAttributes.append(alphaSize > 0 ? alphaSize : 0);
99
configAttributes.append(EGL_DEPTH_SIZE);
100
configAttributes.append(depthSize > 0 ? depthSize : 0);
102
configAttributes.append(EGL_STENCIL_SIZE);
103
// TODO: Note stencil is ignored due to mesa-egl-platform-mir radeon issue.... (racarr)
104
// configAttributes.append(stencilSize > 0 ? stencilSize : 0);
105
configAttributes.append(0);
107
configAttributes.append(EGL_SAMPLES);
108
configAttributes.append(sampleCount > 0 ? sampleCount : 0);
110
configAttributes.append(EGL_SAMPLE_BUFFERS);
111
configAttributes.append(sampleCount > 0);
113
return configAttributes;
116
bool q_reduceConfigAttributes(QVector<EGLint> *configAttributes)
119
// Reduce the complexity of a configuration request to ask for less
120
// because the previous request did not result in success. Returns
121
// true if the complexity was reduced, or false if no further
122
// reductions in complexity are possible.
124
i = configAttributes->indexOf(EGL_SWAP_BEHAVIOR);
126
configAttributes->remove(i,2);
129
#ifdef EGL_VG_ALPHA_FORMAT_PRE_BIT
130
// For OpenVG, we sometimes try to create a surface using a pre-multiplied format. If we can't
131
// find a config which supports pre-multiplied formats, remove the flag on the surface type:
133
i = configAttributes->indexOf(EGL_SURFACE_TYPE);
135
EGLint surfaceType = configAttributes->at(i +1);
136
if (surfaceType & EGL_VG_ALPHA_FORMAT_PRE_BIT) {
137
surfaceType ^= EGL_VG_ALPHA_FORMAT_PRE_BIT;
138
configAttributes->replace(i+1,surfaceType);
144
// EGL chooses configs with the highest color depth over
145
// those with smaller (but faster) lower color depths. One
146
// way around this is to set EGL_BUFFER_SIZE to 16, which
147
// trumps the others. Of course, there may not be a 16-bit
148
// config available, so it's the first restraint we remove.
149
i = configAttributes->indexOf(EGL_BUFFER_SIZE);
151
if (configAttributes->at(i+1) == 16) {
152
configAttributes->remove(i,2);
157
i = configAttributes->indexOf(EGL_SAMPLES);
159
EGLint value = configAttributes->value(i+1, 0);
161
configAttributes->replace(i+1, qMin(EGLint(16), value / 2));
163
configAttributes->remove(i, 2);
167
i = configAttributes->indexOf(EGL_SAMPLE_BUFFERS);
169
configAttributes->remove(i,2);
173
i = configAttributes->indexOf(EGL_ALPHA_SIZE);
175
configAttributes->remove(i,2);
176
#if defined(EGL_BIND_TO_TEXTURE_RGBA) && defined(EGL_BIND_TO_TEXTURE_RGB)
177
i = configAttributes->indexOf(EGL_BIND_TO_TEXTURE_RGBA);
179
configAttributes->replace(i,EGL_BIND_TO_TEXTURE_RGB);
180
configAttributes->replace(i+1,true);
187
i = configAttributes->indexOf(EGL_STENCIL_SIZE);
189
if (configAttributes->at(i + 1) > 1)
190
configAttributes->replace(i + 1, 1);
192
configAttributes->remove(i, 2);
196
i = configAttributes->indexOf(EGL_DEPTH_SIZE);
198
if (configAttributes->at(i + 1) > 1)
199
configAttributes->replace(i + 1, 1);
201
configAttributes->remove(i, 2);
204
#ifdef EGL_BIND_TO_TEXTURE_RGB
205
i = configAttributes->indexOf(EGL_BIND_TO_TEXTURE_RGB);
207
configAttributes->remove(i,2);
215
EGLConfig q_configFromGLFormat(EGLDisplay display, const QSurfaceFormat &format, bool highestPixelFormat, int surfaceType)
218
QVector<EGLint> configureAttributes = q_createConfigAttributesFromFormat(format);
219
configureAttributes.append(EGL_SURFACE_TYPE);
220
configureAttributes.append(surfaceType);
222
configureAttributes.append(EGL_RENDERABLE_TYPE);
223
if (format.renderableType() == QSurfaceFormat::OpenVG)
224
configureAttributes.append(EGL_OPENVG_BIT);
225
#ifdef EGL_VERSION_1_4
226
else if (format.renderableType() == QSurfaceFormat::OpenGL)
227
configureAttributes.append(EGL_OPENGL_BIT);
229
else if (format.majorVersion() == 1)
230
configureAttributes.append(EGL_OPENGL_ES_BIT);
232
configureAttributes.append(EGL_OPENGL_ES2_BIT);
234
configureAttributes.append(EGL_NONE);
237
// Get the number of matching configurations for this set of properties.
239
if (!eglChooseConfig(display, configureAttributes.constData(), 0, 0, &matching) || !matching)
242
// If we want the best pixel format, then return the first
243
// matching configuration.
244
if (highestPixelFormat) {
245
eglChooseConfig(display, configureAttributes.constData(), &cfg, 1, &matching);
251
// Fetch all of the matching configurations and find the
252
// first that matches the pixel format we wanted.
253
int i = configureAttributes.indexOf(EGL_RED_SIZE);
254
int confAttrRed = configureAttributes.at(i+1);
255
i = configureAttributes.indexOf(EGL_GREEN_SIZE);
256
int confAttrGreen = configureAttributes.at(i+1);
257
i = configureAttributes.indexOf(EGL_BLUE_SIZE);
258
int confAttrBlue = configureAttributes.at(i+1);
259
i = configureAttributes.indexOf(EGL_ALPHA_SIZE);
260
int confAttrAlpha = i == -1 ? 0 : configureAttributes.at(i+1);
262
EGLint size = matching;
263
EGLConfig *configs = new EGLConfig [size];
264
eglChooseConfig(display, configureAttributes.constData(), configs, size, &matching);
265
for (EGLint index = 0; index < size; ++index) {
266
EGLint red, green, blue, alpha;
267
eglGetConfigAttrib(display, configs[index], EGL_RED_SIZE, &red);
268
eglGetConfigAttrib(display, configs[index], EGL_GREEN_SIZE, &green);
269
eglGetConfigAttrib(display, configs[index], EGL_BLUE_SIZE, &blue);
270
eglGetConfigAttrib(display, configs[index], EGL_ALPHA_SIZE, &alpha);
271
if ((confAttrRed == 0 || red == confAttrRed) &&
272
(confAttrGreen == 0 || green == confAttrGreen) &&
273
(confAttrBlue == 0 || blue == confAttrBlue) &&
274
(confAttrAlpha == 0 || alpha == confAttrAlpha)) {
275
cfg = configs[index];
281
} while (q_reduceConfigAttributes(&configureAttributes));
282
qWarning("Cant find EGLConfig, returning null config");
286
QSurfaceFormat q_glFormatFromConfig(EGLDisplay display, const EGLConfig config, const QSurfaceFormat &referenceFormat)
288
QSurfaceFormat format;
290
EGLint greenSize = 0;
292
EGLint alphaSize = 0;
293
EGLint depthSize = 0;
294
EGLint stencilSize = 0;
295
EGLint sampleCount = 0;
296
EGLint renderableType = 0;
298
eglGetConfigAttrib(display, config, EGL_RED_SIZE, &redSize);
299
eglGetConfigAttrib(display, config, EGL_GREEN_SIZE, &greenSize);
300
eglGetConfigAttrib(display, config, EGL_BLUE_SIZE, &blueSize);
301
eglGetConfigAttrib(display, config, EGL_ALPHA_SIZE, &alphaSize);
302
eglGetConfigAttrib(display, config, EGL_DEPTH_SIZE, &depthSize);
303
eglGetConfigAttrib(display, config, EGL_STENCIL_SIZE, &stencilSize);
304
eglGetConfigAttrib(display, config, EGL_SAMPLES, &sampleCount);
305
eglGetConfigAttrib(display, config, EGL_RENDERABLE_TYPE, &renderableType);
307
if (referenceFormat.renderableType() == QSurfaceFormat::OpenVG && (renderableType & EGL_OPENVG_BIT))
308
format.setRenderableType(QSurfaceFormat::OpenVG);
309
#ifdef EGL_VERSION_1_4
310
else if (referenceFormat.renderableType() == QSurfaceFormat::OpenGL && (renderableType & EGL_OPENGL_BIT))
311
format.setRenderableType(QSurfaceFormat::OpenGL);
314
format.setRenderableType(QSurfaceFormat::OpenGLES);
316
format.setRedBufferSize(redSize);
317
format.setGreenBufferSize(greenSize);
318
format.setBlueBufferSize(blueSize);
319
format.setAlphaBufferSize(alphaSize);
320
format.setDepthBufferSize(depthSize);
321
format.setStencilBufferSize(stencilSize);
322
format.setSamples(sampleCount);
323
format.setStereo(false); // EGL doesn't support stereo buffers
325
// Clear the EGL error state because some of the above may
326
// have errored out because the attribute is not applicable
327
// to the surface type. Such errors don't matter.
333
bool q_hasEglExtension(EGLDisplay display, const char* extensionName)
335
QList<QByteArray> extensions =
336
QByteArray(reinterpret_cast<const char *>
337
(eglQueryString(display, EGL_EXTENSIONS))).split(' ');
338
return extensions.contains(extensionName);
341
struct AttrInfo { EGLint attr; const char *name; };
342
static struct AttrInfo attrs[] = {
343
{EGL_BUFFER_SIZE, "EGL_BUFFER_SIZE"},
344
{EGL_ALPHA_SIZE, "EGL_ALPHA_SIZE"},
345
{EGL_BLUE_SIZE, "EGL_BLUE_SIZE"},
346
{EGL_GREEN_SIZE, "EGL_GREEN_SIZE"},
347
{EGL_RED_SIZE, "EGL_RED_SIZE"},
348
{EGL_DEPTH_SIZE, "EGL_DEPTH_SIZE"},
349
{EGL_STENCIL_SIZE, "EGL_STENCIL_SIZE"},
350
{EGL_CONFIG_CAVEAT, "EGL_CONFIG_CAVEAT"},
351
{EGL_CONFIG_ID, "EGL_CONFIG_ID"},
352
{EGL_LEVEL, "EGL_LEVEL"},
353
{EGL_MAX_PBUFFER_HEIGHT, "EGL_MAX_PBUFFER_HEIGHT"},
354
{EGL_MAX_PBUFFER_PIXELS, "EGL_MAX_PBUFFER_PIXELS"},
355
{EGL_MAX_PBUFFER_WIDTH, "EGL_MAX_PBUFFER_WIDTH"},
356
{EGL_NATIVE_RENDERABLE, "EGL_NATIVE_RENDERABLE"},
357
{EGL_NATIVE_VISUAL_ID, "EGL_NATIVE_VISUAL_ID"},
358
{EGL_NATIVE_VISUAL_TYPE, "EGL_NATIVE_VISUAL_TYPE"},
359
{EGL_SAMPLES, "EGL_SAMPLES"},
360
{EGL_SAMPLE_BUFFERS, "EGL_SAMPLE_BUFFERS"},
361
{EGL_SURFACE_TYPE, "EGL_SURFACE_TYPE"},
362
{EGL_TRANSPARENT_TYPE, "EGL_TRANSPARENT_TYPE"},
363
{EGL_TRANSPARENT_BLUE_VALUE, "EGL_TRANSPARENT_BLUE_VALUE"},
364
{EGL_TRANSPARENT_GREEN_VALUE, "EGL_TRANSPARENT_GREEN_VALUE"},
365
{EGL_TRANSPARENT_RED_VALUE, "EGL_TRANSPARENT_RED_VALUE"},
366
{EGL_BIND_TO_TEXTURE_RGB, "EGL_BIND_TO_TEXTURE_RGB"},
367
{EGL_BIND_TO_TEXTURE_RGBA, "EGL_BIND_TO_TEXTURE_RGBA"},
368
{EGL_MIN_SWAP_INTERVAL, "EGL_MIN_SWAP_INTERVAL"},
369
{EGL_MAX_SWAP_INTERVAL, "EGL_MAX_SWAP_INTERVAL"},
372
void q_printEglConfig(EGLDisplay display, EGLConfig config)
375
for (index = 0; attrs[index].attr != -1; ++index) {
377
if (eglGetConfigAttrib(display, config, attrs[index].attr, &value)) {
378
qWarning("\t%s: %d\n", attrs[index].name, (int)value);