~robertcarr/qtubuntu/mirclient-with-input

« back to all changes in this revision

Viewing changes to src/platforms/ubuntu/qeglconvenience.cpp

  • Committer: Robert Carr
  • Date: 2013-04-01 22:13:20 UTC
  • Revision ID: robert.carr@canonical.com-20130401221320-ac2bu8up9ttlrrqp
Skeleton mirclient build

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/****************************************************************************
 
2
**
 
3
** Copyright (C) 2012 Digia Plc and/or its subsidiary(-ies).
 
4
** Contact: http://www.qt-project.org/legal
 
5
**
 
6
** This file is part of the plugins of the Qt Toolkit.
 
7
**
 
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.
 
16
**
 
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.
 
24
**
 
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.
 
28
**
 
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.
 
36
**
 
37
**
 
38
** $QT_END_LICENSE$
 
39
**
 
40
****************************************************************************/
 
41
 
 
42
#include <QByteArray>
 
43
 
 
44
#include "qeglconvenience_p.h"
 
45
 
 
46
QT_BEGIN_NAMESPACE
 
47
 
 
48
QVector<EGLint> q_createConfigAttributesFromFormat(const QSurfaceFormat &format)
 
49
{
 
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();
 
57
 
 
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.
 
75
 
 
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;
 
84
 
 
85
    QVector<EGLint> configAttributes;
 
86
 
 
87
    configAttributes.append(EGL_RED_SIZE);
 
88
    configAttributes.append(redSize > 0 ? redSize : 0);
 
89
 
 
90
    configAttributes.append(EGL_GREEN_SIZE);
 
91
    configAttributes.append(greenSize > 0 ? greenSize : 0);
 
92
 
 
93
    configAttributes.append(EGL_BLUE_SIZE);
 
94
    configAttributes.append(blueSize > 0 ? blueSize : 0);
 
95
 
 
96
    configAttributes.append(EGL_ALPHA_SIZE);
 
97
    configAttributes.append(alphaSize > 0 ? alphaSize : 0);
 
98
 
 
99
    configAttributes.append(EGL_DEPTH_SIZE);
 
100
    configAttributes.append(depthSize > 0 ? depthSize : 0);
 
101
 
 
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);
 
106
 
 
107
    configAttributes.append(EGL_SAMPLES);
 
108
    configAttributes.append(sampleCount > 0 ? sampleCount : 0);
 
109
 
 
110
    configAttributes.append(EGL_SAMPLE_BUFFERS);
 
111
    configAttributes.append(sampleCount > 0);
 
112
 
 
113
    return configAttributes;
 
114
}
 
115
 
 
116
bool q_reduceConfigAttributes(QVector<EGLint> *configAttributes)
 
117
{
 
118
    int i = -1;
 
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.
 
123
 
 
124
    i = configAttributes->indexOf(EGL_SWAP_BEHAVIOR);
 
125
    if (i >= 0) {
 
126
        configAttributes->remove(i,2);
 
127
    }
 
128
 
 
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:
 
132
 
 
133
    i = configAttributes->indexOf(EGL_SURFACE_TYPE);
 
134
    if (i >= 0) {
 
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);
 
139
            return true;
 
140
        }
 
141
    }
 
142
#endif
 
143
 
 
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);
 
150
    if (i >= 0) {
 
151
        if (configAttributes->at(i+1) == 16) {
 
152
            configAttributes->remove(i,2);
 
153
            return true;
 
154
        }
 
155
    }
 
156
 
 
157
    i = configAttributes->indexOf(EGL_SAMPLES);
 
158
    if (i >= 0) {
 
159
        EGLint value = configAttributes->value(i+1, 0);
 
160
        if (value > 1)
 
161
            configAttributes->replace(i+1, qMin(EGLint(16), value / 2));
 
162
        else
 
163
            configAttributes->remove(i, 2);
 
164
        return true;
 
165
    }
 
166
 
 
167
    i = configAttributes->indexOf(EGL_SAMPLE_BUFFERS);
 
168
    if (i >= 0) {
 
169
        configAttributes->remove(i,2);
 
170
        return true;
 
171
    }
 
172
 
 
173
    i = configAttributes->indexOf(EGL_ALPHA_SIZE);
 
174
    if (i >= 0) {
 
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);
 
178
        if (i >= 0) {
 
179
            configAttributes->replace(i,EGL_BIND_TO_TEXTURE_RGB);
 
180
            configAttributes->replace(i+1,true);
 
181
 
 
182
        }
 
183
#endif
 
184
        return true;
 
185
    }
 
