summaryrefslogtreecommitdiffstats
path: root/src/opengl
diff options
context:
space:
mode:
Diffstat (limited to 'src/opengl')
-rw-r--r--src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp16
-rw-r--r--src/opengl/gl2paintengineex/qtriangulator.cpp8
-rw-r--r--src/opengl/opengl.pro28
-rw-r--r--src/opengl/qgl.cpp92
-rw-r--r--src/opengl/qgl_egl.cpp3
-rw-r--r--src/opengl/qgl_mac.mm11
-rw-r--r--src/opengl/qgl_p.h12
-rw-r--r--src/opengl/qgl_symbian.cpp362
-rw-r--r--src/opengl/qglextensions.cpp4
-rw-r--r--src/opengl/qglframebufferobject.cpp4
-rw-r--r--src/opengl/qglshaderprogram.cpp2
-rw-r--r--src/opengl/qpixmapdata_gl.cpp6
-rw-r--r--src/opengl/qwindowsurface_gl.cpp19
-rw-r--r--src/opengl/qwindowsurface_gl_p.h1
14 files changed, 532 insertions, 36 deletions
diff --git a/src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp b/src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp
index d3f6a29..18192e3 100644
--- a/src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp
+++ b/src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp
@@ -90,7 +90,10 @@
QT_BEGIN_NAMESPACE
-//#define QT_GL_NO_SCISSOR_TEST
+#if defined(Q_OS_SYMBIAN)
+#define QT_GL_NO_SCISSOR_TEST
+#endif
+
#if defined(Q_WS_WIN)
extern Q_GUI_EXPORT bool qt_cleartype_enabled;
#endif
@@ -374,12 +377,12 @@ void QGL2PaintEngineExPrivate::updateMatrix()
dx = ceilf(dx - 0.5f);
dy = ceilf(dy - 0.5f);
}
-
+#ifndef Q_OS_SYMBIAN
if (addOffset) {
dx += 0.49f;
dy += 0.49f;
}
-
+#endif
pmvMatrix[0][0] = (wfactor * transform.m11()) - transform.m13();
pmvMatrix[1][0] = (wfactor * transform.m21()) - transform.m23();
pmvMatrix[2][0] = (wfactor * dx) - transform.m33();
@@ -686,7 +689,12 @@ void QGL2PaintEngineExPrivate::fill(const QVectorPath& path)
const QPointF* const points = reinterpret_cast<const QPointF*>(path.points());
// ### Remove before release...
- static bool do_vectorpath_cache = qgetenv("QT_OPENGL_NO_PATH_CACHE").isEmpty();
+#ifdef Q_OS_SYMBIAN
+ // ### There are some unresolved issues in Symbian vector path caching.
+ static bool do_vectorpath_cache = false;
+#else
+ static bool do_vectorpath_cache = true;
+#endif
// Check to see if there's any hints
if (path.shape() == QVectorPath::RectangleHint) {
diff --git a/src/opengl/gl2paintengineex/qtriangulator.cpp b/src/opengl/gl2paintengineex/qtriangulator.cpp
index df7cbc2..f14b0a4 100644
--- a/src/opengl/gl2paintengineex/qtriangulator.cpp
+++ b/src/opengl/gl2paintengineex/qtriangulator.cpp
@@ -65,7 +65,11 @@ QT_BEGIN_NAMESPACE
// Quick sort.
template <class T, class LessThan>
+#ifdef Q_CC_RVCT // RVCT 2.2 doesn't see recursive _static_ template function
+void sort(T *array, int count, LessThan lessThan)
+#else
static void sort(T *array, int count, LessThan lessThan)
+#endif
{
// If the number of elements fall below some threshold, use insertion sort.
const int INSERTION_SORT_LIMIT = 7; // About 7 is fastest on my computer...
@@ -122,7 +126,11 @@ sort_loop_end:
// Quick sort.
template <class T>
+#ifdef Q_CC_RVCT
+void sort(T *array, int count) // RVCT 2.2 doesn't see recursive _static_ template function
+#else
static void sort(T *array, int count)
+#endif
{
// If the number of elements fall below some threshold, use insertion sort.
const int INSERTION_SORT_LIMIT = 25; // About 25 is fastest on my computer...
diff --git a/src/opengl/opengl.pro b/src/opengl/opengl.pro
index d6011cf..0e82467 100644
--- a/src/opengl/opengl.pro
+++ b/src/opengl/opengl.pro
@@ -11,18 +11,18 @@ unix:QMAKE_PKGCONFIG_REQUIRES = QtCore QtGui
include(../qbase.pri)
-!win32:!embedded:!mac:CONFIG += x11
+!win32:!embedded:!mac:!symbian:CONFIG += x11
contains(QT_CONFIG, opengl):CONFIG += opengl
contains(QT_CONFIG, opengles1):CONFIG += opengles1
contains(QT_CONFIG, opengles2):CONFIG += opengles2
contains(QT_CONFIG, egl):CONFIG += egl
HEADERS += qgl.h \
- qgl_p.h \
- qglcolormap.h \
- qglpixelbuffer.h \
+ qgl_p.h \
+ qglcolormap.h \
+ qglpixelbuffer.h \
qglpixelbuffer_p.h \
- qglframebufferobject.h \
+ qglframebufferobject.h \
qglframebufferobject_p.h \
qglextensions_p.h \
qglpaintdevice_p.h \
@@ -30,9 +30,9 @@ HEADERS += qgl.h \
SOURCES += qgl.cpp \
- qglcolormap.cpp \
- qglpixelbuffer.cpp \
- qglframebufferobject.cpp \
+ qglcolormap.cpp \
+ qglpixelbuffer.cpp \
+ qglframebufferobject.cpp \
qglextensions.cpp \
qglpaintdevice.cpp \
qglbuffer.cpp \
@@ -119,7 +119,7 @@ mac {
win32:!wince*: {
DEFINES += QT_NO_EGL
SOURCES += qgl_win.cpp \
- qglpixelbuffer_win.cpp
+ qglpixelbuffer_win.cpp
}
wince*: {
SOURCES += qgl_wince.cpp \
@@ -147,4 +147,14 @@ embedded {
}
}
+symbian {
+ SOURCES += qgl_symbian.cpp \
+ qglpixelbuffer_egl.cpp \
+ qgl_egl.cpp
+
+ HEADERS += qgl_egl_p.h
+
+ symbian:TARGET.UID3 = 0x2002131A
+}
+
INCLUDEPATH += ../3rdparty/harfbuzz/src
diff --git a/src/opengl/qgl.cpp b/src/opengl/qgl.cpp
index 6120a85..9e69816 100644
--- a/src/opengl/qgl.cpp
+++ b/src/opengl/qgl.cpp
@@ -96,7 +96,7 @@
QT_BEGIN_NAMESPACE
-#if defined(Q_WS_X11) || defined(Q_WS_MAC) || defined(Q_WS_QWS)
+#if defined(Q_WS_X11) || defined(Q_WS_MAC) || defined(Q_WS_QWS) || defined(Q_OS_SYMBIAN)
QGLExtensionFuncs QGLContextPrivate::qt_extensionFuncs;
#endif
@@ -1688,6 +1688,10 @@ void QGLContextPrivate::init(QPaintDevice *dev, const QGLFormat &format)
workaround_needsFullClearOnEveryFrame = false;
workaround_brokenFBOReadBack = false;
workaroundsCached = false;
+
+ workaround_brokenTextureFromPixmap = false;
+ workaround_brokenTextureFromPixmap_init = false;
+
for (int i = 0; i < QT_GL_VERTEX_ARRAY_TRACKED_COUNT; ++i)
vertexAttributeArraysEnabledState[i] = false;
}
@@ -1991,7 +1995,7 @@ struct DDSFormat {
option helps preserve this default behavior.
\omitvalue CanFlipNativePixmapBindOption Used by x11 from pixmap to choose
- wether or not it can bind the pixmap upside down or not.
+ whether or not it can bind the pixmap upside down or not.
\omitvalue MemoryManagedBindOption Used by paint engines to
indicate that the pixmap should be memory managed along side with
@@ -2260,7 +2264,7 @@ static void convertToGLFormatHelper(QImage &dst, const QImage &img, GLenum textu
}
}
-#if defined(Q_WS_X11) || defined(Q_WS_MAC) || defined(Q_WS_QWS)
+#if defined(Q_WS_X11) || defined(Q_WS_MAC) || defined(Q_WS_QWS) || defined(Q_OS_SYMBIAN)
QGLExtensionFuncs& QGLContextPrivate::extensionFuncs(const QGLContext *)
{
return qt_extensionFuncs;
@@ -2283,11 +2287,19 @@ QImage QGLContextPrivate::convertToGLFormat(const QImage &image, bool force_prem
QGLTexture *QGLContextPrivate::bindTexture(const QImage &image, GLenum target, GLint format,
QGLContext::BindOptions options)
{
+ Q_Q(QGLContext);
+
const qint64 key = image.cacheKey();
QGLTexture *texture = textureCacheLookup(key, target);
if (texture) {
- glBindTexture(target, texture->id);
- return texture;
+ if (image.paintingActive()) {
+ // A QPainter is active on the image - take the safe route and replace the texture.
+ q->deleteTexture(texture->id);
+ texture = 0;
+ } else {
+ glBindTexture(target, texture->id);
+ return texture;
+ }
}
if (!texture)
@@ -2553,14 +2565,19 @@ QGLTexture *QGLContextPrivate::bindTexture(const QPixmap &pixmap, GLenum target,
}
#else
Q_UNUSED(pd);
- Q_UNUSED(q);
#endif
const qint64 key = pixmap.cacheKey();
QGLTexture *texture = textureCacheLookup(key, target);
if (texture) {
- glBindTexture(target, texture->id);
- return texture;
+ if (pixmap.paintingActive()) {
+ // A QPainter is active on the pixmap - take the safe route and replace the texture.
+ q->deleteTexture(texture->id);
+ texture = 0;
+ } else {
+ glBindTexture(target, texture->id);
+ return texture;
+ }
}
#if defined(Q_WS_X11)
@@ -2570,11 +2587,27 @@ QGLTexture *QGLContextPrivate::bindTexture(const QPixmap &pixmap, GLenum target,
&& xinfo && xinfo->screen() == pixmap.x11Info().screen()
&& target == GL_TEXTURE_2D)
{
- texture = bindTextureFromNativePixmap(const_cast<QPixmap*>(&pixmap), key, options);
- if (texture) {
- texture->options |= QGLContext::MemoryManagedBindOption;
- texture->boundPixmap = pd;
- boundPixmaps.insert(pd, QPixmap(pixmap));
+ if (!workaround_brokenTextureFromPixmap_init) {
+ workaround_brokenTextureFromPixmap_init = true;
+
+ const QByteArray versionString(reinterpret_cast<const char*>(glGetString(GL_VERSION)));
+ const int pos = versionString.indexOf("NVIDIA ");
+
+ if (pos >= 0) {
+ const QByteArray nvidiaVersionString = versionString.mid(pos + strlen("NVIDIA "));
+
+ if (nvidiaVersionString.startsWith("195") || nvidiaVersionString.startsWith("256"))
+ workaround_brokenTextureFromPixmap = true;
+ }
+ }
+
+ if (!workaround_brokenTextureFromPixmap) {
+ texture = bindTextureFromNativePixmap(const_cast<QPixmap*>(&pixmap), key, options);
+ if (texture) {
+ texture->options |= QGLContext::MemoryManagedBindOption;
+ texture->boundPixmap = pd;
+ boundPixmaps.insert(pd, QPixmap(pixmap));
+ }
}
}
#endif
@@ -4177,6 +4210,34 @@ bool QGLWidget::event(QEvent *e)
d->glcx->d_ptr->clearDrawable();
# endif
}
+#elif defined(Q_OS_SYMBIAN)
+ // prevents errors on some systems, where we get a flush to a
+ // hidden widget
+ if (e->type() == QEvent::Hide) {
+ makeCurrent();
+ glFinish();
+ doneCurrent();
+ } else if (e->type() == QEvent::ParentChange) {
+ // if we've reparented a window that has the current context
+ // bound, we need to rebind that context to the new window id
+ if (d->glcx == QGLContext::currentContext())
+ makeCurrent();
+
+ if (testAttribute(Qt::WA_TranslucentBackground))
+ setContext(new QGLContext(d->glcx->requestedFormat(), this));
+ }
+
+ // A re-parent is likely to destroy the Symbian window and re-create it. It is important
+ // that we free the EGL surface _before_ the winID changes - otherwise we can leak.
+ if (e->type() == QEvent::ParentAboutToChange)
+ d->glcx->d_func()->destroyEglSurfaceForDevice();
+
+ if ((e->type() == QEvent::ParentChange) || (e->type() == QEvent::WindowStateChange)) {
+ // The window may have been re-created during re-parent or state change - if so, the EGL
+ // surface will need to be re-created.
+ d->recreateEglSurface();
+ }
+
#endif
return QWidget::event(e);
@@ -4384,6 +4445,11 @@ void QGLWidget::glDraw()
Q_D(QGLWidget);
if (!isValid())
return;
+#ifdef Q_OS_SYMBIAN
+ // Crashes on Symbian if trying to render to invisible surfaces
+ if (!isVisible() && d->glcx->device()->devType() == QInternal::Widget)
+ return;
+#endif
makeCurrent();
#ifndef QT_OPENGL_ES
if (d->glcx->deviceIsPixmap())
diff --git a/src/opengl/qgl_egl.cpp b/src/opengl/qgl_egl.cpp
index 3763926..ebd1169 100644
--- a/src/opengl/qgl_egl.cpp
+++ b/src/opengl/qgl_egl.cpp
@@ -230,7 +230,7 @@ void QGLContext::swapBuffers() const
void QGLContextPrivate::destroyEglSurfaceForDevice()
{
if (eglSurface != EGL_NO_SURFACE) {
-#ifdef Q_WS_X11
+#if defined(Q_WS_X11) || defined(Q_OS_SYMBIAN)
// Make sure we don't call eglDestroySurface on a surface which
// was created for a different winId. This applies only to QGLWidget
// paint device, so make sure this is the one we're operating on
@@ -240,6 +240,7 @@ void QGLContextPrivate::destroyEglSurfaceForDevice()
if (QGLWidget *wgl = qobject_cast<QGLWidget *>(w)) {
if (wgl->d_func()->eglSurfaceWindowId != wgl->winId()) {
qWarning("WARNING: Potential EGL surface leak! Not destroying surface.");
+ eglSurface = EGL_NO_SURFACE;
return;
}
}
diff --git a/src/opengl/qgl_mac.mm b/src/opengl/qgl_mac.mm
index 4d7532e..66fe7d3 100644
--- a/src/opengl/qgl_mac.mm
+++ b/src/opengl/qgl_mac.mm
@@ -804,17 +804,22 @@ void QGLContext::generateFontDisplayLists(const QFont & /* fnt */, int /* listBa
static CFBundleRef qt_getOpenGLBundle()
{
CFBundleRef bundle = 0;
+ CFStringRef urlString = QCFString::toCFStringRef(QLatin1String("/System/Library/Frameworks/OpenGL.framework"));
QCFType<CFURLRef> url = CFURLCreateWithFileSystemPath(kCFAllocatorDefault,
- QCFString::toCFStringRef(QLatin1String("/System/Library/Frameworks/OpenGL.framework")), kCFURLPOSIXPathStyle, false);
+ urlString, kCFURLPOSIXPathStyle, false);
if (url)
bundle = CFBundleCreate(kCFAllocatorDefault, url);
+ CFRelease(urlString);
return bundle;
}
void *QGLContext::getProcAddress(const QString &proc) const
{
- return CFBundleGetFunctionPointerForName(QCFType<CFBundleRef>(qt_getOpenGLBundle()),
- QCFString(proc));
+ CFStringRef procName = QCFString(proc).toCFStringRef(proc);
+ void *result = CFBundleGetFunctionPointerForName(QCFType<CFBundleRef>(qt_getOpenGLBundle()),
+ procName);
+ CFRelease(procName);
+ return result;
}
#ifndef QT_MAC_USE_COCOA
/*****************************************************************************
diff --git a/src/opengl/qgl_p.h b/src/opengl/qgl_p.h
index 32feacd..387c8f7 100644
--- a/src/opengl/qgl_p.h
+++ b/src/opengl/qgl_p.h
@@ -167,6 +167,9 @@ public:
#if defined(Q_WS_X11) && !defined(QT_NO_EGL)
, eglSurfaceWindowId(0)
#endif
+#if defined(Q_OS_SYMBIAN)
+ , eglSurfaceWindowId(0)
+#endif
{
isGLWidget = 1;
}
@@ -208,6 +211,10 @@ public:
#elif defined(Q_WS_QWS)
QWSGLWindowSurface *wsurf;
#endif
+#ifdef Q_OS_SYMBIAN
+ void recreateEglSurface();
+ WId eglSurfaceWindowId;
+#endif
};
class QGLContextResource;
@@ -393,6 +400,9 @@ public:
uint workaround_brokenFBOReadBack : 1;
uint workaroundsCached : 1;
+ uint workaround_brokenTextureFromPixmap : 1;
+ uint workaround_brokenTextureFromPixmap_init : 1;
+
QPaintDevice *paintDevice;
QColor transpColor;
QGLContext *q_ptr;
@@ -414,7 +424,7 @@ public:
static inline QGLExtensionFuncs& extensionFuncs(const QGLContext *ctx) { return ctx->d_ptr->group->extensionFuncs(); }
#endif
-#if defined(Q_WS_X11) || defined(Q_WS_MAC) || defined(Q_WS_QWS)
+#if defined(Q_WS_X11) || defined(Q_WS_MAC) || defined(Q_WS_QWS) || defined(Q_OS_SYMBIAN)
static QGLExtensionFuncs qt_extensionFuncs;
static Q_OPENGL_EXPORT QGLExtensionFuncs& extensionFuncs(const QGLContext *);
#endif
diff --git a/src/opengl/qgl_symbian.cpp b/src/opengl/qgl_symbian.cpp
new file mode 100644
index 0000000..73fe4c9
--- /dev/null
+++ b/src/opengl/qgl_symbian.cpp
@@ -0,0 +1,362 @@
+/****************************************************************************
+**
+** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (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 Technology Preview License Agreement accompanying
+** this package.
+**
+** 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.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+
+#include "qgl.h"
+#include <coemain.h>
+#include <coecntrl.h>
+#include <w32std.h>
+#include <private/qpixmap_s60_p.h>
+#include <private/qimagepixmapcleanuphooks_p.h>
+#include <private/qgl_p.h>
+#include <private/qpaintengine_opengl_p.h>
+#include <private/qwidget_p.h> // to access QWExtra
+#include "qgl_egl_p.h"
+#include "qcolormap.h"
+#include <QDebug>
+
+QT_BEGIN_NAMESPACE
+
+// Turn off "direct to window" rendering if EGL cannot support it.
+#if !defined(EGL_RENDER_BUFFER) || !defined(EGL_SINGLE_BUFFER)
+#if defined(QGL_DIRECT_TO_WINDOW)
+#undef QGL_DIRECT_TO_WINDOW
+#endif
+#endif
+
+// Determine if preserved window contents should be used.
+#if !defined(EGL_SWAP_BEHAVIOR) || !defined(EGL_BUFFER_PRESERVED)
+#if !defined(QGL_NO_PRESERVED_SWAP)
+#define QGL_NO_PRESERVED_SWAP 1
+#endif
+#endif
+
+/*
+ QGLTemporaryContext implementation
+*/
+
+
+class QGLTemporaryContextPrivate
+{
+public:
+ bool initialized;
+ RWindow *window;
+ EGLContext context;
+ EGLSurface surface;
+ EGLDisplay display;
+};
+
+QGLTemporaryContext::QGLTemporaryContext(bool, QWidget *)
+ : d(new QGLTemporaryContextPrivate)
+{
+ d->initialized = false;
+ d->window = 0;
+ d->context = 0;
+ d->surface = 0;
+
+ d->display = d->display = QEgl::display();
+
+ EGLConfig config;
+ int numConfigs = 0;
+ EGLint attribs[] = {
+ EGL_SURFACE_TYPE, EGL_WINDOW_BIT,
+#ifdef QT_OPENGL_ES_2
+ EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT,
+#endif
+ EGL_NONE
+ };
+
+ eglChooseConfig(d->display, attribs, &config, 1, &numConfigs);
+ if (!numConfigs) {
+ qWarning("QGLTemporaryContext: No EGL configurations available.");
+ return;
+ }
+
+ d->window = new RWindow(CCoeEnv::Static()->WsSession());
+ d->window->Construct(CCoeEnv::Static()->RootWin(),(uint)this);
+
+ d->surface = eglCreateWindowSurface(d->display, config, (EGLNativeWindowType) d->window, NULL);
+
+ if (d->surface == EGL_NO_SURFACE) {
+ qWarning("QGLTemporaryContext: Error creating EGL surface.");
+ delete d->window;
+ d->window = 0;
+ return;
+ }
+
+ EGLint contextAttribs[] = {
+#ifdef QT_OPENGL_ES_2
+ EGL_CONTEXT_CLIENT_VERSION, 2,
+#endif
+ EGL_NONE
+ };
+ d->context = eglCreateContext(d->display, config, 0, contextAttribs);
+ if (d->context != EGL_NO_CONTEXT
+ && eglMakeCurrent(d->display, d->surface, d->surface, d->context))
+ {
+ d->initialized = true;
+ } else {
+ qWarning("QGLTemporaryContext: Error creating EGL context.");
+ d->window = 0;
+ return;
+ }
+}
+
+QGLTemporaryContext::~QGLTemporaryContext()
+{
+ if (d->initialized) {
+ eglMakeCurrent(d->display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
+ eglDestroyContext(d->display, d->context);
+ eglDestroySurface(d->display, d->surface);
+ delete d->window;
+ }
+}
+
+bool QGLFormat::hasOpenGLOverlays()
+{
+ return false;
+}
+
+// Chooses the EGL config and creates the EGL context
+bool QGLContext::chooseContext(const QGLContext* shareContext) // almost same as in qgl_x11egl.cpp
+{
+ Q_D(QGLContext);
+
+ if (!device())
+ return false;
+
+ int devType = device()->devType();
+
+ if ((devType != QInternal::Widget) && (devType != QInternal::Pbuffer)) {
+ qWarning("WARNING: Creating a QGLContext not supported on device type %d", devType);
+ return false;
+ }
+
+ // Get the display and initialize it.
+ if (d->eglContext == 0) {
+ d->eglContext = new QEglContext();
+ d->ownsEglContext = true;
+ d->eglContext->setApi(QEgl::OpenGL);
+
+ // If the device is a widget with WA_TranslucentBackground set, make sure the glFormat
+ // has the alpha channel option set:
+ if (devType == QInternal::Widget) {
+ QWidget* widget = static_cast<QWidget*>(device());
+ if (widget->testAttribute(Qt::WA_TranslucentBackground))
+ d->glFormat.setAlpha(true);
+ }
+
+ // Construct the configuration we need for this surface.
+ QEglProperties configProps;
+ configProps.setDeviceType(devType);
+ configProps.setPaintDeviceFormat(device());
+ configProps.setRenderableType(QEgl::OpenGL);
+ configProps.setValue(EGL_SURFACE_TYPE, EGL_WINDOW_BIT|EGL_SWAP_BEHAVIOR_PRESERVED_BIT);
+
+ qt_eglproperties_set_glformat(configProps, d->glFormat);
+
+ if (!d->eglContext->chooseConfig(configProps, QEgl::BestPixelFormat)) {
+ delete d->eglContext;
+ d->eglContext = 0;
+ return false;
+ }
+
+ // Create a new context for the configuration.
+ QEglContext* eglSharedContext = shareContext ? shareContext->d_func()->eglContext : 0;
+ if (!d->eglContext->createContext(eglSharedContext)) {
+ delete d->eglContext;
+ d->eglContext = 0;
+ return false;
+ }
+ d->sharing = d->eglContext->isSharing();
+ if (d->sharing && shareContext)
+ const_cast<QGLContext *>(shareContext)->d_func()->sharing = true;
+ }
+
+ // Inform the higher layers about the actual format properties
+ qt_glformat_from_eglconfig(d->glFormat, d->eglContext->config());
+
+ // Do don't create the EGLSurface for everything.
+ // QWidget - yes, create the EGLSurface and store it in QGLContextPrivate::eglSurface
+ // QGLWidget - yes, create the EGLSurface and store it in QGLContextPrivate::eglSurface
+ // QGLPixelBuffer - no, it creates the surface itself and stores it in QGLPixelBufferPrivate::pbuf
+
+ if (devType == QInternal::Widget) {
+ if (d->eglSurface != EGL_NO_SURFACE)
+ eglDestroySurface(d->eglContext->display(), d->eglSurface);
+
+ d->eglSurface = QEgl::createSurface(device(), d->eglContext->config());
+
+#if !defined(QGL_NO_PRESERVED_SWAP)
+ eglGetError(); // Clear error state first.
+ eglSurfaceAttrib(QEgl::display(), d->eglSurface,
+ EGL_SWAP_BEHAVIOR, EGL_BUFFER_PRESERVED);
+ if (eglGetError() != EGL_SUCCESS) {
+ qWarning("QGLContext: could not enable preserved swap");
+ }
+#endif
+
+ setWindowCreated(true);
+ }
+
+ return true;
+}
+
+void QGLWidget::resizeEvent(QResizeEvent *)
+{
+ Q_D(QGLWidget);
+ if (!isValid())
+ return;
+
+ if (QGLContext::currentContext())
+ doneCurrent();
+
+ // Symbian needs to recreate the surface on resize.
+ d->recreateEglSurface();
+
+ 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;
+
+ bool createFailed = false;
+ if (!d->glcx->isValid()) {
+ // Create the QGLContext here, which in turn chooses the EGL config
+ // and creates the EGL context:
+ if (!d->glcx->create(shareContext ? shareContext : oldcx))
+ createFailed = true;
+ }
+ if (createFailed) {
+ if (deleteOldContext)
+ delete oldcx;
+ return;
+ }
+
+ d->eglSurfaceWindowId = winId(); // Remember the window id we created the surface for
+}
+
+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");
+ }
+}
+
+void QGLWidgetPrivate::cleanupColormaps()
+{
+}
+
+const QGLColormap & QGLWidget::colormap() const
+{
+ return d_func()->cmap;
+}
+
+void QGLWidget::setColormap(const QGLColormap &)
+{
+}
+
+void QGLWidgetPrivate::recreateEglSurface()
+{
+ Q_Q(QGLWidget);
+
+ WId currentId = q->winId();
+
+ if (glcx->d_func()->eglSurface != EGL_NO_SURFACE) {
+ eglDestroySurface(glcx->d_func()->eglContext->display(),
+ glcx->d_func()->eglSurface);
+ }
+
+ glcx->d_func()->eglSurface = QEgl::createSurface(glcx->device(),
+ glcx->d_func()->eglContext->config());
+
+#if !defined(QGL_NO_PRESERVED_SWAP)
+ eglGetError(); // Clear error state first.
+ eglSurfaceAttrib(QEgl::display(), glcx->d_func()->eglSurface,
+ EGL_SWAP_BEHAVIOR, EGL_BUFFER_PRESERVED);
+ if (eglGetError() != EGL_SUCCESS) {
+ qWarning("QGLContext: could not enable preserved swap");
+ }
+#endif
+
+ eglSurfaceWindowId = currentId;
+}
+
+QT_END_NAMESPACE
+
diff --git a/src/opengl/qglextensions.cpp b/src/opengl/qglextensions.cpp
index 8e2bbd4..6aec8ae 100644
--- a/src/opengl/qglextensions.cpp
+++ b/src/opengl/qglextensions.cpp
@@ -255,6 +255,10 @@ bool qt_resolve_glsl_extensions(QGLContext *ctx)
glFramebufferTextureLayerEXT = (_glFramebufferTextureLayerEXT) ctx->getProcAddress(QLatin1String("glFramebufferTextureLayerEXT"));
glFramebufferTextureFaceEXT = (_glFramebufferTextureFaceEXT) ctx->getProcAddress(QLatin1String("glFramebufferTextureFaceEXT"));
+ // Must at least have the FragmentShader extension to continue.
+ if (!(QGLExtensions::glExtensions() & QGLExtensions::FragmentShader))
+ return false;
+
glCreateShader = (_glCreateShader) ctx->getProcAddress(QLatin1String("glCreateShader"));
if (glCreateShader) {
glShaderSource = (_glShaderSource) ctx->getProcAddress(QLatin1String("glShaderSource"));
diff --git a/src/opengl/qglframebufferobject.cpp b/src/opengl/qglframebufferobject.cpp
index deffc20..9b8a3d1 100644
--- a/src/opengl/qglframebufferobject.cpp
+++ b/src/opengl/qglframebufferobject.cpp
@@ -445,11 +445,11 @@ void QGLFramebufferObjectPrivate::init(QGLFramebufferObject *q, const QSize &sz,
GLint maxSamples;
glGetIntegerv(GL_MAX_SAMPLES_EXT, &maxSamples);
- samples = qBound(1, int(samples), int(maxSamples));
+ samples = qBound(0, int(samples), int(maxSamples));
glGenRenderbuffers(1, &color_buffer);
glBindRenderbuffer(GL_RENDERBUFFER_EXT, color_buffer);
- if (glRenderbufferStorageMultisampleEXT) {
+ if (glRenderbufferStorageMultisampleEXT && samples > 0) {
glRenderbufferStorageMultisampleEXT(GL_RENDERBUFFER_EXT, samples,
internal_format, size.width(), size.height());
} else {
diff --git a/src/opengl/qglshaderprogram.cpp b/src/opengl/qglshaderprogram.cpp
index c7689b8..74382b0 100644
--- a/src/opengl/qglshaderprogram.cpp
+++ b/src/opengl/qglshaderprogram.cpp
@@ -2121,7 +2121,7 @@ void QGLShaderProgram::setUniformValue(int location, const QSize& size)
Q_D(QGLShaderProgram);
Q_UNUSED(d);
if (location != -1) {
- GLfloat values[4] = {GLfloat(size.width()), GLfloat(size.width())};
+ GLfloat values[4] = {GLfloat(size.width()), GLfloat(size.height())};
glUniform2fv(location, 1, values);
}
}
diff --git a/src/opengl/qpixmapdata_gl.cpp b/src/opengl/qpixmapdata_gl.cpp
index 653e805..1efd398 100644
--- a/src/opengl/qpixmapdata_gl.cpp
+++ b/src/opengl/qpixmapdata_gl.cpp
@@ -367,7 +367,7 @@ void QGLPixmapData::ensureCreated() const
}
void QGLPixmapData::fromImage(const QImage &image,
- Qt::ImageConversionFlags /*flags*/)
+ Qt::ImageConversionFlags flags)
{
if (image.size() == QSize(w, h))
setSerialNumber(++qt_gl_pixmap_serial);
@@ -381,7 +381,9 @@ void QGLPixmapData::fromImage(const QImage &image,
if (qApp->desktop()->depth() == 16)
format = QImage::Format_RGB16;
- if (image.hasAlphaChannel() && const_cast<QImage &>(image).data_ptr()->checkForAlphaPixels())
+ if (image.hasAlphaChannel()
+ && ((flags & Qt::NoOpaqueDetection)
+ || const_cast<QImage &>(image).data_ptr()->checkForAlphaPixels()))
format = QImage::Format_ARGB32_Premultiplied;;
m_source = image.convertToFormat(format);
diff --git a/src/opengl/qwindowsurface_gl.cpp b/src/opengl/qwindowsurface_gl.cpp
index 6b82ed3..b86fb78 100644
--- a/src/opengl/qwindowsurface_gl.cpp
+++ b/src/opengl/qwindowsurface_gl.cpp
@@ -199,6 +199,7 @@ public:
return widget;
}
+ // destroys the share widget and prevents recreation
void cleanup() {
QGLWidget *w = widget;
cleanedUp = true;
@@ -206,6 +207,20 @@ public:
delete w;
}
+ // destroys the share widget, but allows it to be recreated later on
+ void destroy() {
+ if (cleanedUp)
+ return;
+
+ QGLWidget *w = widget;
+
+ // prevent potential recursions
+ cleanedUp = true;
+ widget = 0;
+ delete w;
+ cleanedUp = false;
+ }
+
static bool cleanedUp;
private:
@@ -233,6 +248,10 @@ QGLWidget* qt_gl_share_widget()
return _qt_gl_share_widget()->shareWidget();
}
+void qt_destroy_gl_share_widget()
+{
+ _qt_gl_share_widget()->destroy();
+}
struct QGLWindowSurfacePrivate
{
diff --git a/src/opengl/qwindowsurface_gl_p.h b/src/opengl/qwindowsurface_gl_p.h
index 5e670fe..ffc2e86 100644
--- a/src/opengl/qwindowsurface_gl_p.h
+++ b/src/opengl/qwindowsurface_gl_p.h
@@ -67,6 +67,7 @@ class QWidget;
struct QGLWindowSurfacePrivate;
Q_OPENGL_EXPORT QGLWidget* qt_gl_share_widget();
+Q_OPENGL_EXPORT void qt_destroy_gl_share_widget();
class QGLWindowSurfaceGLPaintDevice : public QGLPaintDevice
{