src/opengl/qgl_x11egl.cpp
changeset 7 f7bc934e204c
parent 3 41300fa6a67c
child 30 5dc02b23752f
equal deleted inserted replaced
3:41300fa6a67c 7:f7bc934e204c
     1 /****************************************************************************
     1 /****************************************************************************
     2 **
     2 **
     3 ** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
     3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
     4 ** All rights reserved.
     4 ** All rights reserved.
     5 ** Contact: Nokia Corporation (qt-info@nokia.com)
     5 ** Contact: Nokia Corporation (qt-info@nokia.com)
     6 **
     6 **
     7 ** This file is part of the QtOpenGL module of the Qt Toolkit.
     7 ** This file is part of the QtOpenGL module of the Qt Toolkit.
     8 **
     8 **
    50 #include <QDebug>
    50 #include <QDebug>
    51 
    51 
    52 
    52 
    53 QT_BEGIN_NAMESPACE
    53 QT_BEGIN_NAMESPACE
    54 
    54 
       
    55 
       
    56 bool qt_egl_setup_x11_visual(XVisualInfo &vi, EGLDisplay display, EGLConfig config,
       
    57                              const QX11Info &x11Info, bool useArgbVisual);
       
    58 
       
    59 /*
       
    60     QGLTemporaryContext implementation
       
    61 */
       
    62 
       
    63 class QGLTemporaryContextPrivate
       
    64 {
       
    65 public:
       
    66     bool initialized;
       
    67     Window window;
       
    68     EGLContext context;
       
    69     EGLSurface surface;
       
    70     EGLDisplay display;
       
    71 };
       
    72 
       
    73 QGLTemporaryContext::QGLTemporaryContext(bool, QWidget *)
       
    74     : d(new QGLTemporaryContextPrivate)
       
    75 {
       
    76     d->initialized = false;
       
    77     d->window = 0;
       
    78     d->context = 0;
       
    79     d->surface = 0;
       
    80     int screen = 0;
       
    81 
       
    82     d->display = eglGetDisplay(EGLNativeDisplayType(X11->display));
       
    83 
       
    84     if (!eglInitialize(d->display, NULL, NULL)) {
       
    85         qWarning("QGLTemporaryContext: Unable to initialize EGL display.");
       
    86         return;
       
    87     }
       
    88 
       
    89     EGLConfig config;
       
    90     int numConfigs = 0;
       
    91     EGLint attribs[] = {
       
    92         EGL_SURFACE_TYPE, EGL_WINDOW_BIT,
       
    93 #ifdef QT_OPENGL_ES_2
       
    94         EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT,
       
    95 #endif
       
    96         EGL_NONE
       
    97     };
       
    98 
       
    99     eglChooseConfig(d->display, attribs, &config, 1, &numConfigs);
       
   100     if (!numConfigs) {
       
   101         qWarning("QGLTemporaryContext: No EGL configurations available.");
       
   102         return;
       
   103     }
       
   104 
       
   105     XVisualInfo visualInfo;
       
   106     XVisualInfo *vi;
       
   107     int numVisuals;
       
   108     EGLint id = 0;
       
   109 
       
   110     eglGetConfigAttrib(d->display, config, EGL_NATIVE_VISUAL_ID, &id);
       
   111     if (id == 0) {
       
   112         // EGL_NATIVE_VISUAL_ID is optional and might not be supported
       
   113         // on some implementations - we'll have to do it the hard way
       
   114         QX11Info xinfo;
       
   115         qt_egl_setup_x11_visual(visualInfo, d->display, config, xinfo, false);
       
   116     } else {
       
   117         visualInfo.visualid = id;
       
   118     }
       
   119     vi = XGetVisualInfo(X11->display, VisualIDMask, &visualInfo, &numVisuals);
       
   120     if (!vi || numVisuals < 1) {
       
   121         qWarning("QGLTemporaryContext: Unable to get X11 visual info id.");
       
   122         return;
       
   123     }
       
   124 
       
   125     d->window = XCreateWindow(X11->display, RootWindow(X11->display, screen),
       
   126                               0, 0, 1, 1, 0,
       
   127                               vi->depth, InputOutput, vi->visual,
       
   128                               0, 0);
       
   129 
       
   130     d->surface = eglCreateWindowSurface(d->display, config, (EGLNativeWindowType) d->window, NULL);
       
   131 
       
   132     if (d->surface == EGL_NO_SURFACE) {
       
   133         qWarning("QGLTemporaryContext: Error creating EGL surface.");
       
   134         XFree(vi);
       
   135         XDestroyWindow(X11->display, d->window);
       
   136         return;
       
   137     }
       
   138 
       
   139     EGLint contextAttribs[] = {
       
   140 #ifdef QT_OPENGL_ES_2
       
   141         EGL_CONTEXT_CLIENT_VERSION, 2,
       
   142 #endif
       
   143         EGL_NONE
       
   144     };
       
   145     d->context = eglCreateContext(d->display, config, 0, contextAttribs);
       
   146     if (d->context != EGL_NO_CONTEXT
       
   147         && eglMakeCurrent(d->display, d->surface, d->surface, d->context))
       
   148     {
       
   149         d->initialized = true;
       
   150     } else {
       
   151         qWarning("QGLTemporaryContext: Error creating EGL context.");
       
   152         eglDestroySurface(d->display, d->surface);
       
   153         XDestroyWindow(X11->display, d->window);
       
   154     }
       
   155     XFree(vi);
       
   156 }
       
   157 
       
   158 QGLTemporaryContext::~QGLTemporaryContext()
       
   159 {
       
   160     if (d->initialized) {
       
   161         eglMakeCurrent(d->display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
       
   162         eglDestroyContext(d->display, d->context);
       
   163         eglDestroySurface(d->display, d->surface);
       
   164         XDestroyWindow(X11->display, d->window);
       
   165     }
       
   166 }
       
   167 
    55 bool QGLFormat::hasOpenGLOverlays()
   168 bool QGLFormat::hasOpenGLOverlays()
    56 {
   169 {
    57     return false;
   170     return false;
    58 }
   171 }
    59 
   172 
    75 
   188 
    76     // Get the display and initialize it.
   189     // Get the display and initialize it.
    77     if (d->eglContext == 0) {
   190     if (d->eglContext == 0) {
    78         d->eglContext = new QEglContext();
   191         d->eglContext = new QEglContext();
    79         d->eglContext->setApi(QEgl::OpenGL);
   192         d->eglContext->setApi(QEgl::OpenGL);
    80         if (!d->eglContext->openDisplay(device())) {
       
    81             delete d->eglContext;
       
    82             d->eglContext = 0;
       
    83             return false;
       
    84         }
       
    85 
   193 
    86         // Construct the configuration we need for this surface.
   194         // Construct the configuration we need for this surface.
    87         QEglProperties configProps;
   195         QEglProperties configProps;
    88         qt_egl_set_format(configProps, devType, d->glFormat);
   196         qt_egl_set_format(configProps, devType, d->glFormat);
    89         qt_egl_add_platform_config(configProps, device());
   197         qt_egl_add_platform_config(configProps, device());
   237         }
   345         }
   238     }
   346     }
   239 
   347 
   240     // If EGL does not know the visual ID, so try to select an appropriate one ourselves, first
   348     // If EGL does not know the visual ID, so try to select an appropriate one ourselves, first
   241     // using XRender if we're supposed to have an alpha, then falling back to XGetVisualInfo
   349     // using XRender if we're supposed to have an alpha, then falling back to XGetVisualInfo
   242           
   350 
   243 #if !defined(QT_NO_XRENDER)
   351 #if !defined(QT_NO_XRENDER)
   244     if (vi.visualid == 0 && useArgbVisual) {
   352     if (vi.visualid == 0 && useArgbVisual) {
   245         // Try to use XRender to find an ARGB visual we can use
   353         // Try to use XRender to find an ARGB visual we can use
   246         vi.screen  = x11Info.screen();
   354         vi.screen  = x11Info.screen();
   247         vi.depth   = 32; //### We might at some point (soon) get ARGB4444
   355         vi.depth   = 32; //### We might at some point (soon) get ARGB4444
   435 
   543 
   436 void QGLWidget::setColormap(const QGLColormap &)
   544 void QGLWidget::setColormap(const QGLColormap &)
   437 {
   545 {
   438 }
   546 }
   439 
   547 
   440 void QGLExtensions::init()
       
   441 {
       
   442     static bool init_done = false;
       
   443 
       
   444     if (init_done)
       
   445         return;
       
   446     init_done = true;
       
   447 
       
   448     // We need a context current to initialize the extensions.
       
   449     QGLWidget tmpWidget;
       
   450     tmpWidget.makeCurrent();
       
   451 
       
   452     init_extensions();
       
   453 
       
   454     tmpWidget.doneCurrent();
       
   455 }
       
   456 
       
   457 // Re-creates the EGL surface if the window ID has changed or if force is true
   548 // Re-creates the EGL surface if the window ID has changed or if force is true
   458 void QGLWidgetPrivate::recreateEglSurface(bool force)
   549 void QGLWidgetPrivate::recreateEglSurface(bool force)
   459 {
   550 {
   460     Q_Q(QGLWidget);
   551     Q_Q(QGLWidget);
   461 
   552 
   516             configAttribs.setValue(EGL_SAMPLE_BUFFERS, 1);
   607             configAttribs.setValue(EGL_SAMPLE_BUFFERS, 1);
   517         }
   608         }
   518 
   609 
   519         EGLint configCount = 0;
   610         EGLint configCount = 0;
   520         do {
   611         do {
   521             eglChooseConfig(QEglContext::defaultDisplay(0), configAttribs.properties(), targetConfig, 1, &configCount);
   612             eglChooseConfig(QEglContext::display(), configAttribs.properties(), targetConfig, 1, &configCount);
   522             if (configCount > 0) {
   613             if (configCount > 0) {
   523                 // Got one
   614                 // Got one
   524                 qDebug() << "Found an" << (hasAlpha ? "ARGB" : "RGB") << (readOnly ? "readonly" : "target" )
   615                 qDebug() << "Found an" << (hasAlpha ? "ARGB" : "RGB") << (readOnly ? "readonly" : "target" )
   525                          << "config (" << int(*targetConfig) << ") to create a pixmap surface:";
   616                          << "config (" << int(*targetConfig) << ") to create a pixmap surface:";
   526 
   617 
   555         pixmapAttribs.setValue(EGL_TEXTURE_FORMAT, EGL_TEXTURE_RGBA);
   646         pixmapAttribs.setValue(EGL_TEXTURE_FORMAT, EGL_TEXTURE_RGBA);
   556     else
   647     else
   557         pixmapAttribs.setValue(EGL_TEXTURE_FORMAT, EGL_TEXTURE_RGB);
   648         pixmapAttribs.setValue(EGL_TEXTURE_FORMAT, EGL_TEXTURE_RGB);
   558 
   649 
   559     EGLSurface pixmapSurface;
   650     EGLSurface pixmapSurface;
   560     pixmapSurface = eglCreatePixmapSurface(QEglContext::defaultDisplay(0),
   651     pixmapSurface = eglCreatePixmapSurface(QEglContext::display(),
   561                                            pixmapConfig,
   652                                            pixmapConfig,
   562                                            (EGLNativePixmapType) pixmapData->handle(),
   653                                            (EGLNativePixmapType) pixmapData->handle(),
   563                                            pixmapAttribs.properties());
   654                                            pixmapAttribs.properties());
   564 //    qDebug("qt_createEGLSurfaceForPixmap() created surface 0x%x for pixmap 0x%x",
   655 //    qDebug("qt_createEGLSurfaceForPixmap() created surface 0x%x for pixmap 0x%x",
   565 //           pixmapSurface, pixmapData->handle());
   656 //           pixmapSurface, pixmapData->handle());
   664 {
   755 {
   665     Q_ASSERT(pmd->classId() == QPixmapData::X11Class);
   756     Q_ASSERT(pmd->classId() == QPixmapData::X11Class);
   666     QX11PixmapData *pixmapData = static_cast<QX11PixmapData*>(pmd);
   757     QX11PixmapData *pixmapData = static_cast<QX11PixmapData*>(pmd);
   667     if (pixmapData->gl_surface) {
   758     if (pixmapData->gl_surface) {
   668         EGLBoolean success;
   759         EGLBoolean success;
   669         success = eglDestroySurface(QEglContext::defaultDisplay(0), (EGLSurface)pixmapData->gl_surface);
   760         success = eglDestroySurface(QEglContext::display(), (EGLSurface)pixmapData->gl_surface);
   670         if (success == EGL_FALSE) {
   761         if (success == EGL_FALSE) {
   671             qWarning() << "destroyGlSurfaceForPixmap() - Error deleting surface: "
   762             qWarning() << "destroyGlSurfaceForPixmap() - Error deleting surface: "
   672                        << QEglContext::errorString(eglGetError());
   763                        << QEglContext::errorString(eglGetError());
   673         }
   764         }
   674         pixmapData->gl_surface = 0;
   765         pixmapData->gl_surface = 0;
   679 {
   770 {
   680     Q_ASSERT(pmd->classId() == QPixmapData::X11Class);
   771     Q_ASSERT(pmd->classId() == QPixmapData::X11Class);
   681     QX11PixmapData *pixmapData = static_cast<QX11PixmapData*>(pmd);
   772     QX11PixmapData *pixmapData = static_cast<QX11PixmapData*>(pmd);
   682     if (pixmapData->gl_surface) {
   773     if (pixmapData->gl_surface) {
   683         EGLBoolean success;
   774         EGLBoolean success;
   684         success = eglReleaseTexImage(QEglContext::defaultDisplay(0),
   775         success = eglReleaseTexImage(QEglContext::display(),
   685                                      (EGLSurface)pixmapData->gl_surface,
   776                                      (EGLSurface)pixmapData->gl_surface,
   686                                      EGL_BACK_BUFFER);
   777                                      EGL_BACK_BUFFER);
   687         if (success == EGL_FALSE) {
   778         if (success == EGL_FALSE) {
   688             qWarning() << "unbindPixmapFromTexture() - Unable to release bound texture: "
   779             qWarning() << "unbindPixmapFromTexture() - Unable to release bound texture: "
   689                        << QEglContext::errorString(eglGetError());
   780                        << QEglContext::errorString(eglGetError());