src/gui/egl/qegl.cpp
changeset 33 3e2da88830cd
parent 30 5dc02b23752f
equal deleted inserted replaced
30:5dc02b23752f 33:3e2da88830cd
    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 
    47 
    47 #include "qegl_p.h"
    48 #include "qegl_p.h"
    48 #include "qeglcontext_p.h"
    49 #include "qeglcontext_p.h"
    49 
    50 
    50 
    51 
    51 QT_BEGIN_NAMESPACE
    52 QT_BEGIN_NAMESPACE
       
    53 
       
    54 
       
    55 /*
       
    56     QEglContextTracker is used to track the EGL contexts that we
       
    57     create internally in Qt, so that we can call eglTerminate() to
       
    58     free additional EGL resources when the last context is destroyed.
       
    59 */
       
    60 
       
    61 class QEglContextTracker
       
    62 {
       
    63 public:
       
    64     static void ref() { contexts.ref(); }
       
    65     static void deref() {
       
    66         if (!contexts.deref()) {
       
    67             eglTerminate(QEgl::display());
       
    68             displayOpen = 0;
       
    69         }
       
    70     }
       
    71     static void setDisplayOpened() { displayOpen = 1; }
       
    72     static bool displayOpened() { return displayOpen; }
       
    73 
       
    74 private:
       
    75     static QBasicAtomicInt contexts;
       
    76     static QBasicAtomicInt displayOpen;
       
    77 };
       
    78 
       
    79 QBasicAtomicInt QEglContextTracker::contexts = Q_BASIC_ATOMIC_INITIALIZER(0);
       
    80 QBasicAtomicInt QEglContextTracker::displayOpen = Q_BASIC_ATOMIC_INITIALIZER(0);
    52 
    81 
    53 // Current GL and VG contexts.  These are used to determine if
    82 // Current GL and VG contexts.  These are used to determine if
    54 // we can avoid an eglMakeCurrent() after a call to lazyDoneCurrent().
    83 // we can avoid an eglMakeCurrent() after a call to lazyDoneCurrent().
    55 // If a background thread modifies the value, the worst that will
    84 // If a background thread modifies the value, the worst that will
    56 // happen is a redundant eglMakeCurrent() in the foreground thread.
    85 // happen is a redundant eglMakeCurrent() in the foreground thread.
    64     , currentSurface(EGL_NO_SURFACE)
    93     , currentSurface(EGL_NO_SURFACE)
    65     , current(false)
    94     , current(false)
    66     , ownsContext(true)
    95     , ownsContext(true)
    67     , sharing(false)
    96     , sharing(false)
    68 {
    97 {
       
    98     QEglContextTracker::ref();
    69 }
    99 }
    70 
   100 
    71 QEglContext::~QEglContext()
   101 QEglContext::~QEglContext()
    72 {
   102 {
    73     destroyContext();
   103     destroyContext();
    74 
   104 
    75     if (currentGLContext == this)
   105     if (currentGLContext == this)
    76         currentGLContext = 0;
   106         currentGLContext = 0;
    77     if (currentVGContext == this)
   107     if (currentVGContext == this)
    78         currentVGContext = 0;
   108         currentVGContext = 0;
       
   109     QEglContextTracker::deref();
    79 }
   110 }
    80 
   111 
    81 bool QEglContext::isValid() const
   112 bool QEglContext::isValid() const
    82 {
   113 {
    83     return (ctx != EGL_NO_CONTEXT);
   114     return (ctx != EGL_NO_CONTEXT);
   482     if (!ok)
   513     if (!ok)
   483         qWarning() << "QEglContext::swapBuffers():" << QEgl::errorString();
   514         qWarning() << "QEglContext::swapBuffers():" << QEgl::errorString();
   484     return ok;
   515     return ok;
   485 }
   516 }
   486 
   517 
       
   518 bool QEglContext::swapBuffersRegion2NOK(EGLSurface surface, const QRegion *region) {
       
   519     QVector<QRect> qrects = region->rects();
       
   520     EGLint *gl_rects;
       
   521     uint count;
       
   522     uint i;
       
   523 
       
   524     count = qrects.size();
       
   525     QVarLengthArray <EGLint> arr(4 * count);
       
   526     gl_rects = arr.data();
       
   527     for (i = 0; i < count; i++) {
       
   528       QRect qrect = qrects[i];
       
   529 
       
   530       gl_rects[4 * i + 0] = qrect.x();
       
   531       gl_rects[4 * i + 1] = qrect.y();
       
   532       gl_rects[4 * i + 2] = qrect.width();
       
   533       gl_rects[4 * i + 3] = qrect.height();
       
   534     }
       
   535 
       
   536     bool ok = QEgl::eglSwapBuffersRegion2NOK(QEgl::display(), surface, count, gl_rects);
       
   537 
       
   538     if (!ok)
       
   539         qWarning() << "QEglContext::swapBuffersRegion2NOK():" << QEgl::errorString();
       
   540     return ok;
       
   541 }
       
   542 
   487 int QEglContext::configAttrib(int name) const
   543 int QEglContext::configAttrib(int name) const
   488 {
   544 {
   489     EGLint value;
   545     EGLint value;
   490     EGLBoolean success = eglGetConfigAttrib(QEgl::display(), cfg, name, &value);
   546     EGLBoolean success = eglGetConfigAttrib(QEgl::display(), cfg, name, &value);
   491     if (success)
   547     if (success)
   499 
   555 
   500 // Defined in qegl.cpp:
   556 // Defined in qegl.cpp:
   501 static _eglCreateImageKHR qt_eglCreateImageKHR = 0;
   557 static _eglCreateImageKHR qt_eglCreateImageKHR = 0;
   502 static _eglDestroyImageKHR qt_eglDestroyImageKHR = 0;
   558 static _eglDestroyImageKHR qt_eglDestroyImageKHR = 0;
   503 
   559 
       
   560 typedef EGLBoolean (EGLAPIENTRY *_eglSwapBuffersRegion2NOK)(EGLDisplay, EGLSurface, EGLint, const EGLint*);
       
   561 
       
   562 static _eglSwapBuffersRegion2NOK qt_eglSwapBuffersRegion2NOK = 0;
   504 
   563 
   505 EGLDisplay QEgl::display()
   564 EGLDisplay QEgl::display()
   506 {
   565 {
   507     static EGLDisplay dpy = EGL_NO_DISPLAY;
   566     static EGLDisplay dpy = EGL_NO_DISPLAY;
   508     static bool openedDisplay = false;
   567     if (!QEglContextTracker::displayOpened()) {
   509 
       
   510     if (!openedDisplay) {
       
   511         dpy = eglGetDisplay(nativeDisplay());
   568         dpy = eglGetDisplay(nativeDisplay());
   512         openedDisplay = true;
   569         QEglContextTracker::setDisplayOpened();
   513         if (dpy == EGL_NO_DISPLAY) {
   570         if (dpy == EGL_NO_DISPLAY) {
   514             qWarning("QEgl::display(): Falling back to EGL_DEFAULT_DISPLAY");
   571             qWarning("QEgl::display(): Falling back to EGL_DEFAULT_DISPLAY");
   515             dpy = eglGetDisplay(EGLNativeDisplayType(EGL_DEFAULT_DISPLAY));
   572             dpy = eglGetDisplay(EGLNativeDisplayType(EGL_DEFAULT_DISPLAY));
   516         }
   573         }
   517         if (dpy == EGL_NO_DISPLAY) {
   574         if (dpy == EGL_NO_DISPLAY) {
   529         if (QEgl::hasExtension("EGL_KHR_image") || QEgl::hasExtension("EGL_KHR_image_base")) {
   586         if (QEgl::hasExtension("EGL_KHR_image") || QEgl::hasExtension("EGL_KHR_image_base")) {
   530             qt_eglCreateImageKHR = (_eglCreateImageKHR) eglGetProcAddress("eglCreateImageKHR");
   587             qt_eglCreateImageKHR = (_eglCreateImageKHR) eglGetProcAddress("eglCreateImageKHR");
   531             qt_eglDestroyImageKHR = (_eglDestroyImageKHR) eglGetProcAddress("eglDestroyImageKHR");
   588             qt_eglDestroyImageKHR = (_eglDestroyImageKHR) eglGetProcAddress("eglDestroyImageKHR");
   532         }
   589         }
   533 #endif
   590 #endif
       
   591 
       
   592         if (QEgl::hasExtension("EGL_NOK_swap_region2")) {
       
   593             qt_eglSwapBuffersRegion2NOK = (_eglSwapBuffersRegion2NOK) eglGetProcAddress("eglSwapBuffersRegion2NOK");
       
   594         }
   534     }
   595     }
   535 
   596 
   536     return dpy;
   597     return dpy;
   537 }
   598 }
   538 
   599 
   560 
   621 
   561     qWarning("QEgl::eglDestroyImageKHR() called but EGL_KHR_image(_base) extension not present");
   622     qWarning("QEgl::eglDestroyImageKHR() called but EGL_KHR_image(_base) extension not present");
   562     return 0;
   623     return 0;
   563 }
   624 }
   564 
   625 
       
   626 EGLBoolean QEgl::eglSwapBuffersRegion2NOK(EGLDisplay dpy, EGLSurface surface, EGLint count, const EGLint *rects)
       
   627 {
       
   628     if (qt_eglSwapBuffersRegion2NOK)
       
   629         return qt_eglSwapBuffersRegion2NOK(dpy, surface, count, rects);
       
   630 
       
   631     QEgl::display(); // Initialises function pointers
       
   632     if (qt_eglSwapBuffersRegion2NOK)
       
   633         return qt_eglSwapBuffersRegion2NOK(dpy, surface, count, rects);
       
   634 
       
   635     qWarning("QEgl::eglSwapBuffersRegion2NOK() called but EGL_NOK_swap_region2 extension not present");
       
   636     return 0;
       
   637 }
   565 
   638 
   566 #ifndef Q_WS_X11
   639 #ifndef Q_WS_X11
   567 EGLSurface QEgl::createSurface(QPaintDevice *device, EGLConfig cfg, const QEglProperties *properties)
   640 EGLSurface QEgl::createSurface(QPaintDevice *device, EGLConfig cfg, const QEglProperties *properties)
   568 {
   641 {
   569     // Create the native drawable for the paint device.
   642     // Create the native drawable for the paint device.