40 ****************************************************************************/ |
40 ****************************************************************************/ |
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/qatomic.h> |
45 #include <QtCore/qdebug.h> |
46 #include <QtCore/qdebug.h> |
46 #include "qegl_p.h" |
47 #include "qegl_p.h" |
47 |
48 |
48 QT_BEGIN_NAMESPACE |
49 QT_BEGIN_NAMESPACE |
|
50 |
|
51 |
|
52 /* |
|
53 QEglContextTracker is used to track the EGL contexts that we |
|
54 create internally in Qt, so that we can call eglTerminate() to |
|
55 free additional EGL resources when the last context is destroyed. |
|
56 */ |
|
57 |
|
58 class QEglContextTracker |
|
59 { |
|
60 public: |
|
61 static void ref() { contexts.ref(); } |
|
62 static void deref() { |
|
63 if (!contexts.deref()) { |
|
64 eglTerminate(QEglContext::display()); |
|
65 displayOpen = 0; |
|
66 } |
|
67 } |
|
68 static void setDisplayOpened() { displayOpen = 1; } |
|
69 static bool displayOpened() { return displayOpen; } |
|
70 |
|
71 private: |
|
72 static QBasicAtomicInt contexts; |
|
73 static QBasicAtomicInt displayOpen; |
|
74 }; |
|
75 |
|
76 QBasicAtomicInt QEglContextTracker::contexts = Q_BASIC_ATOMIC_INITIALIZER(0); |
|
77 QBasicAtomicInt QEglContextTracker::displayOpen = Q_BASIC_ATOMIC_INITIALIZER(0); |
49 |
78 |
50 // Current GL and VG contexts. These are used to determine if |
79 // Current GL and VG contexts. These are used to determine if |
51 // we can avoid an eglMakeCurrent() after a call to lazyDoneCurrent(). |
80 // we can avoid an eglMakeCurrent() after a call to lazyDoneCurrent(). |
52 // If a background thread modifies the value, the worst that will |
81 // If a background thread modifies the value, the worst that will |
53 // happen is a redundant eglMakeCurrent() in the foreground thread. |
82 // happen is a redundant eglMakeCurrent() in the foreground thread. |
63 , currentSurface(EGL_NO_SURFACE) |
92 , currentSurface(EGL_NO_SURFACE) |
64 , current(false) |
93 , current(false) |
65 , ownsContext(true) |
94 , ownsContext(true) |
66 , sharing(false) |
95 , sharing(false) |
67 { |
96 { |
|
97 QEglContextTracker::ref(); |
68 } |
98 } |
69 |
99 |
70 QEglContext::~QEglContext() |
100 QEglContext::~QEglContext() |
71 { |
101 { |
72 destroyContext(); |
102 destroyContext(); |
73 |
103 |
74 if (currentGLContext == this) |
104 if (currentGLContext == this) |
75 currentGLContext = 0; |
105 currentGLContext = 0; |
76 if (currentVGContext == this) |
106 if (currentVGContext == this) |
77 currentVGContext = 0; |
107 currentVGContext = 0; |
|
108 QEglContextTracker::deref(); |
78 } |
109 } |
79 |
110 |
80 bool QEglContext::isValid() const |
111 bool QEglContext::isValid() const |
81 { |
112 { |
82 return (ctx != EGL_NO_CONTEXT); |
113 return (ctx != EGL_NO_CONTEXT); |
359 return props; |
390 return props; |
360 } |
391 } |
361 |
392 |
362 EGLDisplay QEglContext::display() |
393 EGLDisplay QEglContext::display() |
363 { |
394 { |
364 static bool openedDisplay = false; |
395 if (!QEglContextTracker::displayOpened()) { |
365 |
|
366 if (!openedDisplay) { |
|
367 dpy = eglGetDisplay(nativeDisplay()); |
396 dpy = eglGetDisplay(nativeDisplay()); |
368 openedDisplay = true; |
397 QEglContextTracker::setDisplayOpened(); |
369 if (dpy == EGL_NO_DISPLAY) { |
398 if (dpy == EGL_NO_DISPLAY) { |
370 qWarning("QEglContext::display(): Falling back to EGL_DEFAULT_DISPLAY"); |
399 qWarning("QEglContext::display(): Falling back to EGL_DEFAULT_DISPLAY"); |
371 dpy = eglGetDisplay(EGLNativeDisplayType(EGL_DEFAULT_DISPLAY)); |
400 dpy = eglGetDisplay(EGLNativeDisplayType(EGL_DEFAULT_DISPLAY)); |
372 } |
401 } |
373 if (dpy == EGL_NO_DISPLAY) { |
402 if (dpy == EGL_NO_DISPLAY) { |