Qt 4.8
qeglconvenience.cpp
Go to the documentation of this file.
1 /****************************************************************************
2 **
3 ** Copyright (C) 2014 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 "qeglconvenience.h"
43 
45 
47 {
48  int redSize = format.redBufferSize();
49  int greenSize = format.greenBufferSize();
50  int blueSize = format.blueBufferSize();
51  int alphaSize = format.alphaBufferSize();
52  int depthSize = format.depthBufferSize();
53  int stencilSize = format.stencilBufferSize();
54  int sampleCount = format.samples();
55 
56  // QPlatformWindowFormat uses a magic value of -1 to indicate "don't care", even when a buffer of that
57  // type has been requested. So we must check QPlatformWindowFormat's booleans too if size is -1:
58  if (format.alpha() && alphaSize <= 0)
59  alphaSize = 1;
60  if (format.depth() && depthSize <= 0)
61  depthSize = 1;
62  if (format.stencil() && stencilSize <= 0)
63  stencilSize = 1;
64  if (format.sampleBuffers() && sampleCount <= 0)
65  sampleCount = 1;
66 
67  // We want to make sure 16-bit configs are chosen over 32-bit configs as they will provide
68  // the best performance. The EGL config selection algorithm is a bit stange in this regard:
69  // The selection criteria for EGL_BUFFER_SIZE is "AtLeast", so we can't use it to discard
70  // 32-bit configs completely from the selection. So it then comes to the sorting algorithm.
71  // The red/green/blue sizes have a sort priority of 3, so they are sorted by first. The sort
72  // order is special and described as "by larger _total_ number of color bits.". So EGL will
73  // put 32-bit configs in the list before the 16-bit configs. However, the spec also goes on
74  // to say "If the requested number of bits in attrib_list for a particular component is 0,
75  // then the number of bits for that component is not considered". This part of the spec also
76  // seems to imply that setting the red/green/blue bits to zero means none of the components
77  // are considered and EGL disregards the entire sorting rule. It then looks to the next
78  // highest priority rule, which is EGL_BUFFER_SIZE. Despite the selection criteria being
79  // "AtLeast" for EGL_BUFFER_SIZE, it's sort order is "smaller" meaning 16-bit configs are
80  // put in the list before 32-bit configs. So, to make sure 16-bit is preffered over 32-bit,
81  // we must set the red/green/blue sizes to zero. This has an unfortunate consequence that
82  // if the application sets the red/green/blue size to 5/6/5 on the QPlatformWindowFormat,
83  // they will probably get a 32-bit config, even when there's an RGB565 config available.
84 
85  // Now normalize the values so -1 becomes 0
86  redSize = redSize > 0 ? redSize : 0;
87  greenSize = greenSize > 0 ? greenSize : 0;
88  blueSize = blueSize > 0 ? blueSize : 0;
89  alphaSize = alphaSize > 0 ? alphaSize : 0;
90  depthSize = depthSize > 0 ? depthSize : 0;
91  stencilSize = stencilSize > 0 ? stencilSize : 0;
92  sampleCount = sampleCount > 0 ? sampleCount : 0;
93 
94  QVector<EGLint> configAttributes;
95 
96  configAttributes.append(EGL_RED_SIZE);
97  configAttributes.append(redSize);
98 
99  configAttributes.append(EGL_GREEN_SIZE);
100  configAttributes.append(greenSize);
101 
102  configAttributes.append(EGL_BLUE_SIZE);
103  configAttributes.append(blueSize);
104 
105  configAttributes.append(EGL_ALPHA_SIZE);
106  configAttributes.append(alphaSize);
107 
108  configAttributes.append(EGL_DEPTH_SIZE);
109  configAttributes.append(depthSize);
110 
111  configAttributes.append(EGL_STENCIL_SIZE);
112  configAttributes.append(stencilSize);
113 
114  configAttributes.append(EGL_SAMPLES);
115  configAttributes.append(sampleCount);
116 
117  configAttributes.append(EGL_SAMPLE_BUFFERS);
118  configAttributes.append(sampleCount? 1:0);
119 
120  return configAttributes;
121 }
122 
124 {
125  int i = -1;
126  // Reduce the complexity of a configuration request to ask for less
127  // because the previous request did not result in success. Returns
128  // true if the complexity was reduced, or false if no further
129  // reductions in complexity are possible.
130 
131  i = configAttributes->indexOf(EGL_SWAP_BEHAVIOR);
132  if (i >= 0) {
133  configAttributes->remove(i,2);
134  }
135 
136 #ifdef EGL_VG_ALPHA_FORMAT_PRE_BIT
137  // For OpenVG, we sometimes try to create a surface using a pre-multiplied format. If we can't
138  // find a config which supports pre-multiplied formats, remove the flag on the surface type:
139 
140  i = configAttributes->indexOf(EGL_SURFACE_TYPE);
141  if (i >= 0) {
142  EGLint surfaceType = configAttributes->at(i +1);
143  if (surfaceType & EGL_VG_ALPHA_FORMAT_PRE_BIT) {
144  surfaceType ^= EGL_VG_ALPHA_FORMAT_PRE_BIT;
145  configAttributes->replace(i+1,surfaceType);
146  return true;
147  }
148  }
149 #endif
150 
151  // EGL chooses configs with the highest color depth over
152  // those with smaller (but faster) lower color depths. One
153  // way around this is to set EGL_BUFFER_SIZE to 16, which
154  // trumps the others. Of course, there may not be a 16-bit
155  // config available, so it's the first restraint we remove.
156  i = configAttributes->indexOf(EGL_BUFFER_SIZE);
157  if (i >= 0) {
158  if (configAttributes->at(i+1) == 16) {
159  configAttributes->remove(i,2);
160  return true;
161  }
162  }
163 
164  i = configAttributes->indexOf(EGL_SAMPLE_BUFFERS);
165  if (i >= 0) {
166  configAttributes->remove(i,2);
167  i = configAttributes->indexOf(EGL_SAMPLES);
168  if (i >= 0) {
169  configAttributes->remove(i,2);
170  }
171  return true;
172  }
173 
174  i = configAttributes->indexOf(EGL_ALPHA_SIZE);
175  if (i >= 0) {
176  configAttributes->remove(i,2);
177 #if defined(EGL_BIND_TO_TEXTURE_RGBA) && defined(EGL_BIND_TO_TEXTURE_RGB)
178  i = configAttributes->indexOf(EGL_BIND_TO_TEXTURE_RGBA);
179  if (i >= 0) {
180  configAttributes->replace(i,EGL_BIND_TO_TEXTURE_RGB);
181  configAttributes->replace(i+1,TRUE);
182 
183  }
184 #endif
185  return true;
186  }
187 
188  i = configAttributes->indexOf(EGL_STENCIL_SIZE);
189  if (i >= 0) {
190  configAttributes->remove(i,2);
191  return true;
192  }
193  i = configAttributes->indexOf(EGL_DEPTH_SIZE);
194  if (i >= 0) {
195  configAttributes->remove(i,2);
196  return true;
197  }
198 #ifdef EGL_BIND_TO_TEXTURE_RGB
199  i = configAttributes->indexOf(EGL_BIND_TO_TEXTURE_RGB);
200  if (i >= 0) {
201  configAttributes->remove(i,2);
202  return true;
203  }
204 #endif
205 
206  return false;
207 }
208 
209 EGLConfig q_configFromQPlatformWindowFormat(EGLDisplay display, const QPlatformWindowFormat &format, bool highestPixelFormat, int surfaceType)
210 {
211  EGLConfig cfg = 0;
212  QVector<EGLint> configureAttributes = q_createConfigAttributesFromFormat(format);
213  configureAttributes.append(EGL_SURFACE_TYPE); //we only support eglconfigs for windows for now
214  configureAttributes.append(surfaceType);
215 
216  configureAttributes.append(EGL_RENDERABLE_TYPE);
217  if (format.windowApi() == QPlatformWindowFormat::OpenVG) {
218  configureAttributes.append(EGL_OPENVG_BIT);
219  } else {
220  configureAttributes.append(EGL_OPENGL_ES2_BIT);
221  }
222  configureAttributes.append(EGL_NONE);
223 
224  do {
225  // Get the number of matching configurations for this set of properties.
226  EGLint matching = 0;
227  if (!eglChooseConfig(display, configureAttributes.constData(), 0, 0, &matching) || !matching)
228  continue;
229 
230  // If we want the best pixel format, then return the first
231  // matching configuration.
232  if (highestPixelFormat) {
233  eglChooseConfig(display, configureAttributes.constData(), &cfg, 1, &matching);
234  if (matching < 1)
235  continue;
236  return cfg;
237  }
238 
239  // Fetch all of the matching configurations and find the
240  // first that matches the pixel format we wanted.
241  int i = configureAttributes.indexOf(EGL_RED_SIZE);
242  int confAttrRed = configureAttributes.at(i+1);
243  i = configureAttributes.indexOf(EGL_GREEN_SIZE);
244  int confAttrGreen = configureAttributes.at(i+1);
245  i = configureAttributes.indexOf(EGL_BLUE_SIZE);
246  int confAttrBlue = configureAttributes.at(i+1);
247  i = configureAttributes.indexOf(EGL_ALPHA_SIZE);
248  int confAttrAlpha = configureAttributes.at(i+1);
249 
250  EGLint size = matching;
251  EGLConfig *configs = new EGLConfig [size];
252  eglChooseConfig(display, configureAttributes.constData(), configs, size, &matching);
253  for (EGLint index = 0; index < size; ++index) {
254  EGLint red, green, blue, alpha;
255  eglGetConfigAttrib(display, configs[index], EGL_RED_SIZE, &red);
256  eglGetConfigAttrib(display, configs[index], EGL_GREEN_SIZE, &green);
257  eglGetConfigAttrib(display, configs[index], EGL_BLUE_SIZE, &blue);
258  eglGetConfigAttrib(display, configs[index], EGL_ALPHA_SIZE, &alpha);
259  if (red == confAttrRed &&
260  green == confAttrGreen &&
261  blue == confAttrBlue &&
262  (confAttrAlpha == 0 ||
263  alpha == confAttrAlpha)) {
264  cfg = configs[index];
265  delete [] configs;
266  return cfg;
267  }
268  }
269  delete [] configs;
270  } while (q_reduceConfigAttributes(&configureAttributes));
271  qWarning("Cant find EGLConfig, returning null config");
272  return 0;
273 }
274 
276 {
278  EGLint redSize = 0;
279  EGLint greenSize = 0;
280  EGLint blueSize = 0;
281  EGLint alphaSize = 0;
282  EGLint depthSize = 0;
283  EGLint stencilSize = 0;
284  EGLint sampleCount = 0;
285  EGLint level = 0;
286 
287  eglGetConfigAttrib(display, config, EGL_RED_SIZE, &redSize);
288  eglGetConfigAttrib(display, config, EGL_GREEN_SIZE, &greenSize);
289  eglGetConfigAttrib(display, config, EGL_BLUE_SIZE, &blueSize);
290  eglGetConfigAttrib(display, config, EGL_ALPHA_SIZE, &alphaSize);
291  eglGetConfigAttrib(display, config, EGL_DEPTH_SIZE, &depthSize);
292  eglGetConfigAttrib(display, config, EGL_STENCIL_SIZE, &stencilSize);
293  eglGetConfigAttrib(display, config, EGL_SAMPLES, &sampleCount);
294  eglGetConfigAttrib(display, config, EGL_LEVEL, &level);
295 
296  format.setRedBufferSize(redSize);
297  format.setGreenBufferSize(greenSize);
298  format.setBlueBufferSize(blueSize);
299  format.setAlphaBufferSize(alphaSize);
300  format.setDepthBufferSize(depthSize);
301  format.setStencilBufferSize(stencilSize);
302  format.setSamples(sampleCount);
303  format.setDirectRendering(true); // All EGL contexts are direct-rendered
304  format.setRgba(true); // EGL doesn't support colour index rendering
305  format.setStereo(false); // EGL doesn't support stereo buffers
306  format.setAccumBufferSize(0); // EGL doesn't support accululation buffers
307 
308  // Clear the EGL error state because some of the above may
309  // have errored out because the attribute is not applicable
310  // to the surface type. Such errors don't matter.
311  eglGetError();
312 
313  return format;
314 }
315 
316 bool q_hasEglExtension(EGLDisplay display, const char* extensionName)
317 {
319  QByteArray(reinterpret_cast<const char *>
320  (eglQueryString(display, EGL_EXTENSIONS))).split(' ');
321  return extensions.contains(extensionName);
322 }
323 
bool q_reduceConfigAttributes(QVector< EGLint > *configAttributes)
int greenBufferSize() const
Returns the green buffer size.
#define QT_END_NAMESPACE
This macro expands to.
Definition: qglobal.h:90
void replace(int i, const T &t)
Replaces the item at index position i with value.
Definition: qvector.h:382
void setDepthBufferSize(int size)
Set the minimum depth buffer size to size.
void remove(int i)
Removes the element at index position i.
Definition: qvector.h:374
void setStereo(bool enable)
If enable is true enables stereo buffering; otherwise disables stereo buffering.
void setDirectRendering(bool enable)
If enable is true enables direct rendering; otherwise disables direct rendering.
EGLConfig q_configFromQPlatformWindowFormat(EGLDisplay display, const QPlatformWindowFormat &format, bool highestPixelFormat, int surfaceType)
The QByteArray class provides an array of bytes.
Definition: qbytearray.h:135
int samples() const
Returns the number of samples per pixel when multisampling is enabled.
The QPlatformWindowFormat class specifies the display format of an OpenGL rendering context and if po...
void setBlueBufferSize(int size)
Set the preferred blue buffer size to size.
void setStencilBufferSize(int size)
Set the preferred stencil buffer size to size.
int stencilBufferSize() const
Returns the stencil buffer size.
Q_GUI_EXPORT QString extensions()
Definition: qegl.cpp:785
#define QT_BEGIN_NAMESPACE
This macro expands to.
Definition: qglobal.h:89
Q_GUI_EXPORT EGLDisplay display()
Definition: qegl.cpp:589
QBool contains(const T &t) const
Returns true if the list contains an occurrence of value; otherwise returns false.
Definition: qlist.h:880
void setAccumBufferSize(int size)
Set the preferred accumulation buffer size, where size is the bit depth for each RGBA component...
void setAlphaBufferSize(int size)
Set the preferred alpha buffer size to size.
void append(const T &t)
Inserts value at the end of the vector.
Definition: qvector.h:573
Q_CORE_EXPORT void qWarning(const char *,...)
int depthBufferSize() const
Returns the depth buffer size.
int alphaBufferSize() const
Returns the alpha buffer size.
void setSamples(int numSamples)
Set the preferred number of samples per pixel when multisampling is enabled to numSamples.
bool depth() const
Returns true if the depth buffer is enabled; otherwise returns false.
int indexOf(const T &t, int from=0) const
Returns the index position of the first occurrence of value in the vector, searching forward from ind...
Definition: qvector.h:698
void setRgba(bool enable)
If enable is true sets RGBA mode.
const T & at(int i) const
Returns the item at index position i in the vector.
Definition: qvector.h:350
#define TRUE
Synonym for true.
Definition: qglobal.h:1018
QList< QByteArray > split(char sep) const
Splits the byte array into subarrays wherever sep occurs, and returns the list of those arrays...
QVector< EGLint > q_createConfigAttributesFromFormat(const QPlatformWindowFormat &format)
QPlatformWindowFormat qt_qPlatformWindowFormatFromConfig(EGLDisplay display, const EGLConfig config)
bool stencil() const
Returns true if the stencil buffer is enabled; otherwise returns false.
int blueBufferSize() const
Returns the blue buffer size.
int redBufferSize() const
Returns the red buffer size.
void setRedBufferSize(int size)
Set the preferred red buffer size to size.
quint16 index
bool alpha() const
Returns true if the alpha buffer in the framebuffer is enabled; otherwise returns false...
const T * constData() const
Returns a const pointer to the data stored in the vector.
Definition: qvector.h:154
bool sampleBuffers() const
Returns true if multisample buffer support is enabled; otherwise returns false.
void setGreenBufferSize(int size)
Set the preferred green buffer size to size.
bool q_hasEglExtension(EGLDisplay display, const char *extensionName)