summaryrefslogtreecommitdiffstats
path: root/src/opengl/qgl_x11egl.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/opengl/qgl_x11egl.cpp')
-rw-r--r--src/opengl/qgl_x11egl.cpp378
1 files changed, 378 insertions, 0 deletions
diff --git a/src/opengl/qgl_x11egl.cpp b/src/opengl/qgl_x11egl.cpp
new file mode 100644
index 0000000..480a2dc
--- /dev/null
+++ b/src/opengl/qgl_x11egl.cpp
@@ -0,0 +1,378 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtOpenGL module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qgl.h"
+#include <private/qt_x11_p.h>
+#include <private/qgl_p.h>
+#include <private/qpaintengine_opengl_p.h>
+#include "qgl_egl_p.h"
+#include "qcolormap.h"
+
+
+QT_BEGIN_NAMESPACE
+
+
+bool QGLFormat::hasOpenGL()
+{
+ return true;
+}
+
+bool QGLFormat::hasOpenGLOverlays()
+{
+ return false;
+}
+
+void qt_egl_add_platform_config(QEglProperties& props, QPaintDevice *device)
+{
+ if (device->devType() == QInternal::Image)
+ props.setPixelFormat(static_cast<QImage *>(device)->format());
+}
+
+bool QGLContext::chooseContext(const QGLContext* shareContext)
+{
+ Q_D(QGLContext);
+
+ if (!device())
+ return false;
+
+ int devType = device()->devType();
+
+ // Get the display and initialize it.
+ d->eglContext = new QEglContext();
+ d->eglContext->setApi(QEglContext::OpenGL);
+ if (!d->eglContext->openDisplay(device())) {
+ delete d->eglContext;
+ d->eglContext = 0;
+ return false;
+ }
+
+ // Construct the configuration we need for this surface.
+ QEglProperties configProps;
+ qt_egl_set_format(configProps, devType, d->glFormat);
+ qt_egl_add_platform_config(configProps, device());
+ configProps.setRenderableType(QEglContext::OpenGL);
+
+ // Search for a matching configuration, reducing the complexity
+ // each time until we get something that matches.
+ if (!d->eglContext->chooseConfig(configProps, QEglContext::BestPixelFormat)) {
+ delete d->eglContext;
+ d->eglContext = 0;
+ return false;
+ }
+
+ // Inform the higher layers about the actual format properties.
+ qt_egl_update_format(*(d->eglContext), d->glFormat);
+
+ // Create a new context for the configuration.
+ if (!d->eglContext->createContext
+ (shareContext ? shareContext->d_func()->eglContext : 0)) {
+ delete d->eglContext;
+ d->eglContext = 0;
+ return false;
+ }
+
+#if defined(EGL_VERSION_1_1)
+ if (d->glFormat.swapInterval() != -1 && devType == QInternal::Widget)
+ eglSwapInterval(d->eglContext->display(), d->glFormat.swapInterval());
+#endif
+
+ // Create the EGL surface to draw into.
+ if (!d->eglContext->createSurface(device())) {
+ delete d->eglContext;
+ d->eglContext = 0;
+ return false;
+ }
+
+ return true;
+}
+
+
+void QGLContext::reset()
+{
+ Q_D(QGLContext);
+ if (!d->valid)
+ return;
+ d->cleanup();
+ doneCurrent();
+ if (d->eglContext) {
+ delete d->eglContext;
+ d->eglContext = 0;
+ }
+ d->crWin = false;
+ d->sharing = false;
+ d->valid = false;
+ d->transpColor = QColor();
+ d->initDone = false;
+ qgl_share_reg()->removeShare(this);
+}
+
+void QGLContext::makeCurrent()
+{
+ Q_D(QGLContext);
+ if(!d->valid || !d->eglContext) {
+ qWarning("QGLContext::makeCurrent(): Cannot make invalid context current");
+ return;
+ }
+
+ if (d->eglContext->makeCurrent()) {
+ if (!qgl_context_storage.hasLocalData() && QThread::currentThread())
+ qgl_context_storage.setLocalData(new QGLThreadContext);
+ if (qgl_context_storage.hasLocalData())
+ qgl_context_storage.localData()->context = this;
+ currentCtx = this;
+ }
+}
+
+void QGLContext::doneCurrent()
+{
+ Q_D(QGLContext);
+ if (d->eglContext)
+ d->eglContext->doneCurrent();
+
+ if (qgl_context_storage.hasLocalData())
+ qgl_context_storage.localData()->context = 0;
+ currentCtx = 0;
+}
+
+
+void QGLContext::swapBuffers() const
+{
+ Q_D(const QGLContext);
+ if(!d->valid || !d->eglContext)
+ return;
+
+ d->eglContext->swapBuffers();
+}
+
+QColor QGLContext::overlayTransparentColor() const
+{
+ return QColor(0, 0, 0); // Invalid color
+}
+
+uint QGLContext::colorIndex(const QColor &c) const
+{
+ //### color index doesn't work on egl
+ Q_UNUSED(c);
+ return 0;
+}
+
+void QGLContext::generateFontDisplayLists(const QFont & fnt, int listBase)
+{
+ Q_UNUSED(fnt);
+ Q_UNUSED(listBase);
+}
+
+void *QGLContext::getProcAddress(const QString &proc) const
+{
+ return (void*)eglGetProcAddress(reinterpret_cast<const char *>(proc.toLatin1().data()));
+}
+
+void QGLWidget::setMouseTracking(bool enable)
+{
+ QWidget::setMouseTracking(enable);
+}
+
+
+void QGLWidget::resizeEvent(QResizeEvent *)
+{
+ Q_D(QGLWidget);
+ if (!isValid())
+ return;
+ makeCurrent();
+ if (!d->glcx->initialized())
+ glInit();
+ resizeGL(width(), height());
+ //handle overlay
+}
+
+const QGLContext* QGLWidget::overlayContext() const
+{
+ return 0;
+}
+
+void QGLWidget::makeOverlayCurrent()
+{
+ //handle overlay
+}
+
+void QGLWidget::updateOverlayGL()
+{
+ //handle overlay
+}
+
+void QGLWidget::setContext(QGLContext *context, const QGLContext* shareContext, bool deleteOldContext)
+{
+ Q_D(QGLWidget);
+ if (context == 0) {
+ qWarning("QGLWidget::setContext: Cannot set null context");
+ return;
+ }
+ if (!context->deviceIsPixmap() && context->device() != this) {
+ qWarning("QGLWidget::setContext: Context must refer to this widget");
+ return;
+ }
+
+ if (d->glcx)
+ d->glcx->doneCurrent();
+ QGLContext* oldcx = d->glcx;
+ d->glcx = context;
+
+ if (parentWidget()) {
+ // force creation of delay-created widgets
+ parentWidget()->winId();
+ if (parentWidget()->x11Info().screen() != x11Info().screen())
+ d_func()->xinfo = parentWidget()->d_func()->xinfo;
+ }
+
+ bool visible = isVisible();
+ if (visible)
+ hide();
+
+ XVisualInfo vi;
+
+ int err = XMatchVisualInfo(x11Info().display(), x11Info().screen(), x11Info().depth(), TrueColor, &vi);
+ if (err == 0) {
+ qWarning("Error: Couldn't get a matching X visual for format");
+ return;
+ }
+
+ XSetWindowAttributes a;
+
+ Window p = RootWindow(X11->display, vi.screen);
+ if (parentWidget())
+ p = parentWidget()->winId();
+
+ QColormap colmap = QColormap::instance(vi.screen);
+ a.background_pixel = colmap.pixel(palette().color(backgroundRole()));
+ a.border_pixel = colmap.pixel(Qt::black);
+
+ Window w = XCreateWindow(X11->display, p, x(), y(), width(), height(),
+ 0, vi.depth, InputOutput, vi.visual,
+ CWBackPixel|CWBorderPixel, &a);
+
+ if (deleteOldContext)
+ delete oldcx;
+ oldcx = 0;
+
+ create(w); // Create with the ID of the window we've just created
+
+ d->eglSurfaceWindowId = w; // Remember the window id we created the surface for
+
+ if (visible)
+ show();
+
+ bool createFailed = false;
+ if (!d->glcx->isValid()) {
+ if (!d->glcx->create(shareContext ? shareContext : oldcx))
+ createFailed = true;
+ }
+ if (createFailed) {
+ if (deleteOldContext)
+ delete oldcx;
+ return;
+ }
+
+ if (d->glcx->windowCreated() || d->glcx->deviceIsPixmap()) {
+ if (deleteOldContext)
+ delete oldcx;
+ return;
+ }
+
+ d->glcx->setWindowCreated(true);
+}
+
+void QGLWidgetPrivate::init(QGLContext *context, const QGLWidget* shareWidget)
+{
+ Q_Q(QGLWidget);
+
+ initContext(context, shareWidget);
+
+ if(q->isValid() && glcx->format().hasOverlay()) {
+ //no overlay
+ qWarning("QtOpenGL ES doesn't currently support overlays");
+ }
+}
+
+bool QGLWidgetPrivate::renderCxPm(QPixmap*)
+{
+ return false;
+}
+
+void QGLWidgetPrivate::cleanupColormaps()
+{
+}
+
+const QGLColormap & QGLWidget::colormap() const
+{
+ return d_func()->cmap;
+}
+
+void QGLWidget::setColormap(const QGLColormap &)
+{
+}
+
+void QGLExtensions::init()
+{
+ static bool init_done = false;
+
+ if (init_done)
+ return;
+ init_done = true;
+ init_extensions();
+}
+
+// Re-creates the EGL surface if the window ID has changed or if force is true
+void QGLWidgetPrivate::recreateEglSurface(bool force)
+{
+ Q_Q(QGLWidget);
+
+ Window currentId = q->winId();
+
+ if ( force || (currentId != eglSurfaceWindowId) ) {
+ // The window id has changed so we need to re-create the EGL surface
+ if (!glcx->d_func()->eglContext->recreateSurface(q))
+ qWarning("Error creating EGL window surface: 0x%x", eglGetError());
+
+ eglSurfaceWindowId = currentId;
+ }
+}
+
+QT_END_NAMESPACE