52 // If a background thread modifies the value, the worst that will |
52 // If a background thread modifies the value, the worst that will |
53 // happen is a redundant eglMakeCurrent() in the foreground thread. |
53 // happen is a redundant eglMakeCurrent() in the foreground thread. |
54 static QEglContext * volatile currentGLContext = 0; |
54 static QEglContext * volatile currentGLContext = 0; |
55 static QEglContext * volatile currentVGContext = 0; |
55 static QEglContext * volatile currentVGContext = 0; |
56 |
56 |
|
57 EGLDisplay QEglContext::dpy = EGL_NO_DISPLAY; |
|
58 |
57 QEglContext::QEglContext() |
59 QEglContext::QEglContext() |
58 : apiType(QEgl::OpenGL) |
60 : apiType(QEgl::OpenGL) |
59 , dpy(EGL_NO_DISPLAY) |
|
60 , ctx(EGL_NO_CONTEXT) |
61 , ctx(EGL_NO_CONTEXT) |
61 , cfg(0) |
62 , cfg(0) |
62 , currentSurface(EGL_NO_SURFACE) |
63 , currentSurface(EGL_NO_SURFACE) |
63 , current(false) |
64 , current(false) |
64 , ownsContext(true) |
65 , ownsContext(true) |
84 bool QEglContext::isCurrent() const |
85 bool QEglContext::isCurrent() const |
85 { |
86 { |
86 return current; |
87 return current; |
87 } |
88 } |
88 |
89 |
89 // Open the EGL display associated with "device". |
|
90 bool QEglContext::openDisplay(QPaintDevice *device) |
|
91 { |
|
92 if (dpy == EGL_NO_DISPLAY) |
|
93 dpy = defaultDisplay(device); |
|
94 return (dpy != EGL_NO_DISPLAY); |
|
95 } |
|
96 |
|
97 // Choose a configuration that matches "properties". |
90 // Choose a configuration that matches "properties". |
98 bool QEglContext::chooseConfig |
91 bool QEglContext::chooseConfig |
99 (const QEglProperties& properties, QEgl::PixelFormatMatch match) |
92 (const QEglProperties& properties, QEgl::PixelFormatMatch match) |
100 { |
93 { |
101 QEglProperties props(properties); |
94 QEglProperties props(properties); |
102 do { |
95 do { |
103 // Get the number of matching configurations for this set of properties. |
96 // Get the number of matching configurations for this set of properties. |
104 EGLint matching = 0; |
97 EGLint matching = 0; |
105 if (!eglChooseConfig(dpy, props.properties(), 0, 0, &matching) || !matching) |
98 if (!eglChooseConfig(display(), props.properties(), 0, 0, &matching) || !matching) |
106 continue; |
99 continue; |
107 |
100 |
108 // If we want the best pixel format, then return the first |
101 // If we want the best pixel format, then return the first |
109 // matching configuration. |
102 // matching configuration. |
110 if (match == QEgl::BestPixelFormat) { |
103 if (match == QEgl::BestPixelFormat) { |
111 eglChooseConfig(dpy, props.properties(), &cfg, 1, &matching); |
104 eglChooseConfig(display(), props.properties(), &cfg, 1, &matching); |
112 if (matching < 1) |
105 if (matching < 1) |
113 continue; |
106 continue; |
114 return true; |
107 return true; |
115 } |
108 } |
116 |
109 |
117 // Fetch all of the matching configurations and find the |
110 // Fetch all of the matching configurations and find the |
118 // first that matches the pixel format we wanted. |
111 // first that matches the pixel format we wanted. |
119 EGLint size = matching; |
112 EGLint size = matching; |
120 EGLConfig *configs = new EGLConfig [size]; |
113 EGLConfig *configs = new EGLConfig [size]; |
121 eglChooseConfig(dpy, props.properties(), configs, size, &matching); |
114 eglChooseConfig(display(), props.properties(), configs, size, &matching); |
122 for (EGLint index = 0; index < size; ++index) { |
115 for (EGLint index = 0; index < size; ++index) { |
123 EGLint red, green, blue, alpha; |
116 EGLint red, green, blue, alpha; |
124 eglGetConfigAttrib(dpy, configs[index], EGL_RED_SIZE, &red); |
117 eglGetConfigAttrib(display(), configs[index], EGL_RED_SIZE, &red); |
125 eglGetConfigAttrib(dpy, configs[index], EGL_GREEN_SIZE, &green); |
118 eglGetConfigAttrib(display(), configs[index], EGL_GREEN_SIZE, &green); |
126 eglGetConfigAttrib(dpy, configs[index], EGL_BLUE_SIZE, &blue); |
119 eglGetConfigAttrib(display(), configs[index], EGL_BLUE_SIZE, &blue); |
127 eglGetConfigAttrib(dpy, configs[index], EGL_ALPHA_SIZE, &alpha); |
120 eglGetConfigAttrib(display(), configs[index], EGL_ALPHA_SIZE, &alpha); |
128 if (red == props.value(EGL_RED_SIZE) && |
121 if (red == props.value(EGL_RED_SIZE) && |
129 green == props.value(EGL_GREEN_SIZE) && |
122 green == props.value(EGL_GREEN_SIZE) && |
130 blue == props.value(EGL_BLUE_SIZE) && |
123 blue == props.value(EGL_BLUE_SIZE) && |
131 (props.value(EGL_ALPHA_SIZE) == 0 || |
124 (props.value(EGL_ALPHA_SIZE) == 0 || |
132 alpha == props.value(EGL_ALPHA_SIZE))) { |
125 alpha == props.value(EGL_ALPHA_SIZE))) { |
177 #endif |
170 #endif |
178 sharing = false; |
171 sharing = false; |
179 if (shareContext && shareContext->ctx == EGL_NO_CONTEXT) |
172 if (shareContext && shareContext->ctx == EGL_NO_CONTEXT) |
180 shareContext = 0; |
173 shareContext = 0; |
181 if (shareContext) { |
174 if (shareContext) { |
182 ctx = eglCreateContext(dpy, cfg, shareContext->ctx, contextProps.properties()); |
175 ctx = eglCreateContext(display(), cfg, shareContext->ctx, contextProps.properties()); |
183 if (ctx == EGL_NO_CONTEXT) { |
176 if (ctx == EGL_NO_CONTEXT) { |
184 qWarning() << "QEglContext::createContext(): Could not share context:" << errorString(eglGetError()); |
177 qWarning() << "QEglContext::createContext(): Could not share context:" << errorString(eglGetError()); |
185 shareContext = 0; |
178 shareContext = 0; |
186 } else { |
179 } else { |
187 sharing = true; |
180 sharing = true; |
188 } |
181 } |
189 } |
182 } |
190 if (ctx == EGL_NO_CONTEXT) { |
183 if (ctx == EGL_NO_CONTEXT) { |
191 ctx = eglCreateContext(dpy, cfg, 0, contextProps.properties()); |
184 ctx = eglCreateContext(display(), cfg, 0, contextProps.properties()); |
192 if (ctx == EGL_NO_CONTEXT) { |
185 if (ctx == EGL_NO_CONTEXT) { |
193 qWarning() << "QEglContext::createContext(): Unable to create EGL context:" << errorString(eglGetError()); |
186 qWarning() << "QEglContext::createContext(): Unable to create EGL context:" << errorString(eglGetError()); |
194 return false; |
187 return false; |
195 } |
188 } |
196 } |
189 } |
202 void QEglContext::destroySurface(EGLSurface surface) |
195 void QEglContext::destroySurface(EGLSurface surface) |
203 { |
196 { |
204 if (surface != EGL_NO_SURFACE) { |
197 if (surface != EGL_NO_SURFACE) { |
205 if (surface == currentSurface) |
198 if (surface == currentSurface) |
206 doneCurrent(); |
199 doneCurrent(); |
207 eglDestroySurface(dpy, surface); |
200 eglDestroySurface(display(), surface); |
208 } |
201 } |
209 } |
202 } |
210 |
203 |
211 // Destroy the context. Note: this does not destroy the surface. |
204 // Destroy the context. Note: this does not destroy the surface. |
212 void QEglContext::destroy() |
205 void QEglContext::destroyContext() |
213 { |
206 { |
214 if (ctx != EGL_NO_CONTEXT && ownsContext) |
207 if (ctx != EGL_NO_CONTEXT && ownsContext) |
215 eglDestroyContext(dpy, ctx); |
208 eglDestroyContext(display(), ctx); |
216 dpy = EGL_NO_DISPLAY; |
|
217 ctx = EGL_NO_CONTEXT; |
209 ctx = EGL_NO_CONTEXT; |
218 cfg = 0; |
210 cfg = 0; |
219 } |
211 } |
220 |
212 |
221 bool QEglContext::makeCurrent(EGLSurface surface) |
213 bool QEglContext::makeCurrent(EGLSurface surface) |
348 if (!cfg) |
340 if (!cfg) |
349 cfg = config(); |
341 cfg = config(); |
350 QEglProperties props; |
342 QEglProperties props; |
351 for (int name = 0x3020; name <= 0x304F; ++name) { |
343 for (int name = 0x3020; name <= 0x304F; ++name) { |
352 EGLint value; |
344 EGLint value; |
353 if (name != EGL_NONE && eglGetConfigAttrib(dpy, cfg, name, &value)) |
345 if (name != EGL_NONE && eglGetConfigAttrib(display(), cfg, name, &value)) |
354 props.setValue(name, value); |
346 props.setValue(name, value); |
355 } |
347 } |
356 eglGetError(); // Clear the error state. |
348 eglGetError(); // Clear the error state. |
357 return props; |
349 return props; |
358 } |
350 } |
359 |
351 |
360 // Initialize and return the default display. |
352 EGLDisplay QEglContext::display() |
361 EGLDisplay QEglContext::defaultDisplay(QPaintDevice *device) |
353 { |
362 { |
354 static bool openedDisplay = false; |
363 static EGLDisplay dpy = EGL_NO_DISPLAY; |
355 |
364 if (dpy == EGL_NO_DISPLAY) { |
356 if (!openedDisplay) { |
365 dpy = getDisplay(device); |
357 dpy = eglGetDisplay(nativeDisplay()); |
|
358 openedDisplay = true; |
366 if (dpy == EGL_NO_DISPLAY) { |
359 if (dpy == EGL_NO_DISPLAY) { |
367 qWarning() << "QEglContext::defaultDisplay(): Cannot open EGL display"; |
360 qWarning("QEglContext::display(): Falling back to EGL_DEFAULT_DISPLAY"); |
|
361 dpy = eglGetDisplay(EGLNativeDisplayType(EGL_DEFAULT_DISPLAY)); |
|
362 } |
|
363 if (dpy == EGL_NO_DISPLAY) { |
|
364 qWarning("QEglContext::display(): Can't even open the default display"); |
368 return EGL_NO_DISPLAY; |
365 return EGL_NO_DISPLAY; |
369 } |
366 } |
|
367 |
370 if (!eglInitialize(dpy, NULL, NULL)) { |
368 if (!eglInitialize(dpy, NULL, NULL)) { |
371 qWarning() << "QEglContext::defaultDisplay(): Cannot initialize EGL display:" << errorString(eglGetError()); |
369 qWarning() << "QEglContext::display(): Cannot initialize EGL display:" << errorString(eglGetError()); |
372 return EGL_NO_DISPLAY; |
370 return EGL_NO_DISPLAY; |
373 } |
371 } |
374 #ifdef EGL_OPENGL_ES_API |
372 } |
375 eglBindAPI(EGL_OPENGL_ES_API); |
373 |
376 #endif |
|
377 } |
|
378 return dpy; |
374 return dpy; |
379 } |
375 } |
|
376 |
|
377 #if !defined(Q_WS_X11) && !defined(Q_WS_WINCE) // WinCE & X11 implement this properly |
|
378 EGLNativeDisplayType QEglContext::nativeDisplay() |
|
379 { |
|
380 return EGL_DEFAULT_DISPLAY; |
|
381 } |
|
382 #endif |
380 |
383 |
381 // Return the error string associated with a specific code. |
384 // Return the error string associated with a specific code. |
382 QString QEglContext::errorString(EGLint code) |
385 QString QEglContext::errorString(EGLint code) |
383 { |
386 { |
384 static const char * const errors[] = { |
387 static const char * const errors[] = { |
408 // Dump all of the EGL configurations supported by the system. |
411 // Dump all of the EGL configurations supported by the system. |
409 void QEglContext::dumpAllConfigs() |
412 void QEglContext::dumpAllConfigs() |
410 { |
413 { |
411 QEglProperties props; |
414 QEglProperties props; |
412 EGLint count = 0; |
415 EGLint count = 0; |
413 if (!eglGetConfigs(dpy, 0, 0, &count) || count < 1) |
416 if (!eglGetConfigs(display(), 0, 0, &count) || count < 1) |
414 return; |
417 return; |
415 EGLConfig *configs = new EGLConfig [count]; |
418 EGLConfig *configs = new EGLConfig [count]; |
416 eglGetConfigs(dpy, configs, count, &count); |
419 eglGetConfigs(display(), configs, count, &count); |
417 for (EGLint index = 0; index < count; ++index) { |
420 for (EGLint index = 0; index < count; ++index) { |
418 props = configProperties(configs[index]); |
421 props = configProperties(configs[index]); |
419 qWarning() << props.toString(); |
422 qWarning() << props.toString(); |
420 } |
423 } |
421 delete [] configs; |
424 delete [] configs; |
422 } |
425 } |
423 |
426 |
424 QString QEglContext::extensions() |
427 QString QEglContext::extensions() |
425 { |
428 { |
426 const char* exts = eglQueryString(QEglContext::defaultDisplay(0), EGL_EXTENSIONS); |
429 const char* exts = eglQueryString(QEglContext::display(), EGL_EXTENSIONS); |
427 return QString(QLatin1String(exts)); |
430 return QString(QLatin1String(exts)); |
428 } |
431 } |
429 |
432 |
430 bool QEglContext::hasExtension(const char* extensionName) |
433 bool QEglContext::hasExtension(const char* extensionName) |
431 { |
434 { |
432 QList<QByteArray> extensions = |
435 QList<QByteArray> extensions = |
433 QByteArray(reinterpret_cast<const char *> |
436 QByteArray(reinterpret_cast<const char *> |
434 (eglQueryString(QEglContext::defaultDisplay(0), EGL_EXTENSIONS))).split(' '); |
437 (eglQueryString(QEglContext::display(), EGL_EXTENSIONS))).split(' '); |
435 return extensions.contains(extensionName); |
438 return extensions.contains(extensionName); |
436 } |
439 } |
437 |
440 |
438 QEglContext *QEglContext::currentContext(QEgl::API api) |
441 QEglContext *QEglContext::currentContext(QEgl::API api) |
439 { |
442 { |