source: trunk/src/gui/egl/qeglproperties.cpp

Last change on this file was 846, checked in by Dmitry A. Kuminov, 14 years ago

trunk: Merged in qt 4.7.2 sources from branches/vendor/nokia/qt.

  • Property svn:eol-style set to native
File size: 17.9 KB
Line 
1/****************************************************************************
2**
3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
4** All rights reserved.
5** Contact: Nokia Corporation ([email protected])
6**
7** This file is part of the QtGui module of the Qt Toolkit.
8**
9** $QT_BEGIN_LICENSE:LGPL$
10** Commercial Usage
11** Licensees holding valid Qt Commercial licenses may use this file in
12** accordance with the Qt Commercial License Agreement provided with the
13** Software or, alternatively, in accordance with the terms contained in
14** a written agreement between you and Nokia.
15**
16** GNU Lesser General Public License Usage
17** Alternatively, this file may be used under the terms of the GNU Lesser
18** General Public License version 2.1 as published by the Free Software
19** Foundation and appearing in the file LICENSE.LGPL included in the
20** packaging of this file. Please review the following information to
21** ensure the GNU Lesser General Public License version 2.1 requirements
22** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
23**
24** In addition, as a special exception, Nokia gives you certain additional
25** rights. These rights are described in the Nokia Qt LGPL Exception
26** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
27**
28** GNU General Public License Usage
29** Alternatively, this file may be used under the terms of the GNU
30** General Public License version 3.0 as published by the Free Software
31** Foundation and appearing in the file LICENSE.GPL included in the
32** packaging of this file. Please review the following information to
33** ensure the GNU General Public License version 3.0 requirements will be
34** met: http://www.gnu.org/copyleft/gpl.html.
35**
36** If you have questions regarding the use of this file, please contact
37** Nokia at [email protected].
38** $QT_END_LICENSE$
39**
40****************************************************************************/
41
42#include <QtCore/qdebug.h>
43#include <QtCore/qstringlist.h>
44
45#include "qeglproperties_p.h"
46#include "qeglcontext_p.h"
47
48QT_BEGIN_NAMESPACE
49
50// Initialize a property block.
51QEglProperties::QEglProperties()
52{
53 props.append(EGL_NONE);
54}
55
56QEglProperties::QEglProperties(EGLConfig cfg)
57{
58 props.append(EGL_NONE);
59 for (int name = 0x3020; name <= 0x304F; ++name) {
60 EGLint value;
61 if (name != EGL_NONE && eglGetConfigAttrib(QEgl::display(), cfg, name, &value))
62 setValue(name, value);
63 }
64 eglGetError(); // Clear the error state.
65}
66
67// Fetch the current value associated with a property.
68int QEglProperties::value(int name) const
69{
70 for (int index = 0; index < (props.size() - 1); index += 2) {
71 if (props[index] == name)
72 return props[index + 1];
73 }
74
75 // If the attribute has not been explicitly set, return the EGL default
76 // The following defaults were taken from the EGL 1.4 spec:
77 switch(name) {
78 case EGL_BUFFER_SIZE: return 0;
79 case EGL_RED_SIZE: return 0;
80 case EGL_GREEN_SIZE: return 0;
81 case EGL_BLUE_SIZE: return 0;
82 case EGL_ALPHA_SIZE: return 0;
83#ifdef EGL_LUMINANCE_SIZE
84 case EGL_LUMINANCE_SIZE: return 0;
85#endif
86#ifdef EGL_ALPHA_MASK_SIZE
87 case EGL_ALPHA_MASK_SIZE: return 0;
88#endif
89#ifdef EGL_BIND_TO_TEXTURE_RGB
90 case EGL_BIND_TO_TEXTURE_RGB: return EGL_DONT_CARE;
91#endif
92#ifdef EGL_BIND_TO_TEXTURE_RGBA
93 case EGL_BIND_TO_TEXTURE_RGBA: return EGL_DONT_CARE;
94#endif
95#ifdef EGL_COLOR_BUFFER_TYPE
96 case EGL_COLOR_BUFFER_TYPE: return EGL_RGB_BUFFER;
97#endif
98 case EGL_CONFIG_CAVEAT: return EGL_DONT_CARE;
99 case EGL_CONFIG_ID: return EGL_DONT_CARE;
100 case EGL_DEPTH_SIZE: return 0;
101 case EGL_LEVEL: return 0;
102 case EGL_NATIVE_RENDERABLE: return EGL_DONT_CARE;
103 case EGL_NATIVE_VISUAL_TYPE: return EGL_DONT_CARE;
104 case EGL_MAX_SWAP_INTERVAL: return EGL_DONT_CARE;
105 case EGL_MIN_SWAP_INTERVAL: return EGL_DONT_CARE;
106#ifdef EGL_RENDERABLE_TYPE
107 case EGL_RENDERABLE_TYPE: return EGL_OPENGL_ES_BIT;
108#endif
109 case EGL_SAMPLE_BUFFERS: return 0;
110 case EGL_SAMPLES: return 0;
111 case EGL_STENCIL_SIZE: return 0;
112 case EGL_SURFACE_TYPE: return EGL_WINDOW_BIT;
113 case EGL_TRANSPARENT_TYPE: return EGL_NONE;
114 case EGL_TRANSPARENT_RED_VALUE: return EGL_DONT_CARE;
115 case EGL_TRANSPARENT_GREEN_VALUE: return EGL_DONT_CARE;
116 case EGL_TRANSPARENT_BLUE_VALUE: return EGL_DONT_CARE;
117
118#ifdef EGL_VERSION_1_3
119 case EGL_CONFORMANT: return 0;
120 case EGL_MATCH_NATIVE_PIXMAP: return EGL_NONE;
121#endif
122
123 case EGL_MAX_PBUFFER_HEIGHT:
124 case EGL_MAX_PBUFFER_WIDTH:
125 case EGL_MAX_PBUFFER_PIXELS:
126 case EGL_NATIVE_VISUAL_ID:
127 case EGL_NONE:
128 // Attribute does not affect config selection.
129 return EGL_DONT_CARE;
130 default:
131 // Attribute is unknown in EGL <= 1.4.
132 return EGL_DONT_CARE;
133 }
134}
135
136// Set the value associated with a property, replacing an existing
137// value if there is one.
138void QEglProperties::setValue(int name, int value)
139{
140 for (int index = 0; index < (props.size() - 1); index += 2) {
141 if (props[index] == name) {
142 props[index + 1] = value;
143 return;
144 }
145 }
146 props[props.size() - 1] = name;
147 props.append(value);
148 props.append(EGL_NONE);
149}
150
151// Remove a property value. Returns false if the property is not present.
152bool QEglProperties::removeValue(int name)
153{
154 for (int index = 0; index < (props.size() - 1); index += 2) {
155 if (props[index] == name) {
156 while ((index + 2) < props.size()) {
157 props[index] = props[index + 2];
158 ++index;
159 }
160 props.resize(props.size() - 2);
161 return true;
162 }
163 }
164 return false;
165}
166
167void QEglProperties::setDeviceType(int devType)
168{
169 if (devType == QInternal::Pixmap || devType == QInternal::Image)
170 setValue(EGL_SURFACE_TYPE, EGL_PIXMAP_BIT);
171 else if (devType == QInternal::Pbuffer)
172 setValue(EGL_SURFACE_TYPE, EGL_PBUFFER_BIT);
173 else
174 setValue(EGL_SURFACE_TYPE, EGL_WINDOW_BIT);
175}
176
177
178// Sets the red, green, blue, and alpha sizes based on a pixel format.
179// Normally used to match a configuration request to the screen format.
180void QEglProperties::setPixelFormat(QImage::Format pixelFormat)
181{
182 int red, green, blue, alpha;
183 switch (pixelFormat) {
184 case QImage::Format_RGB32:
185 case QImage::Format_RGB888:
186 red = green = blue = 8; alpha = 0; break;
187 case QImage::Format_ARGB32:
188 case QImage::Format_ARGB32_Premultiplied:
189 red = green = blue = alpha = 8; break;
190 case QImage::Format_RGB16:
191 red = 5; green = 6; blue = 5; alpha = 0; break;
192 case QImage::Format_ARGB8565_Premultiplied:
193 red = 5; green = 6; blue = 5; alpha = 8; break;
194 case QImage::Format_RGB666:
195 red = green = blue = 6; alpha = 0; break;
196 case QImage::Format_ARGB6666_Premultiplied:
197 red = green = blue = alpha = 6; break;
198 case QImage::Format_RGB555:
199 red = green = blue = 5; alpha = 0; break;
200 case QImage::Format_ARGB8555_Premultiplied:
201 red = green = blue = 5; alpha = 8; break;
202 case QImage::Format_RGB444:
203 red = green = blue = 4; alpha = 0; break;
204 case QImage::Format_ARGB4444_Premultiplied:
205 red = green = blue = alpha = 4; break;
206 default:
207 qWarning() << "QEglProperties::setPixelFormat(): Unsupported pixel format";
208 red = green = blue = alpha = 1; break;
209 }
210 setValue(EGL_RED_SIZE, red);
211 setValue(EGL_GREEN_SIZE, green);
212 setValue(EGL_BLUE_SIZE, blue);
213 setValue(EGL_ALPHA_SIZE, alpha);
214}
215
216void QEglProperties::setRenderableType(QEgl::API api)
217{
218#ifdef EGL_RENDERABLE_TYPE
219#if defined(QT_OPENGL_ES_2)
220 if (api == QEgl::OpenGL)
221 setValue(EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT);
222#elif defined(QT_OPENGL_ES)
223 if (api == QEgl::OpenGL)
224 setValue(EGL_RENDERABLE_TYPE, EGL_OPENGL_ES_BIT);
225#elif defined(EGL_OPENGL_BIT)
226 if (api == QEgl::OpenGL)
227 setValue(EGL_RENDERABLE_TYPE, EGL_OPENGL_BIT);
228#endif
229#ifdef EGL_OPENVG_BIT
230 if (api == QEgl::OpenVG)
231 setValue(EGL_RENDERABLE_TYPE, EGL_OPENVG_BIT);
232#endif
233#else
234 Q_UNUSED(api);
235#endif
236}
237
238// Reduce the complexity of a configuration request to ask for less
239// because the previous request did not result in success. Returns
240// true if the complexity was reduced, or false if no further
241// reductions in complexity are possible.
242bool QEglProperties::reduceConfiguration()
243{
244#ifdef EGL_SWAP_BEHAVIOR
245 if (value(EGL_SWAP_BEHAVIOR) != EGL_DONT_CARE)
246 removeValue(EGL_SWAP_BEHAVIOR);
247#endif
248
249#ifdef EGL_VG_ALPHA_FORMAT_PRE_BIT
250 // For OpenVG, we sometimes try to create a surface using a pre-multiplied format. If we can't
251 // find a config which supports pre-multiplied formats, remove the flag on the surface type:
252 EGLint surfaceType = value(EGL_SURFACE_TYPE);
253 if (surfaceType & EGL_VG_ALPHA_FORMAT_PRE_BIT) {
254 surfaceType ^= EGL_VG_ALPHA_FORMAT_PRE_BIT;
255 setValue(EGL_SURFACE_TYPE, surfaceType);
256 return true;
257 }
258#endif
259 // EGL chooses configs with the highest color depth over
260 // those with smaller (but faster) lower color depths. One
261 // way around this is to set EGL_BUFFER_SIZE to 16, which
262 // trumps the others. Of course, there may not be a 16-bit
263 // config available, so it's the first restraint we remove.
264 if (value(EGL_BUFFER_SIZE) == 16) {
265 removeValue(EGL_BUFFER_SIZE);
266 return true;
267 }
268 if (removeValue(EGL_SAMPLE_BUFFERS)) {
269 removeValue(EGL_SAMPLES);
270 return true;
271 }
272 if (removeValue(EGL_ALPHA_SIZE)) {
273#if defined(EGL_BIND_TO_TEXTURE_RGBA) && defined(EGL_BIND_TO_TEXTURE_RGB)
274 if (removeValue(EGL_BIND_TO_TEXTURE_RGBA))
275 setValue(EGL_BIND_TO_TEXTURE_RGB, TRUE);
276#endif
277 return true;
278 }
279 if (removeValue(EGL_STENCIL_SIZE))
280 return true;
281 if (removeValue(EGL_DEPTH_SIZE))
282 return true;
283#ifdef EGL_BIND_TO_TEXTURE_RGB
284 if (removeValue(EGL_BIND_TO_TEXTURE_RGB))
285 return true;
286#endif
287 return false;
288}
289
290static void addTag(QString& str, const QString& tag)
291{
292 int lastnl = str.lastIndexOf(QLatin1String("\n"));
293 if (lastnl == -1)
294 lastnl = 0;
295 if ((str.length() - lastnl) >= 50)
296 str += QLatin1String("\n ");
297 str += tag;
298}
299
300// Convert a property list to a string suitable for debug output.
301QString QEglProperties::toString() const
302{
303 QString str;
304 int val;
305
306 val = value(EGL_CONFIG_ID);
307 if (val != EGL_DONT_CARE) {
308 str += QLatin1String("id=");
309 str += QString::number(val);
310 str += QLatin1Char(' ');
311 }
312
313#ifdef EGL_RENDERABLE_TYPE
314 val = value(EGL_RENDERABLE_TYPE);
315 if (val != EGL_DONT_CARE) {
316 str += QLatin1String("type=");
317 QStringList types;
318 if ((val & EGL_OPENGL_ES_BIT) != 0)
319 types += QLatin1String("es1");
320#ifdef EGL_OPENGL_ES2_BIT
321 if ((val & EGL_OPENGL_ES2_BIT) != 0)
322 types += QLatin1String("es2");
323#endif
324#ifdef EGL_OPENGL_BIT
325 if ((val & EGL_OPENGL_BIT) != 0)
326 types += QLatin1String("gl");
327#endif
328 if ((val & EGL_OPENVG_BIT) != 0)
329 types += QLatin1String("vg");
330 if ((val & ~7) != 0)
331 types += QString::number(val);
332 str += types.join(QLatin1String(","));
333 } else {
334 str += QLatin1String("type=any");
335 }
336#else
337 str += QLatin1String("type=es1");
338#endif
339
340 int red = value(EGL_RED_SIZE);
341 int green = value(EGL_GREEN_SIZE);
342 int blue = value(EGL_BLUE_SIZE);
343 int alpha = value(EGL_ALPHA_SIZE);
344 int bufferSize = value(EGL_BUFFER_SIZE);
345 if (bufferSize == (red + green + blue + alpha))
346 bufferSize = 0;
347 str += QLatin1String(" rgba=");
348 str += QString::number(red);
349 str += QLatin1Char(',');
350 str += QString::number(green);
351 str += QLatin1Char(',');
352 str += QString::number(blue);
353 str += QLatin1Char(',');
354 str += QString::number(alpha);
355 if (bufferSize != 0) {
356 // Only report buffer size if different than r+g+b+a.
357 str += QLatin1String(" buffer-size=");
358 str += QString::number(bufferSize);
359 }
360
361#ifdef EGL_COLOR_BUFFER_TYPE
362 val = value(EGL_COLOR_BUFFER_TYPE);
363 if (val == EGL_LUMINANCE_BUFFER) {
364 addTag(str, QLatin1String(" color-buffer-type=luminance"));
365 } else if (val != EGL_DONT_CARE && val != EGL_RGB_BUFFER) {
366 addTag(str, QLatin1String(" color-buffer-type="));
367 str += QString::number(val, 16);
368 }
369#endif
370
371 val = value(EGL_DEPTH_SIZE);
372 if (val != 0) {
373 addTag(str, QLatin1String(" depth="));
374 str += QString::number(val);
375 }
376
377 val = value(EGL_STENCIL_SIZE);
378 if (val != 0) {
379 addTag(str, QLatin1String(" stencil="));
380 str += QString::number(val);
381 }
382
383 val = value(EGL_SURFACE_TYPE);
384 if (val != EGL_DONT_CARE) {
385 addTag(str, QLatin1String(" surface-type="));
386 QStringList types;
387 if ((val & EGL_WINDOW_BIT) != 0)
388 types += QLatin1String("window");
389 if ((val & EGL_PIXMAP_BIT) != 0)
390 types += QLatin1String("pixmap");
391 if ((val & EGL_PBUFFER_BIT) != 0)
392 types += QLatin1String("pbuffer");
393#ifdef EGL_VG_COLORSPACE_LINEAR_BIT
394 if ((val & EGL_VG_COLORSPACE_LINEAR_BIT) != 0)
395 types += QLatin1String("vg-colorspace-linear");
396#endif
397#ifdef EGL_VG_ALPHA_FORMAT_PRE_BIT
398 if ((val & EGL_VG_ALPHA_FORMAT_PRE_BIT) != 0)
399 types += QLatin1String("vg-alpha-format-pre");
400#endif
401 if ((val & ~(EGL_WINDOW_BIT | EGL_PIXMAP_BIT | EGL_PBUFFER_BIT
402#ifdef EGL_VG_COLORSPACE_LINEAR_BIT
403 | EGL_VG_COLORSPACE_LINEAR_BIT
404#endif
405#ifdef EGL_VG_ALPHA_FORMAT_PRE_BIT
406 | EGL_VG_ALPHA_FORMAT_PRE_BIT
407#endif
408 )) != 0) {
409 types += QString::number(val);
410 }
411 str += types.join(QLatin1String(","));
412 }
413
414 val = value(EGL_CONFIG_CAVEAT);
415 if (val != EGL_DONT_CARE) {
416 addTag(str, QLatin1String(" caveat="));
417 if (val == EGL_NONE)
418 str += QLatin1String("none");
419 else if (val == EGL_SLOW_CONFIG)
420 str += QLatin1String("slow");
421 else if (val == EGL_NON_CONFORMANT_CONFIG)
422 str += QLatin1String("non-conformant");
423 else
424 str += QString::number(val, 16);
425 }
426
427 val = value(EGL_LEVEL);
428 if (val != 0) {
429 addTag(str, QLatin1String(" level="));
430 str += QString::number(val);
431 }
432
433 int width, height, pixels;
434 width = value(EGL_MAX_PBUFFER_WIDTH);
435 height = value(EGL_MAX_PBUFFER_HEIGHT);
436 pixels = value(EGL_MAX_PBUFFER_PIXELS);
437 if (height != EGL_DONT_CARE || width != EGL_DONT_CARE) {
438 addTag(str, QLatin1String(" max-pbuffer-size="));
439 str += QString::number(width);
440 str += QLatin1Char('x');
441 str += QString::number(height);
442 if (pixels != (width * height)) {
443 addTag(str, QLatin1String(" max-pbuffer-pixels="));
444 str += QString::number(pixels);
445 }
446 }
447
448 val = value(EGL_NATIVE_RENDERABLE);
449 if (val != EGL_DONT_CARE) {
450 if (val)
451 addTag(str, QLatin1String(" native-renderable=true"));
452 else
453 addTag(str, QLatin1String(" native-renderable=false"));
454 }
455
456 val = value(EGL_NATIVE_VISUAL_ID);
457 if (val != EGL_DONT_CARE) {
458 addTag(str, QLatin1String(" visual-id="));
459 str += QString::number(val);
460 }
461
462 val = value(EGL_NATIVE_VISUAL_TYPE);
463 if (val != EGL_DONT_CARE) {
464 addTag(str, QLatin1String(" visual-type="));
465 str += QString::number(val);
466 }
467
468#ifdef EGL_PRESERVED_RESOURCES
469 val = value(EGL_PRESERVED_RESOURCES);
470 if (val != EGL_DONT_CARE) {
471 if (val)
472 addTag(str, QLatin1String(" preserved-resources=true"));
473 else
474 addTag(str, QLatin1String(" preserved-resources=false"));
475 }
476#endif
477
478 val = value(EGL_SAMPLES);
479 if (val != 0) {
480 addTag(str, QLatin1String(" samples="));
481 str += QString::number(val);
482 }
483
484 val = value(EGL_SAMPLE_BUFFERS);
485 if (val != 0) {
486 addTag(str, QLatin1String(" sample-buffers="));
487 str += QString::number(val);
488 }
489
490 val = value(EGL_TRANSPARENT_TYPE);
491 if (val == EGL_TRANSPARENT_RGB) {
492 addTag(str, QLatin1String(" transparent-rgb="));
493 str += QString::number(value(EGL_TRANSPARENT_RED_VALUE));
494 str += QLatin1Char(',');
495 str += QString::number(value(EGL_TRANSPARENT_GREEN_VALUE));
496 str += QLatin1Char(',');
497 str += QString::number(value(EGL_TRANSPARENT_BLUE_VALUE));
498 }
499
500#if defined(EGL_BIND_TO_TEXTURE_RGB) && defined(EGL_BIND_TO_TEXTURE_RGBA)
501 val = value(EGL_BIND_TO_TEXTURE_RGB);
502 int val2 = value(EGL_BIND_TO_TEXTURE_RGBA);
503 if (val != EGL_DONT_CARE || val2 != EGL_DONT_CARE) {
504 addTag(str, QLatin1String(" bind-texture="));
505 if (val == EGL_TRUE)
506 str += QLatin1String("rgb");
507 else
508 str += QLatin1String("no-rgb");
509 if (val2 == EGL_TRUE)
510 str += QLatin1String(",rgba");
511 else
512 str += QLatin1String(",no-rgba");
513 }
514#endif
515
516#ifdef EGL_MIN_SWAP_INTERVAL
517 val = value(EGL_MIN_SWAP_INTERVAL);
518 if (val != EGL_DONT_CARE) {
519 addTag(str, QLatin1String(" min-swap-interval="));
520 str += QString::number(val);
521 }
522#endif
523
524#ifdef EGL_MIN_SWAP_INTERVAL
525 val = value(EGL_MAX_SWAP_INTERVAL);
526 if (val != EGL_DONT_CARE) {
527 addTag(str, QLatin1String(" max-swap-interval="));
528 str += QString::number(val);
529 }
530#endif
531
532#ifdef EGL_LUMINANCE_SIZE
533 val = value(EGL_LUMINANCE_SIZE);
534 if (val != 0) {
535 addTag(str, QLatin1String(" luminance="));
536 str += QString::number(val);
537 }
538#endif
539
540#ifdef EGL_ALPHA_MASK_SIZE
541 val = value(EGL_ALPHA_MASK_SIZE);
542 if (val != 0) {
543 addTag(str, QLatin1String(" alpha-mask="));
544 str += QString::number(val);
545 }
546#endif
547
548#ifdef EGL_CONFORMANT
549 val = value(EGL_CONFORMANT);
550 if (val != 0) {
551 if (val)
552 addTag(str, QLatin1String(" conformant=true"));
553 else
554 addTag(str, QLatin1String(" conformant=false"));
555 }
556#endif
557
558 return str;
559}
560
561QT_END_NAMESPACE
562
563
Note: See TracBrowser for help on using the repository browser.