Qt 4.8
qbbglcontext.cpp
Go to the documentation of this file.
1 /****************************************************************************
2 **
3 ** Copyright (C) 2011 - 2012 Research In Motion <blackberry-qt@qnx.com>
4 ** Contact: http://www.qt-project.org/legal
5 **
6 ** This file is part of the QtCore module 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 //#define QBBGLCONTEXT_DEBUG
43 
44 
45 #include "qbbglcontext.h"
46 #include "qbbscreen.h"
47 #include "qbbwindow.h"
48 #include "../eglconvenience/qeglconvenience.h"
49 
50 #include <QtGui/QWidget>
51 #include <QDebug>
52 
54 
55 EGLDisplay QBBGLContext::sEglDisplay = EGL_NO_DISPLAY;
56 
59  mPlatformWindow(platformWindow),
60  mEglSurface(EGL_NO_SURFACE)
61 {
62 #if defined(QBBGLCONTEXT_DEBUG)
63  qDebug() << "QBBGLContext::QBBGLContext - w=" << mPlatformWindow->widget();
64 #endif
65 
66  // verify rendering API is correct
67  QPlatformWindowFormat format = mPlatformWindow->widget()->platformWindowFormat();
68  if (format.windowApi() != QPlatformWindowFormat::OpenGL) {
69  qFatal("QBB: window API is not OpenGL");
70  }
71 
72  // set current rendering API
73  EGLBoolean eglResult = eglBindAPI(EGL_OPENGL_ES_API);
74  if (eglResult != EGL_TRUE) {
75  qFatal("QBB: failed to set EGL API, err=%d", eglGetError());
76  }
77 
78  // get colour channel sizes from window format
79  int alphaSize = format.alphaBufferSize();
80  int redSize = format.redBufferSize();
81  int greenSize = format.greenBufferSize();
82  int blueSize = format.blueBufferSize();
83 
84  // check if all channels are don't care
85  if (alphaSize == -1 && redSize == -1 && greenSize == -1 && blueSize == -1) {
86 
87  // set colour channels based on depth of window's screen
88  int depth = platformWindow->screen()->depth();
89  if (depth == 32) {
90  // SCREEN_FORMAT_RGBA8888
91  alphaSize = 8;
92  redSize = 8;
93  greenSize = 8;
94  blueSize = 8;
95  } else {
96  // SCREEN_FORMAT_RGB565
97  alphaSize = 0;
98  redSize = 5;
99  greenSize = 6;
100  blueSize = 5;
101  }
102 
103  } else {
104 
105  // choose best match based on supported pixel formats
106  if (alphaSize <= 0 && redSize <= 5 && greenSize <= 6 && blueSize <= 5) {
107  // SCREEN_FORMAT_RGB565
108  alphaSize = 0;
109  redSize = 5;
110  greenSize = 6;
111  blueSize = 5;
112  } else {
113  // SCREEN_FORMAT_RGBA8888
114  alphaSize = 8;
115  redSize = 8;
116  greenSize = 8;
117  blueSize = 8;
118  }
119  }
120 
121  // update colour channel sizes in window format
122  format.setAlphaBufferSize(alphaSize);
123  format.setRedBufferSize(redSize);
124  format.setGreenBufferSize(greenSize);
125  format.setBlueBufferSize(blueSize);
126 
127  // select EGL config based on requested window format
129  if (mEglConfig == 0) {
130  qFatal("QBB: failed to find EGL config");
131  }
132 
133  mEglContext = eglCreateContext(sEglDisplay, mEglConfig, EGL_NO_CONTEXT, contextAttrs());
134  if (mEglContext == EGL_NO_CONTEXT) {
135  qFatal("QBB: failed to create EGL context, err=%d", eglGetError());
136  }
137 
138  // query/cache window format of selected EGL config
140 }
141 
143 {
144 #if defined(QBBGLCONTEXT_DEBUG)
145  qDebug() << "QBBGLContext::~QBBGLContext - w=" << mPlatformWindow->widget();
146 #endif
147 
148  // cleanup EGL context if it exists
149  if (mEglContext != EGL_NO_CONTEXT) {
150  eglDestroyContext(sEglDisplay, mEglContext);
151  }
152 
153  // cleanup EGL surface if it exists
154  destroySurface();
155 }
156 
158 {
159  // initialize connection to EGL
160  sEglDisplay = eglGetDisplay(EGL_DEFAULT_DISPLAY);
161  if (sEglDisplay == EGL_NO_DISPLAY) {
162  qFatal("QBB: failed to obtain EGL display");
163  }
164 
165  EGLBoolean eglResult = eglInitialize(sEglDisplay, NULL, NULL);
166  if (eglResult != EGL_TRUE) {
167  qFatal("QBB: failed to initialize EGL display, err=%d", eglGetError());
168  }
169 
170  // choose EGL settings based on OpenGL version
171 #if defined(QT_OPENGL_ES_2)
172  EGLint renderableType = EGL_OPENGL_ES2_BIT;
173 #else
174  EGLint renderableType = EGL_OPENGL_ES_BIT;
175 #endif
176 }
177 
179 {
180  // close connection to EGL
181  eglTerminate(sEglDisplay);
182 }
183 
185 {
186 #if defined(QBBGLCONTEXT_DEBUG)
187  qDebug() << "QBBGLContext::makeCurrent - w=" << mPlatformWindow->widget();
188 #endif
189 
190  if (!mPlatformWindow->hasBuffers()) {
191  // NOTE: create a dummy EGL surface since Qt will call makeCurrent() before
192  // setting the geometry on the associated window
193  mSurfaceSize = QSize(1, 1);
195  createSurface();
196  }
197 
198  // call the parent method
200 
201  // set current rendering API
202  EGLBoolean eglResult = eglBindAPI(EGL_OPENGL_ES_API);
203  if (eglResult != EGL_TRUE) {
204  qFatal("QBB: failed to set EGL API, err=%d", eglGetError());
205  }
206 
207  // set current EGL context and bind with EGL surface
208  eglResult = eglMakeCurrent(sEglDisplay, mEglSurface, mEglSurface, mEglContext);
209  if (eglResult != EGL_TRUE) {
210  qFatal("QBB: failed to set current EGL context, err=%d", eglGetError());
211  }
212 }
213 
215 {
216 #if defined(QBBGLCONTEXT_DEBUG)
217  qDebug() << "QBBGLContext::doneCurrent - w=" << mPlatformWindow->widget();
218 #endif
219 
220  // call the parent method
222 
223  // set current rendering API
224  EGLBoolean eglResult = eglBindAPI(EGL_OPENGL_ES_API);
225  if (eglResult != EGL_TRUE) {
226  qFatal("QBB: failed to set EGL API, err=%d", eglGetError());
227  }
228 
229  // clear curent EGL context and unbind EGL surface
230  eglResult = eglMakeCurrent(sEglDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
231  if (eglResult != EGL_TRUE) {
232  qFatal("QBB: failed to clear current EGL context, err=%d", eglGetError());
233  }
234 }
235 
237 {
238 #if defined(QBBGLCONTEXT_DEBUG)
239  qDebug() << "QBBGLContext::swapBuffers - w=" << mPlatformWindow->widget();
240 #endif
241 
242  // set current rendering API
243  EGLBoolean eglResult = eglBindAPI(EGL_OPENGL_ES_API);
244  if (eglResult != EGL_TRUE) {
245  qFatal("QBB: failed to set EGL API, err=%d", eglGetError());
246  }
247 
248  // post EGL surface to window
249  eglResult = eglSwapBuffers(sEglDisplay, mEglSurface);
250  if (eglResult != EGL_TRUE) {
251  qFatal("QBB: failed to swap EGL buffers, err=%d", eglGetError());
252  }
253 
254  // resize surface if window was resized
256  if (s != mSurfaceSize) {
257  resizeSurface(s);
258  }
259 }
260 
261 void* QBBGLContext::getProcAddress(const QString& procName)
262 {
263 #if defined(QBBGLCONTEXT_DEBUG)
264  qDebug() << "QBBGLContext::getProcAddress - w=" << mPlatformWindow->widget();
265 #endif
266 
267  // set current rendering API
268  EGLBoolean eglResult = eglBindAPI(EGL_OPENGL_ES_API);
269  if (eglResult != EGL_TRUE) {
270  qFatal("QBB: failed to set EGL API, err=%d", eglGetError());
271  }
272 
273  // lookup EGL extension function pointer
274  return (void *)eglGetProcAddress( procName.toAscii().constData() );
275 }
276 
278 {
279  // need to destroy surface so make sure its not current
280  bool restoreCurrent = false;
281  if (isCurrent()) {
282  doneCurrent();
283  restoreCurrent = true;
284  }
285 
286  // destroy old EGL surface
287  destroySurface();
288 
289  // resize window's buffers
291 
292  // re-create EGL surface with new size
293  mSurfaceSize = size;
294  createSurface();
295 
296  // make context current again
297  if (restoreCurrent) {
298  makeCurrent();
300  }
301 }
302 
304 {
305  // choose EGL settings based on OpenGL version
306 #if defined(QT_OPENGL_ES_2)
307  static EGLint attrs[] = { EGL_CONTEXT_CLIENT_VERSION, 2, EGL_NONE };
308  return attrs;
309 #else
310  return NULL;
311 #endif
312 }
313 
315 {
316  return (eglGetCurrentContext() == mEglContext);
317 }
318 
320 {
321 #if defined(QBBGLCONTEXT_DEBUG)
322  qDebug() << "QBBGLContext::createSurface - w=" << mPlatformWindow->widget();
323 #endif
324 
325  // create EGL surface
326  mEglSurface = eglCreateWindowSurface(sEglDisplay, mEglConfig, (EGLNativeWindowType)mPlatformWindow->winId(), NULL);
327  if (mEglSurface == EGL_NO_SURFACE) {
328  qFatal("QBB: failed to create EGL surface, err=%d", eglGetError());
329  }
330 }
331 
333 {
334 #if defined(QBBGLCONTEXT_DEBUG)
335  qDebug() << "QBBGLContext::destroySurface - w=" << mPlatformWindow->widget();
336 #endif
337 
338  // destroy EGL surface if it exists
339  if (mEglSurface != EGL_NO_SURFACE) {
340  EGLBoolean eglResult = eglDestroySurface(sEglDisplay, mEglSurface);
341  if (eglResult != EGL_TRUE) {
342  qFatal("QBB: failed to destroy EGL surface, err=%d", eglGetError());
343  }
344  }
345 }
346 
bool hasBuffers() const
Definition: qbbwindow.h:74
virtual void swapBuffers()
Reimplement in subclass to native swap buffers calls.
virtual void makeCurrent()
Reimplement in subclass to do makeCurrent on native GL context.
int greenBufferSize() const
Returns the green buffer size.
#define QT_END_NAMESPACE
This macro expands to.
Definition: qglobal.h:90
virtual QRect geometry() const
Returnes the current geometry of a window.
EGLConfig q_configFromQPlatformWindowFormat(EGLDisplay display, const QPlatformWindowFormat &format, bool highestPixelFormat, int surfaceType)
virtual void doneCurrent()
Reimplement in subclass to release current context.
The QPlatformWindowFormat class specifies the display format of an OpenGL rendering context and if po...
void setBufferSize(const QSize &size)
Definition: qbbwindow.cpp:288
void setBlueBufferSize(int size)
Set the preferred blue buffer size to size.
virtual void * getProcAddress(const QString &procName)
Reimplement in subclass to native getProcAddr calls.
The QString class provides a Unicode character string.
Definition: qstring.h:83
NativeWindowType EGLNativeWindowType
Definition: qegl_p.h:116
virtual ~QBBGLContext()
void update()
Updates the widget unless updates are disabled or the widget is hidden.
Definition: qwidget.cpp:10883
Q_CORE_EXPORT void qDebug(const char *,...)
#define QT_BEGIN_NAMESPACE
This macro expands to.
Definition: qglobal.h:89
static void initialize()
QBBScreen * screen() const
Definition: qbbwindow.h:93
void setAlphaBufferSize(int size)
Set the preferred alpha buffer size to size.
void resizeSurface(const QSize &size)
QSize size() const
Returns the size of the rectangle.
Definition: qrect.h:309
QBBWindow * mPlatformWindow
Definition: qbbglcontext.h:79
EGLConfig mEglConfig
Definition: qbbglcontext.h:78
virtual int depth() const
Reimplement in subclass to return current depth of the screen.
Definition: qbbscreen.cpp:216
int alphaBufferSize() const
Returns the alpha buffer size.
EGLContext mEglContext
Definition: qbbglcontext.h:80
QBBGLContext(QBBWindow *platformWindow)
virtual void makeCurrent()
Reimplement in subclass to do makeCurrent on native GL context.
static EGLint * contextAttrs()
EGLSurface mEglSurface
Definition: qbbglcontext.h:81
bool isCurrent() const
const char * constData() const
Returns a pointer to the data stored in the byte array.
Definition: qbytearray.h:433
Q_CORE_EXPORT void qFatal(const char *,...)
The QPlatformGLContext class provides an abstraction for native GL contexts.
virtual WId winId() const
Reimplement in subclasses to return a handle to the native window.
Definition: qbbwindow.h:70
void destroySurface()
QPlatformWindowFormat qt_qPlatformWindowFormatFromConfig(EGLDisplay display, const EGLConfig config)
QByteArray toAscii() const Q_REQUIRED_RESULT
Returns an 8-bit representation of the string as a QByteArray.
Definition: qstring.cpp:4014
int blueBufferSize() const
Returns the blue buffer size.
QPlatformWindowFormat mWindowFormat
Definition: qbbglcontext.h:77
int redBufferSize() const
Returns the red buffer size.
void setRedBufferSize(int size)
Set the preferred red buffer size to size.
static void shutdown()
void createSurface()
QSize mSurfaceSize
Definition: qbbglcontext.h:82
The QSize class defines the size of a two-dimensional object using integer point precision.
Definition: qsize.h:53
virtual void doneCurrent()
Reimplement in subclass to release current context.
static EGLDisplay sEglDisplay
Definition: qbbglcontext.h:75
void setGreenBufferSize(int size)
Set the preferred green buffer size to size.
QWidget * widget() const
Returnes the widget which belongs to the QPlatformWindow.