186
 
 
187
    i = configAttributes->indexOf(EGL_STENCIL_SIZE);
 
188
    if (i >= 0) {
 
189
        if (configAttributes->at(i + 1) > 1)
 
190
            configAttributes->replace(i + 1, 1);
 
191
        else
 
192
            configAttributes->remove(i, 2);
 
193
        return true;
 
194
    }
 
195
 
 
196
    i = configAttributes->indexOf(EGL_DEPTH_SIZE);
 
197
    if (i >= 0) {
 
198
        if (configAttributes->at(i + 1) > 1)
 
199
            configAttributes->replace(i + 1, 1);
 
200
        else
 
201
            configAttributes->remove(i, 2);
 
202
        return true;
 
203
    }
 
204
#ifdef EGL_BIND_TO_TEXTURE_RGB
 
205
    i = configAttributes->indexOf(EGL_BIND_TO_TEXTURE_RGB);
 
206
    if (i >= 0) {
 
207
        configAttributes->remove(i,2);
 
208
        return true;
 
209
    }
 
210
#endif
 
211
 
 
212
    return false;
 
213
}
 
214
 
 
215
EGLConfig q_configFromGLFormat(EGLDisplay display, const QSurfaceFormat &format, bool highestPixelFormat, int surfaceType)
 
216
{
 
217
    EGLConfig cfg = 0;
 
218
    QVector<EGLint> configureAttributes = q_createConfigAttributesFromFormat(format);
 
219
    configureAttributes.append(EGL_SURFACE_TYPE);
 
220
    configureAttributes.append(surfaceType);
 
221
 
 
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);
 
228
#endif
 
229
    else if (format.majorVersion() == 1)
 
230
        configureAttributes.append(EGL_OPENGL_ES_BIT);
 
231
    else
 
232
        configureAttributes.append(EGL_OPENGL_ES2_BIT);
 
233
 
 
234
    configureAttributes.append(EGL_NONE);
 
235
 
 
236
    do {
 
237
        // Get the number of matching configurations for this set of properties.
 
238
        EGLint matching = 0;
 
239
        if (!eglChooseConfig(display, configureAttributes.constData(), 0, 0, &matching) || !matching)
 
240
            continue;
 
241
 
 
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);
 
246
            if (matching < 1)
 
247
                continue;
 
248
            return cfg;
 
249
        }
 
250
 
 
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);
 
261
 
 
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];
 
276
                delete [] configs;
 
277
                return cfg;
 
278
            }
 
279
        }
 
280
        delete [] configs;
 
281
    } while (q_reduceConfigAttributes(&configureAttributes));
 
282
    qWarning("Cant find EGLConfig, returning null config");
 
283
    return 0;
 
284
}
 
285
 
 
286
QSurfaceFormat q_glFormatFromConfig(EGLDisplay display, const EGLConfig config, const QSurfaceFormat &referenceFormat)
 
287
{
 
288
    QSurfaceFormat format;
 
289
    EGLint redSize     = 0;
 
290
    EGLint greenSize   = 0;
 
291
    EGLint blueSize    = 0;
 
292
    EGLint alphaSize   = 0;
 
293
    EGLint depthSize   = 0;
 
294
    EGLint stencilSize = 0;
 
295
    EGLint sampleCount = 0;
 
296
    EGLint renderableType = 0;
 
297
 
 
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);
 
306
 
 
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);
 
312
#endif
 
313
    else
 
314
        format.setRenderableType(QSurfaceFormat::OpenGLES);
 
315
 
 
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
 
324
 
 
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.
 
328
    eglGetError();
 
329
 
 
330
    return format;
 
331
}
 
332
 
 
333
bool q_hasEglExtension(EGLDisplay display, const char* extensionName)
 
334
{
 
335
    QList<QByteArray> extensions =
 
336
        QByteArray(reinterpret_cast<const char *>
 
337
            (eglQueryString(display, EGL_EXTENSIONS))).split(' ');
 
338
    return extensions.contains(extensionName);
 
339
}
 
340
 
 
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"},
 
370
    {-1, 0}};
 
371
 
 
372
void q_printEglConfig(EGLDisplay display, EGLConfig config)
 
373
{
 
374
    EGLint index;
 
375
    for (index = 0; attrs[index].attr != -1; ++index) {
 
376
        EGLint value;
 
377
        if (eglGetConfigAttrib(display, config, attrs[index].attr, &value)) {
 
378
            qWarning("\t%s: %d\n", attrs[index].name, (int)value);
 
379
        }
 
380
    }
 
381
 
 
382
    qWarning("\n");
 
383
}
 
384
 
 
385
QT_END_NAMESPACE