41 |
41 |
42 #include <QtGui/qpaintdevice.h> |
42 #include <QtGui/qpaintdevice.h> |
43 #include <QtGui/qpixmap.h> |
43 #include <QtGui/qpixmap.h> |
44 #include <QtGui/qwidget.h> |
44 #include <QtGui/qwidget.h> |
45 #include <QtCore/qdebug.h> |
45 #include <QtCore/qdebug.h> |
|
46 |
46 #include "qegl_p.h" |
47 #include "qegl_p.h" |
|
48 #include "qeglcontext_p.h" |
|
49 |
47 |
50 |
48 QT_BEGIN_NAMESPACE |
51 QT_BEGIN_NAMESPACE |
49 |
52 |
50 // Current GL and VG contexts. These are used to determine if |
53 // Current GL and VG contexts. These are used to determine if |
51 // we can avoid an eglMakeCurrent() after a call to lazyDoneCurrent(). |
54 // we can avoid an eglMakeCurrent() after a call to lazyDoneCurrent(). |
52 // If a background thread modifies the value, the worst that will |
55 // If a background thread modifies the value, the worst that will |
53 // happen is a redundant eglMakeCurrent() in the foreground thread. |
56 // happen is a redundant eglMakeCurrent() in the foreground thread. |
54 static QEglContext * volatile currentGLContext = 0; |
57 static QEglContext * volatile currentGLContext = 0; |
55 static QEglContext * volatile currentVGContext = 0; |
58 static QEglContext * volatile currentVGContext = 0; |
56 |
59 |
57 EGLDisplay QEglContext::dpy = EGL_NO_DISPLAY; |
|
58 |
|
59 QEglContext::QEglContext() |
60 QEglContext::QEglContext() |
60 : apiType(QEgl::OpenGL) |
61 : apiType(QEgl::OpenGL) |
61 , ctx(EGL_NO_CONTEXT) |
62 , ctx(EGL_NO_CONTEXT) |
62 , cfg(0) |
63 , cfg(QEGL_NO_CONFIG) |
63 , currentSurface(EGL_NO_SURFACE) |
64 , currentSurface(EGL_NO_SURFACE) |
64 , current(false) |
65 , current(false) |
65 , ownsContext(true) |
66 , ownsContext(true) |
66 , sharing(false) |
67 , sharing(false) |
67 { |
68 { |
85 bool QEglContext::isCurrent() const |
86 bool QEglContext::isCurrent() const |
86 { |
87 { |
87 return current; |
88 return current; |
88 } |
89 } |
89 |
90 |
|
91 EGLConfig QEgl::defaultConfig(int devType, API api, ConfigOptions options) |
|
92 { |
|
93 if ( (devType != QInternal::Pixmap) && ((options & Renderable) == 0)) |
|
94 qWarning("QEgl::defaultConfig() - Only configs for pixmaps make sense to be read-only!"); |
|
95 |
|
96 EGLConfig* targetConfig = 0; |
|
97 |
|
98 static EGLConfig defaultVGConfigs[] = { |
|
99 QEGL_NO_CONFIG, // 0 Window Renderable Translucent |
|
100 QEGL_NO_CONFIG, // 1 Window Renderable Opaque |
|
101 QEGL_NO_CONFIG, // 2 Pixmap Renderable Translucent |
|
102 QEGL_NO_CONFIG, // 3 Pixmap Renderable Opaque |
|
103 QEGL_NO_CONFIG, // 4 Pixmap ReadOnly Translucent |
|
104 QEGL_NO_CONFIG // 5 Pixmap ReadOnly Opaque |
|
105 }; |
|
106 if (api == OpenVG) { |
|
107 if (devType == QInternal::Widget) { |
|
108 if (options & Translucent) |
|
109 targetConfig = &(defaultVGConfigs[0]); |
|
110 else |
|
111 targetConfig = &(defaultVGConfigs[1]); |
|
112 } else if (devType == QInternal::Pixmap) { |
|
113 if (options & Renderable) { |
|
114 if (options & Translucent) |
|
115 targetConfig = &(defaultVGConfigs[2]); |
|
116 else // Opaque |
|
117 targetConfig = &(defaultVGConfigs[3]); |
|
118 } else { // Read-only |
|
119 if (options & Translucent) |
|
120 targetConfig = &(defaultVGConfigs[4]); |
|
121 else // Opaque |
|
122 targetConfig = &(defaultVGConfigs[5]); |
|
123 } |
|
124 } |
|
125 } |
|
126 |
|
127 |
|
128 static EGLConfig defaultGLConfigs[] = { |
|
129 QEGL_NO_CONFIG, // 0 Window Renderable Translucent |
|
130 QEGL_NO_CONFIG, // 1 Window Renderable Opaque |
|
131 QEGL_NO_CONFIG, // 2 PBuffer Renderable Translucent |
|
132 QEGL_NO_CONFIG, // 3 PBuffer Renderable Opaque |
|
133 QEGL_NO_CONFIG, // 4 Pixmap Renderable Translucent |
|
134 QEGL_NO_CONFIG, // 5 Pixmap Renderable Opaque |
|
135 QEGL_NO_CONFIG, // 6 Pixmap ReadOnly Translucent |
|
136 QEGL_NO_CONFIG // 7 Pixmap ReadOnly Opaque |
|
137 }; |
|
138 if (api == OpenGL) { |
|
139 if (devType == QInternal::Widget) { |
|
140 if (options & Translucent) |
|
141 targetConfig = &(defaultGLConfigs[0]); |
|
142 else // Opaque |
|
143 targetConfig = &(defaultGLConfigs[1]); |
|
144 } else if (devType == QInternal::Pbuffer) { |
|
145 if (options & Translucent) |
|
146 targetConfig = &(defaultGLConfigs[2]); |
|
147 else // Opaque |
|
148 targetConfig = &(defaultGLConfigs[3]); |
|
149 } else if (devType == QInternal::Pixmap) { |
|
150 if (options & Renderable) { |
|
151 if (options & Translucent) |
|
152 targetConfig = &(defaultGLConfigs[4]); |
|
153 else // Opaque |
|
154 targetConfig = &(defaultGLConfigs[5]); |
|
155 } else { // ReadOnly |
|
156 if (options & Translucent) |
|
157 targetConfig = &(defaultGLConfigs[6]); |
|
158 else // Opaque |
|
159 targetConfig = &(defaultGLConfigs[7]); |
|
160 } |
|
161 } |
|
162 } |
|
163 |
|
164 if (!targetConfig) { |
|
165 qWarning("QEgl::defaultConfig() - No default config for device/api/options combo"); |
|
166 return QEGL_NO_CONFIG; |
|
167 } |
|
168 if (*targetConfig != QEGL_NO_CONFIG) |
|
169 return *targetConfig; |
|
170 |
|
171 |
|
172 // We haven't found an EGL config for the target config yet, so do it now: |
|
173 |
|
174 |
|
175 // Allow overriding from an environment variable: |
|
176 QByteArray configId; |
|
177 if (api == OpenVG) |
|
178 configId = qgetenv("QT_VG_EGL_CONFIG"); |
|
179 else |
|
180 configId = qgetenv("QT_GL_EGL_CONFIG"); |
|
181 if (!configId.isEmpty()) { |
|
182 // Overriden, so get the EGLConfig for the specified config ID: |
|
183 EGLint properties[] = { |
|
184 EGL_CONFIG_ID, (EGLint)configId.toInt(), |
|
185 EGL_NONE |
|
186 }; |
|
187 EGLint configCount = 0; |
|
188 eglChooseConfig(display(), properties, targetConfig, 1, &configCount); |
|
189 if (configCount > 0) |
|
190 return *targetConfig; |
|
191 qWarning() << "QEgl::defaultConfig() -" << configId << "appears to be invalid"; |
|
192 } |
|
193 |
|
194 QEglProperties configAttribs; |
|
195 configAttribs.setRenderableType(api); |
|
196 |
|
197 EGLint surfaceType; |
|
198 switch (devType) { |
|
199 case QInternal::Widget: |
|
200 surfaceType = EGL_WINDOW_BIT; |
|
201 break; |
|
202 case QInternal::Pixmap: |
|
203 surfaceType = EGL_PIXMAP_BIT; |
|
204 break; |
|
205 case QInternal::Pbuffer: |
|
206 surfaceType = EGL_PBUFFER_BIT; |
|
207 break; |
|
208 default: |
|
209 qWarning("QEgl::defaultConfig() - Can't create EGL surface for %d device type", devType); |
|
210 return QEGL_NO_CONFIG; |
|
211 }; |
|
212 #ifdef EGL_VG_ALPHA_FORMAT_PRE_BIT |
|
213 // For OpenVG, we try to create a surface using a pre-multiplied format if |
|
214 // the surface needs to have an alpha channel: |
|
215 if (api == OpenVG && (options & Translucent)) |
|
216 surfaceType |= EGL_VG_ALPHA_FORMAT_PRE_BIT; |
|
217 #endif |
|
218 configAttribs.setValue(EGL_SURFACE_TYPE, surfaceType); |
|
219 |
|
220 #ifdef EGL_BIND_TO_TEXTURE_RGBA |
|
221 if (devType == QInternal::Pixmap || devType == QInternal::Pbuffer) { |
|
222 if (options & Translucent) |
|
223 configAttribs.setValue(EGL_BIND_TO_TEXTURE_RGBA, EGL_TRUE); |
|
224 else |
|
225 configAttribs.setValue(EGL_BIND_TO_TEXTURE_RGB, EGL_TRUE); |
|
226 } |
|
227 #endif |
|
228 |
|
229 // Add paint engine requirements |
|
230 if (api == OpenVG) { |
|
231 #ifndef QVG_SCISSOR_CLIP |
|
232 configAttribs.setValue(EGL_ALPHA_MASK_SIZE, 1); |
|
233 #endif |
|
234 } else { |
|
235 // Both OpenGL paint engines need to have stencil and sample buffers |
|
236 configAttribs.setValue(EGL_STENCIL_SIZE, 1); |
|
237 configAttribs.setValue(EGL_SAMPLE_BUFFERS, 1); |
|
238 #ifndef QT_OPENGL_ES_2 |
|
239 // Aditionally, the GL1 engine likes to have a depth buffer for clipping |
|
240 configAttribs.setValue(EGL_DEPTH_SIZE, 1); |
|
241 #endif |
|
242 } |
|
243 |
|
244 if (options & Translucent) |
|
245 configAttribs.setValue(EGL_ALPHA_SIZE, 1); |
|
246 |
|
247 *targetConfig = chooseConfig(&configAttribs, QEgl::BestPixelFormat); |
|
248 return *targetConfig; |
|
249 } |
|
250 |
|
251 |
90 // Choose a configuration that matches "properties". |
252 // Choose a configuration that matches "properties". |
91 bool QEglContext::chooseConfig |
253 EGLConfig QEgl::chooseConfig(const QEglProperties* properties, QEgl::PixelFormatMatch match) |
92 (const QEglProperties& properties, QEgl::PixelFormatMatch match) |
254 { |
93 { |
255 QEglProperties props(*properties); |
94 QEglProperties props(properties); |
256 EGLConfig cfg = QEGL_NO_CONFIG; |
95 do { |
257 do { |
96 // Get the number of matching configurations for this set of properties. |
258 // Get the number of matching configurations for this set of properties. |
97 EGLint matching = 0; |
259 EGLint matching = 0; |
98 if (!eglChooseConfig(display(), props.properties(), 0, 0, &matching) || !matching) |
260 EGLDisplay dpy = QEgl::display(); |
|
261 if (!eglChooseConfig(dpy, props.properties(), 0, 0, &matching) || !matching) |
99 continue; |
262 continue; |
100 |
263 |
101 // If we want the best pixel format, then return the first |
264 // If we want the best pixel format, then return the first |
102 // matching configuration. |
265 // matching configuration. |
103 if (match == QEgl::BestPixelFormat) { |
266 if (match == QEgl::BestPixelFormat) { |
104 eglChooseConfig(display(), props.properties(), &cfg, 1, &matching); |
267 eglChooseConfig(display(), props.properties(), &cfg, 1, &matching); |
105 if (matching < 1) |
268 if (matching < 1) |
106 continue; |
269 continue; |
107 return true; |
270 return cfg; |
108 } |
271 } |
109 |
272 |
110 // Fetch all of the matching configurations and find the |
273 // Fetch all of the matching configurations and find the |
111 // first that matches the pixel format we wanted. |
274 // first that matches the pixel format we wanted. |
112 EGLint size = matching; |
275 EGLint size = matching; |
140 #endif |
303 #endif |
141 { |
304 { |
142 qWarning() << "QEglContext::chooseConfig(): Could not find a suitable EGL configuration"; |
305 qWarning() << "QEglContext::chooseConfig(): Could not find a suitable EGL configuration"; |
143 qWarning() << "Requested:" << props.toString(); |
306 qWarning() << "Requested:" << props.toString(); |
144 qWarning() << "Available:"; |
307 qWarning() << "Available:"; |
145 dumpAllConfigs(); |
308 QEgl::dumpAllConfigs(); |
146 } |
309 } |
147 return false; |
310 return QEGL_NO_CONFIG; |
148 } |
311 } |
|
312 |
|
313 bool QEglContext::chooseConfig(const QEglProperties& properties, QEgl::PixelFormatMatch match) |
|
314 { |
|
315 cfg = QEgl::chooseConfig(&properties, match); |
|
316 return cfg != QEGL_NO_CONFIG; |
|
317 } |
|
318 |
|
319 EGLSurface QEglContext::createSurface(QPaintDevice* device, const QEglProperties *properties) |
|
320 { |
|
321 return QEgl::createSurface(device, cfg, properties); |
|
322 } |
|
323 |
149 |
324 |
150 // Create the EGLContext. |
325 // Create the EGLContext. |
151 bool QEglContext::createContext(QEglContext *shareContext, const QEglProperties *properties) |
326 bool QEglContext::createContext(QEglContext *shareContext, const QEglProperties *properties) |
152 { |
327 { |
153 // We need to select the correct API before calling eglCreateContext(). |
328 // We need to select the correct API before calling eglCreateContext(). |
|
329 #ifdef QT_OPENGL_ES |
154 #ifdef EGL_OPENGL_ES_API |
330 #ifdef EGL_OPENGL_ES_API |
155 if (apiType == QEgl::OpenGL) |
331 if (apiType == QEgl::OpenGL) |
156 eglBindAPI(EGL_OPENGL_ES_API); |
332 eglBindAPI(EGL_OPENGL_ES_API); |
157 #endif |
333 #endif |
|
334 #else |
|
335 #ifdef EGL_OPENGL_API |
|
336 if (apiType == QEgl::OpenGL) |
|
337 eglBindAPI(EGL_OPENGL_API); |
|
338 #endif |
|
339 #endif //defined(QT_OPENGL_ES) |
158 #ifdef EGL_OPENVG_API |
340 #ifdef EGL_OPENVG_API |
159 if (apiType == QEgl::OpenVG) |
341 if (apiType == QEgl::OpenVG) |
160 eglBindAPI(EGL_OPENVG_API); |
342 eglBindAPI(EGL_OPENVG_API); |
161 #endif |
343 #endif |
162 |
344 |
163 // Create a new context for the configuration. |
345 // Create a new context for the configuration. |
164 QEglProperties contextProps; |
346 QEglProperties contextProps; |
165 if (properties) |
347 if (properties) |
166 contextProps = *properties; |
348 contextProps = *properties; |
167 #if defined(QT_OPENGL_ES_2) |
349 #ifdef QT_OPENGL_ES_2 |
168 if (apiType == QEgl::OpenGL) |
350 if (apiType == QEgl::OpenGL) |
169 contextProps.setValue(EGL_CONTEXT_CLIENT_VERSION, 2); |
351 contextProps.setValue(EGL_CONTEXT_CLIENT_VERSION, 2); |
170 #endif |
352 #endif |
171 sharing = false; |
353 sharing = false; |
172 if (shareContext && shareContext->ctx == EGL_NO_CONTEXT) |
354 if (shareContext && shareContext->ctx == EGL_NO_CONTEXT) |
173 shareContext = 0; |
355 shareContext = 0; |
174 if (shareContext) { |
356 if (shareContext) { |
175 ctx = eglCreateContext(display(), cfg, shareContext->ctx, contextProps.properties()); |
357 ctx = eglCreateContext(QEgl::display(), cfg, shareContext->ctx, contextProps.properties()); |
176 if (ctx == EGL_NO_CONTEXT) { |
358 if (ctx == EGL_NO_CONTEXT) { |
177 qWarning() << "QEglContext::createContext(): Could not share context:" << errorString(eglGetError()); |
359 qWarning() << "QEglContext::createContext(): Could not share context:" << QEgl::errorString(); |
178 shareContext = 0; |
360 shareContext = 0; |
179 } else { |
361 } else { |
180 sharing = true; |
362 sharing = true; |
181 } |
363 } |
182 } |
364 } |
183 if (ctx == EGL_NO_CONTEXT) { |
365 if (ctx == EGL_NO_CONTEXT) { |
184 ctx = eglCreateContext(display(), cfg, 0, contextProps.properties()); |
366 ctx = eglCreateContext(display(), cfg, 0, contextProps.properties()); |
185 if (ctx == EGL_NO_CONTEXT) { |
367 if (ctx == EGL_NO_CONTEXT) { |
186 qWarning() << "QEglContext::createContext(): Unable to create EGL context:" << errorString(eglGetError()); |
368 qWarning() << "QEglContext::createContext(): Unable to create EGL context:" << QEgl::errorString(); |
187 return false; |
369 return false; |
188 } |
370 } |
189 } |
371 } |
190 return true; |
372 return true; |
191 } |
373 } |
289 bool QEglContext::swapBuffers(EGLSurface surface) |
476 bool QEglContext::swapBuffers(EGLSurface surface) |
290 { |
477 { |
291 if(ctx == EGL_NO_CONTEXT) |
478 if(ctx == EGL_NO_CONTEXT) |
292 return false; |
479 return false; |
293 |
480 |
294 bool ok = eglSwapBuffers(display(), surface); |
481 bool ok = eglSwapBuffers(QEgl::display(), surface); |
295 if (!ok) |
482 if (!ok) |
296 qWarning() << "QEglContext::swapBuffers():" << errorString(eglGetError()); |
483 qWarning() << "QEglContext::swapBuffers():" << QEgl::errorString(); |
297 return ok; |
484 return ok; |
298 } |
485 } |
299 |
486 |
300 // Wait for native rendering operations to complete before starting |
487 int QEglContext::configAttrib(int name) const |
301 // to use OpenGL/OpenVG operations. |
488 { |
302 void QEglContext::waitNative() |
489 EGLint value; |
303 { |
490 EGLBoolean success = eglGetConfigAttrib(QEgl::display(), cfg, name, &value); |
304 #ifdef EGL_CORE_NATIVE_ENGINE |
491 if (success) |
305 eglWaitNative(EGL_CORE_NATIVE_ENGINE); |
492 return value; |
306 #endif |
493 else |
307 } |
494 return EGL_DONT_CARE; |
308 |
495 } |
309 // Wait for client OpenGL/OpenVG operations to complete before |
496 |
310 // using native rendering operations. |
497 typedef EGLImageKHR (EGLAPIENTRY *_eglCreateImageKHR)(EGLDisplay, EGLContext, EGLenum, EGLClientBuffer, const EGLint*); |
311 void QEglContext::waitClient() |
498 typedef EGLBoolean (EGLAPIENTRY *_eglDestroyImageKHR)(EGLDisplay, EGLImageKHR); |
312 { |
499 |
313 #ifdef EGL_OPENGL_ES_API |
500 // Defined in qegl.cpp: |
314 if (apiType == QEgl::OpenGL) { |
501 static _eglCreateImageKHR qt_eglCreateImageKHR = 0; |
315 eglBindAPI(EGL_OPENGL_ES_API); |
502 static _eglDestroyImageKHR qt_eglDestroyImageKHR = 0; |
316 eglWaitClient(); |
503 |
317 } |
504 |
318 #else |
505 EGLDisplay QEgl::display() |
319 if (apiType == QEgl::OpenGL) |
506 { |
320 eglWaitGL(); |
507 static EGLDisplay dpy = EGL_NO_DISPLAY; |
321 #endif |
|
322 #ifdef EGL_OPENVG_API |
|
323 if (apiType == QEgl::OpenVG) { |
|
324 eglBindAPI(EGL_OPENVG_API); |
|
325 eglWaitClient(); |
|
326 } |
|
327 #endif |
|
328 } |
|
329 |
|
330 // Query the value of a configuration attribute. |
|
331 bool QEglContext::configAttrib(int name, EGLint *value) const |
|
332 { |
|
333 return eglGetConfigAttrib(display(), cfg, name, value); |
|
334 } |
|
335 |
|
336 // Retrieve all of the properties on "cfg". If zero, return |
|
337 // the context's configuration. |
|
338 QEglProperties QEglContext::configProperties(EGLConfig cfg) const |
|
339 { |
|
340 if (!cfg) |
|
341 cfg = config(); |
|
342 QEglProperties props; |
|
343 for (int name = 0x3020; name <= 0x304F; ++name) { |
|
344 EGLint value; |
|
345 if (name != EGL_NONE && eglGetConfigAttrib(display(), cfg, name, &value)) |
|
346 props.setValue(name, value); |
|
347 } |
|
348 eglGetError(); // Clear the error state. |
|
349 return props; |
|
350 } |
|
351 |
|
352 EGLDisplay QEglContext::display() |
|
353 { |
|
354 static bool openedDisplay = false; |
508 static bool openedDisplay = false; |
355 |
509 |
356 if (!openedDisplay) { |
510 if (!openedDisplay) { |
357 dpy = eglGetDisplay(nativeDisplay()); |
511 dpy = eglGetDisplay(nativeDisplay()); |
358 openedDisplay = true; |
512 openedDisplay = true; |
359 if (dpy == EGL_NO_DISPLAY) { |
513 if (dpy == EGL_NO_DISPLAY) { |
360 qWarning("QEglContext::display(): Falling back to EGL_DEFAULT_DISPLAY"); |
514 qWarning("QEgl::display(): Falling back to EGL_DEFAULT_DISPLAY"); |
361 dpy = eglGetDisplay(EGLNativeDisplayType(EGL_DEFAULT_DISPLAY)); |
515 dpy = eglGetDisplay(EGLNativeDisplayType(EGL_DEFAULT_DISPLAY)); |
362 } |
516 } |
363 if (dpy == EGL_NO_DISPLAY) { |
517 if (dpy == EGL_NO_DISPLAY) { |
364 qWarning("QEglContext::display(): Can't even open the default display"); |
518 qWarning("QEgl::display(): Can't even open the default display"); |
365 return EGL_NO_DISPLAY; |
519 return EGL_NO_DISPLAY; |
366 } |
520 } |
367 |
521 |
368 if (!eglInitialize(dpy, NULL, NULL)) { |
522 if (!eglInitialize(dpy, NULL, NULL)) { |
369 qWarning() << "QEglContext::display(): Cannot initialize EGL display:" << errorString(eglGetError()); |
523 qWarning() << "QEgl::display(): Cannot initialize EGL display:" << QEgl::errorString(); |
370 return EGL_NO_DISPLAY; |
524 return EGL_NO_DISPLAY; |
371 } |
525 } |
|
526 |
|
527 // Resolve the egl extension function pointers: |
|
528 #if (defined(EGL_KHR_image) || defined(EGL_KHR_image_base)) && !defined(EGL_EGLEXT_PROTOTYPES) |
|
529 if (QEgl::hasExtension("EGL_KHR_image") || QEgl::hasExtension("EGL_KHR_image_base")) { |
|
530 qt_eglCreateImageKHR = (_eglCreateImageKHR) eglGetProcAddress("eglCreateImageKHR"); |
|
531 qt_eglDestroyImageKHR = (_eglDestroyImageKHR) eglGetProcAddress("eglDestroyImageKHR"); |
|
532 } |
|
533 #endif |
372 } |
534 } |
373 |
535 |
374 return dpy; |
536 return dpy; |
375 } |
537 } |
376 |
538 |
377 #if !defined(Q_WS_X11) && !defined(Q_WS_WINCE) // WinCE & X11 implement this properly |
539 EGLImageKHR QEgl::eglCreateImageKHR(EGLDisplay dpy, EGLContext ctx, EGLenum target, EGLClientBuffer buffer, const EGLint *attrib_list) |
378 EGLNativeDisplayType QEglContext::nativeDisplay() |
540 { |
379 { |
541 if (qt_eglCreateImageKHR) |
380 return EGL_DEFAULT_DISPLAY; |
542 return qt_eglCreateImageKHR(dpy, ctx, target, buffer, attrib_list); |
381 } |
543 |
382 #endif |
544 QEgl::display(); // Initialises function pointers |
|
545 if (qt_eglCreateImageKHR) |
|
546 return qt_eglCreateImageKHR(dpy, ctx, target, buffer, attrib_list); |
|
547 |
|
548 qWarning("QEgl::eglCreateImageKHR() called but EGL_KHR_image(_base) extension not present"); |
|
549 return 0; |
|
550 } |
|
551 |
|
552 EGLBoolean QEgl::eglDestroyImageKHR(EGLDisplay dpy, EGLImageKHR img) |
|
553 { |
|
554 if (qt_eglDestroyImageKHR) |
|
555 return qt_eglDestroyImageKHR(dpy, img); |
|
556 |
|
557 QEgl::display(); // Initialises function pointers |
|
558 if (qt_eglDestroyImageKHR) |
|
559 return qt_eglDestroyImageKHR(dpy, img); |
|
560 |
|
561 qWarning("QEgl::eglDestroyImageKHR() called but EGL_KHR_image(_base) extension not present"); |
|
562 return 0; |
|
563 } |
|
564 |
|
565 |
|
566 #ifndef Q_WS_X11 |
|
567 EGLSurface QEgl::createSurface(QPaintDevice *device, EGLConfig cfg, const QEglProperties *properties) |
|
568 { |
|
569 // Create the native drawable for the paint device. |
|
570 int devType = device->devType(); |
|
571 EGLNativePixmapType pixmapDrawable = 0; |
|
572 EGLNativeWindowType windowDrawable = 0; |
|
573 bool ok; |
|
574 if (devType == QInternal::Pixmap) { |
|
575 pixmapDrawable = nativePixmap(static_cast<QPixmap *>(device)); |
|
576 ok = (pixmapDrawable != 0); |
|
577 } else if (devType == QInternal::Widget) { |
|
578 windowDrawable = nativeWindow(static_cast<QWidget *>(device)); |
|
579 ok = (windowDrawable != 0); |
|
580 } else { |
|
581 ok = false; |
|
582 } |
|
583 if (!ok) { |
|
584 qWarning("QEglContext::createSurface(): Cannot create the native EGL drawable"); |
|
585 return EGL_NO_SURFACE; |
|
586 } |
|
587 |
|
588 // Create the EGL surface to draw into, based on the native drawable. |
|
589 const int *props; |
|
590 if (properties) |
|
591 props = properties->properties(); |
|
592 else |
|
593 props = 0; |
|
594 EGLSurface surf; |
|
595 if (devType == QInternal::Widget) |
|
596 surf = eglCreateWindowSurface(QEgl::display(), cfg, windowDrawable, props); |
|
597 else |
|
598 surf = eglCreatePixmapSurface(QEgl::display(), cfg, pixmapDrawable, props); |
|
599 if (surf == EGL_NO_SURFACE) { |
|
600 qWarning("QEglContext::createSurface(): Unable to create EGL surface, error = 0x%x", eglGetError()); |
|
601 } |
|
602 return surf; |
|
603 } |
|
604 #endif |
|
605 |
383 |
606 |
384 // Return the error string associated with a specific code. |
607 // Return the error string associated with a specific code. |
385 QString QEglContext::errorString(EGLint code) |
608 QString QEgl::errorString(EGLint code) |
386 { |
609 { |
387 static const char * const errors[] = { |
610 static const char * const errors[] = { |
388 "Success (0x3000)", // No tr |
611 "Success (0x3000)", // No tr |
389 "Not initialized (0x3001)", // No tr |
612 "Not initialized (0x3001)", // No tr |
390 "Bad access (0x3002)", // No tr |
613 "Bad access (0x3002)", // No tr |
407 return QLatin1String("0x") + QString::number(int(code), 16); |
630 return QLatin1String("0x") + QString::number(int(code), 16); |
408 } |
631 } |
409 } |
632 } |
410 |
633 |
411 // Dump all of the EGL configurations supported by the system. |
634 // Dump all of the EGL configurations supported by the system. |
412 void QEglContext::dumpAllConfigs() |
635 void QEgl::dumpAllConfigs() |
413 { |
636 { |
414 QEglProperties props; |
637 QEglProperties props; |
415 EGLint count = 0; |
638 EGLint count = 0; |
416 if (!eglGetConfigs(display(), 0, 0, &count) || count < 1) |
639 if (!eglGetConfigs(display(), 0, 0, &count) || count < 1) |
417 return; |
640 return; |
418 EGLConfig *configs = new EGLConfig [count]; |
641 EGLConfig *configs = new EGLConfig [count]; |
419 eglGetConfigs(display(), configs, count, &count); |
642 eglGetConfigs(display(), configs, count, &count); |
420 for (EGLint index = 0; index < count; ++index) { |
643 for (EGLint index = 0; index < count; ++index) { |
421 props = configProperties(configs[index]); |
644 props = QEglProperties(configs[index]); |
422 qWarning() << props.toString(); |
645 qWarning() << props.toString(); |
423 } |
646 } |
424 delete [] configs; |
647 delete [] configs; |
425 } |
648 } |
426 |
649 |
427 QString QEglContext::extensions() |
650 QString QEgl::extensions() |
428 { |
651 { |
429 const char* exts = eglQueryString(QEglContext::display(), EGL_EXTENSIONS); |
652 const char* exts = eglQueryString(QEgl::display(), EGL_EXTENSIONS); |
430 return QString(QLatin1String(exts)); |
653 return QString(QLatin1String(exts)); |
431 } |
654 } |
432 |
655 |
433 bool QEglContext::hasExtension(const char* extensionName) |
656 bool QEgl::hasExtension(const char* extensionName) |
434 { |
657 { |
435 QList<QByteArray> extensions = |
658 QList<QByteArray> extensions = |
436 QByteArray(reinterpret_cast<const char *> |
659 QByteArray(reinterpret_cast<const char *> |
437 (eglQueryString(QEglContext::display(), EGL_EXTENSIONS))).split(' '); |
660 (eglQueryString(QEgl::display(), EGL_EXTENSIONS))).split(' '); |
438 return extensions.contains(extensionName); |
661 return extensions.contains(extensionName); |
439 } |
662 } |
440 |
663 |
441 QEglContext *QEglContext::currentContext(QEgl::API api) |
664 QEglContext *QEglContext::currentContext(QEgl::API api) |
442 { |
665 { |