summaryrefslogtreecommitdiffstats
path: root/src/opengl
diff options
context:
space:
mode:
Diffstat (limited to 'src/opengl')
-rw-r--r--src/opengl/gl2paintengineex/qgl2pexvertexarray_p.h4
-rw-r--r--src/opengl/gl2paintengineex/qglengineshadermanager.cpp10
-rw-r--r--src/opengl/gl2paintengineex/qglengineshadersource_p.h1
-rw-r--r--src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp35
-rw-r--r--src/opengl/gl2paintengineex/qpaintengineex_opengl2_p.h4
-rw-r--r--src/opengl/gl2paintengineex/qtextureglyphcache_gl.cpp87
-rw-r--r--src/opengl/gl2paintengineex/qtextureglyphcache_gl_p.h2
-rw-r--r--src/opengl/gl2paintengineex/qtriangulatingstroker.cpp5
-rw-r--r--src/opengl/gl2paintengineex/qtriangulatingstroker_p.h1
-rw-r--r--src/opengl/gl2paintengineex/qtriangulator.cpp12
-rw-r--r--src/opengl/opengl.pro1
-rw-r--r--src/opengl/qgl.cpp154
-rw-r--r--src/opengl/qgl.h5
-rw-r--r--src/opengl/qgl_egl.cpp21
-rw-r--r--src/opengl/qgl_p.h54
-rw-r--r--src/opengl/qgl_x11.cpp376
-rw-r--r--src/opengl/qglbuffer.cpp92
-rw-r--r--src/opengl/qglbuffer.h9
-rw-r--r--src/opengl/qglframebufferobject.cpp30
-rw-r--r--src/opengl/qglframebufferobject.h2
-rw-r--r--src/opengl/qglpaintdevice.cpp5
-rw-r--r--src/opengl/qglpixmapfilter.cpp9
-rw-r--r--src/opengl/qpaintengine_opengl.cpp12
23 files changed, 651 insertions, 280 deletions
diff --git a/src/opengl/gl2paintengineex/qgl2pexvertexarray_p.h b/src/opengl/gl2paintengineex/qgl2pexvertexarray_p.h
index adc69ee..46029b9 100644
--- a/src/opengl/gl2paintengineex/qgl2pexvertexarray_p.h
+++ b/src/opengl/gl2paintengineex/qgl2pexvertexarray_p.h
@@ -100,8 +100,10 @@ class QGL2PEXVertexArray
{
public:
QGL2PEXVertexArray() :
+ vertexArray(0), vertexArrayStops(0),
maxX(-2e10), maxY(-2e10), minX(2e10), minY(2e10),
- boundingRectDirty(true) {}
+ boundingRectDirty(true)
+ { }
inline void addRect(const QRectF &rect)
{
diff --git a/src/opengl/gl2paintengineex/qglengineshadermanager.cpp b/src/opengl/gl2paintengineex/qglengineshadermanager.cpp
index ac25597..40b3641 100644
--- a/src/opengl/gl2paintengineex/qglengineshadermanager.cpp
+++ b/src/opengl/gl2paintengineex/qglengineshadermanager.cpp
@@ -266,10 +266,12 @@ QGLEngineShaderProg *QGLEngineSharedShaders::findProgramInCache(const QGLEngineS
do {
QByteArray source;
- source.append(qShaderSnippets[prog.mainFragShader]);
- source.append(qShaderSnippets[prog.srcPixelFragShader]);
+ // Insert the custom stage before the srcPixel shader to work around an ATI driver bug
+ // where you cannot forward declare a function that takes a sampler as argument.
if (prog.srcPixelFragShader == CustomImageSrcFragmentShader)
source.append(prog.customStageSource);
+ source.append(qShaderSnippets[prog.mainFragShader]);
+ source.append(qShaderSnippets[prog.srcPixelFragShader]);
if (prog.compositionFragShader)
source.append(qShaderSnippets[prog.compositionFragShader]);
if (prog.maskFragShader)
@@ -777,8 +779,8 @@ bool QGLEngineShaderManager::useCorrectShaderProg()
// doesn't use are disabled)
QGLContextPrivate* ctx_d = ctx->d_func();
ctx_d->setVertexAttribArrayEnabled(QT_VERTEX_COORDS_ATTR, true);
- ctx_d->setVertexAttribArrayEnabled(QT_TEXTURE_COORDS_ATTR, currentShaderProg->useTextureCoords);
- ctx_d->setVertexAttribArrayEnabled(QT_OPACITY_ATTR, currentShaderProg->useOpacityAttribute);
+ ctx_d->setVertexAttribArrayEnabled(QT_TEXTURE_COORDS_ATTR, currentShaderProg && currentShaderProg->useTextureCoords);
+ ctx_d->setVertexAttribArrayEnabled(QT_OPACITY_ATTR, currentShaderProg && currentShaderProg->useOpacityAttribute);
shaderProgNeedsChanging = false;
return true;
diff --git a/src/opengl/gl2paintengineex/qglengineshadersource_p.h b/src/opengl/gl2paintengineex/qglengineshadersource_p.h
index 8dba951..a7ece0f 100644
--- a/src/opengl/gl2paintengineex/qglengineshadersource_p.h
+++ b/src/opengl/gl2paintengineex/qglengineshadersource_p.h
@@ -351,7 +351,6 @@ static const char* const qglslImageSrcFragmentShader = "\n\
static const char* const qglslCustomSrcFragmentShader = "\n\
varying highp vec2 textureCoords; \n\
uniform lowp sampler2D imageTexture; \n\
- lowp vec4 customShader(lowp sampler2D texture, highp vec2 coords); \n\
lowp vec4 srcPixel() \n\
{ \n\
return customShader(imageTexture, textureCoords); \n\
diff --git a/src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp b/src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp
index 4461358..ee49a3d 100644
--- a/src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp
+++ b/src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp
@@ -1333,8 +1333,16 @@ void QGL2PaintEngineEx::drawStaticTextItem(QStaticTextItem *textItem)
QFontEngineGlyphCache::Type glyphType = textItem->fontEngine->glyphFormat >= 0
? QFontEngineGlyphCache::Type(textItem->fontEngine->glyphFormat)
: d->glyphCacheType;
+ if (glyphType == QFontEngineGlyphCache::Raster_RGBMask) {
+ if (d->device->alphaRequested() || state()->matrix.type() > QTransform::TxTranslate
+ || (state()->composition_mode != QPainter::CompositionMode_Source
+ && state()->composition_mode != QPainter::CompositionMode_SourceOver))
+ {
+ glyphType = QFontEngineGlyphCache::Raster_A8;
+ }
+ }
- d->drawCachedGlyphs(glyphType, textItem, true);
+ d->drawCachedGlyphs(glyphType, textItem);
}
bool QGL2PaintEngineEx::drawTexture(const QRectF &dest, GLuint textureId, const QSize &size, const QRectF &src)
@@ -1401,14 +1409,14 @@ void QGL2PaintEngineEx::drawTextItem(const QPointF &p, const QTextItem &textItem
{
QStaticTextItem staticTextItem;
- staticTextItem.chars = ti.chars;
+ staticTextItem.chars = const_cast<QChar *>(ti.chars);
staticTextItem.fontEngine = ti.fontEngine;
staticTextItem.glyphs = glyphs.data();
staticTextItem.numChars = ti.num_chars;
staticTextItem.numGlyphs = glyphs.size();
staticTextItem.glyphPositions = positions.data();
- d->drawCachedGlyphs(glyphType, &staticTextItem, false);
+ d->drawCachedGlyphs(glyphType, &staticTextItem);
}
return;
}
@@ -1439,21 +1447,16 @@ namespace {
// #define QT_OPENGL_DRAWCACHEDGLYPHS_INDEX_ARRAY_VBO
void QGL2PaintEngineExPrivate::drawCachedGlyphs(QFontEngineGlyphCache::Type glyphType,
- QStaticTextItem *staticTextItem,
- bool includeMatrixInCache)
+ QStaticTextItem *staticTextItem)
{
Q_Q(QGL2PaintEngineEx);
QOpenGL2PaintEngineState *s = q->state();
QGLTextureGlyphCache *cache =
- (QGLTextureGlyphCache *) staticTextItem->fontEngine->glyphCache(ctx, glyphType,
- includeMatrixInCache
- ? s->matrix
- : QTransform());
+ (QGLTextureGlyphCache *) staticTextItem->fontEngine->glyphCache(ctx, glyphType, QTransform());
if (!cache || cache->cacheType() != glyphType) {
- cache = new QGLTextureGlyphCache(ctx, glyphType,
- includeMatrixInCache ? s->matrix : QTransform());
+ cache = new QGLTextureGlyphCache(ctx, glyphType, QTransform());
staticTextItem->fontEngine->setGlyphCache(ctx, cache);
}
@@ -1561,13 +1564,6 @@ void QGL2PaintEngineExPrivate::drawCachedGlyphs(QFontEngineGlyphCache::Type glyp
QBrush pensBrush = q->state()->pen.brush();
setBrush(pensBrush);
- // When painting a QStaticTextItem, the glyph positions are already in device coordinates,
- // therefore we temporarily set an identity matrix on the painter for the draw call to
- // avoid transforming the positions twice.
- QTransform old = s->matrix;
- if (includeMatrixInCache)
- s->matrix = QTransform();
-
if (glyphType == QFontEngineGlyphCache::Raster_RGBMask) {
// Subpixel antialiasing without gamma correction
@@ -1664,9 +1660,6 @@ void QGL2PaintEngineExPrivate::drawCachedGlyphs(QFontEngineGlyphCache::Type glyp
#else
glDrawElements(GL_TRIANGLE_STRIP, 6 * staticTextItem->numGlyphs, GL_UNSIGNED_SHORT, elementIndices.data());
#endif
-
- if (includeMatrixInCache)
- s->matrix = old;
}
void QGL2PaintEngineEx::drawPixmapFragments(const QPainter::PixmapFragment *fragments, int fragmentCount, const QPixmap &pixmap,
diff --git a/src/opengl/gl2paintengineex/qpaintengineex_opengl2_p.h b/src/opengl/gl2paintengineex/qpaintengineex_opengl2_p.h
index 6ba0c42..59b90d8 100644
--- a/src/opengl/gl2paintengineex/qpaintengineex_opengl2_p.h
+++ b/src/opengl/gl2paintengineex/qpaintengineex_opengl2_p.h
@@ -177,6 +177,7 @@ public:
ctx(0),
useSystemClip(true),
elementIndicesVBOId(0),
+ opacityArray(0),
snapToPixelGrid(false),
addOffset(false),
nativePaintingActive(false),
@@ -201,8 +202,7 @@ public:
void drawTexture(const QGLRect& dest, const QGLRect& src, const QSize &textureSize, bool opaque, bool pattern = false);
void drawPixmapFragments(const QPainter::PixmapFragment *fragments, int fragmentCount, const QPixmap &pixmap,
QPainter::PixmapFragmentHints hints);
- void drawCachedGlyphs(QFontEngineGlyphCache::Type glyphType, QStaticTextItem *staticTextItem,
- bool includeMatrixInCache);
+ void drawCachedGlyphs(QFontEngineGlyphCache::Type glyphType, QStaticTextItem *staticTextItem);
// Calls glVertexAttributePointer if the pointer has changed
inline void setVertexAttributePointer(unsigned int arrayIndex, const GLfloat *pointer);
diff --git a/src/opengl/gl2paintengineex/qtextureglyphcache_gl.cpp b/src/opengl/gl2paintengineex/qtextureglyphcache_gl.cpp
index 994c1c9..5371c5e 100644
--- a/src/opengl/gl2paintengineex/qtextureglyphcache_gl.cpp
+++ b/src/opengl/gl2paintengineex/qtextureglyphcache_gl.cpp
@@ -42,6 +42,10 @@
#include "qtextureglyphcache_gl_p.h"
#include "qpaintengineex_opengl2_p.h"
+#if defined QT_OPENGL_ES_2 && !defined(QT_NO_EGL)
+#include "private/qeglcontext_p.h"
+#endif
+
QT_BEGIN_NAMESPACE
#ifdef Q_WS_WIN
@@ -49,12 +53,19 @@ extern Q_GUI_EXPORT bool qt_cleartype_enabled;
#endif
QGLTextureGlyphCache::QGLTextureGlyphCache(QGLContext *context, QFontEngineGlyphCache::Type type, const QTransform &matrix)
- : QTextureGlyphCache(type, matrix)
+ : QImageTextureGlyphCache(type, matrix)
, ctx(context)
, m_width(0)
, m_height(0)
{
- glGenFramebuffers(1, &m_fbo);
+ // broken FBO readback is a bug in the SGX 1.3 and 1.4 drivers for the N900 where
+ // copying between FBO's is broken if the texture is either GL_ALPHA or POT. The
+ // workaround is to use a system-memory copy of the glyph cache for this device.
+ // Switching to NPOT and GL_RGBA would both cost a lot more graphics memory and
+ // be slower, so that is not desireable.
+ if (!ctx->d_ptr->workaround_brokenFBOReadBack)
+ glGenFramebuffers(1, &m_fbo);
+
connect(QGLSignalProxy::instance(), SIGNAL(aboutToDestroyContext(const QGLContext*)),
SLOT(contextDestroyed(const QGLContext*)));
}
@@ -63,7 +74,9 @@ QGLTextureGlyphCache::~QGLTextureGlyphCache()
{
if (ctx) {
QGLShareContextScope scope(ctx);
- glDeleteFramebuffers(1, &m_fbo);
+
+ if (!ctx->d_ptr->workaround_brokenFBOReadBack)
+ glDeleteFramebuffers(1, &m_fbo);
if (m_width || m_height)
glDeleteTextures(1, &m_texture);
@@ -72,6 +85,18 @@ QGLTextureGlyphCache::~QGLTextureGlyphCache()
void QGLTextureGlyphCache::createTextureData(int width, int height)
{
+ // create in QImageTextureGlyphCache baseclass is meant to be called
+ // only to create the initial image and does not preserve the content,
+ // so we don't call when this function is called from resize.
+ if (ctx->d_ptr->workaround_brokenFBOReadBack && image().isNull())
+ QImageTextureGlyphCache::createTextureData(width, height);
+
+ // Make the lower glyph texture size 16 x 16.
+ if (width < 16)
+ width = 16;
+ if (height < 16)
+ height = 16;
+
glGenTextures(1, &m_texture);
glBindTexture(GL_TEXTURE_2D, m_texture);
@@ -93,14 +118,28 @@ void QGLTextureGlyphCache::createTextureData(int width, int height)
void QGLTextureGlyphCache::resizeTextureData(int width, int height)
{
- // ### the QTextureGlyphCache API needs to be reworked to allow
- // ### resizeTextureData to fail
-
int oldWidth = m_width;
int oldHeight = m_height;
+ // Make the lower glyph texture size 16 x 16.
+ if (width < 16)
+ width = 16;
+ if (height < 16)
+ height = 16;
+
GLuint oldTexture = m_texture;
createTextureData(width, height);
+
+ if (ctx->d_ptr->workaround_brokenFBOReadBack) {
+ QImageTextureGlyphCache::resizeTextureData(width, height);
+ Q_ASSERT(image().depth() == 8);
+ glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, oldWidth, oldHeight, GL_ALPHA, GL_UNSIGNED_BYTE, image().constBits());
+ glDeleteTextures(1, &oldTexture);
+ return;
+ }
+
+ // ### the QTextureGlyphCache API needs to be reworked to allow
+ // ### resizeTextureData to fail
glBindFramebuffer(GL_FRAMEBUFFER_EXT, m_fbo);
@@ -159,20 +198,7 @@ void QGLTextureGlyphCache::resizeTextureData(int width, int height)
glBindTexture(GL_TEXTURE_2D, m_texture);
-#ifdef QT_OPENGL_ES_2
- QDataBuffer<uchar> buffer(4*oldWidth*oldHeight);
- buffer.resize(4*oldWidth*oldHeight);
- glReadPixels(0, 0, oldWidth, oldHeight, GL_RGBA, GL_UNSIGNED_BYTE, buffer.data());
-
- // do an in-place conversion from GL_RGBA to GL_ALPHA
- for (int i=0; i<oldWidth*oldHeight; ++i)
- buffer.data()[i] = buffer.at(4*i + 3);
-
- glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, oldWidth, oldHeight,
- GL_ALPHA, GL_UNSIGNED_BYTE, buffer.data());
-#else
glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, oldWidth, oldHeight);
-#endif
glFramebufferRenderbuffer(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT,
GL_RENDERBUFFER_EXT, 0);
@@ -187,6 +213,21 @@ void QGLTextureGlyphCache::resizeTextureData(int width, int height)
void QGLTextureGlyphCache::fillTexture(const Coord &c, glyph_t glyph)
{
+ if (ctx->d_ptr->workaround_brokenFBOReadBack) {
+ QImageTextureGlyphCache::fillTexture(c, glyph);
+
+ glBindTexture(GL_TEXTURE_2D, m_texture);
+ const QImage &texture = image();
+ const uchar *bits = texture.constBits();
+ bits += c.y * texture.bytesPerLine() + c.x;
+ for (int i=0; i<c.h; ++i) {
+ glTexSubImage2D(GL_TEXTURE_2D, 0, c.x, c.y + i, c.w, 1, GL_ALPHA, GL_UNSIGNED_BYTE, bits);
+ bits += texture.bytesPerLine();
+ }
+
+ return;
+ }
+
QImage mask = textureMapForGlyph(glyph);
const int maskWidth = mask.width();
const int maskHeight = mask.height();
@@ -237,13 +278,7 @@ void QGLTextureGlyphCache::fillTexture(const Coord &c, glyph_t glyph)
int QGLTextureGlyphCache::glyphMargin() const
{
-#if defined(Q_WS_MAC)
- return 2;
-#elif defined (Q_WS_X11)
- return 0;
-#else
- return m_type == QFontEngineGlyphCache::Raster_RGBMask ? 2 : 0;
-#endif
+ return 1;
}
int QGLTextureGlyphCache::glyphPadding() const
diff --git a/src/opengl/gl2paintengineex/qtextureglyphcache_gl_p.h b/src/opengl/gl2paintengineex/qtextureglyphcache_gl_p.h
index 75c2bb1..84e9021 100644
--- a/src/opengl/gl2paintengineex/qtextureglyphcache_gl_p.h
+++ b/src/opengl/gl2paintengineex/qtextureglyphcache_gl_p.h
@@ -62,7 +62,7 @@ QT_BEGIN_NAMESPACE
class QGL2PaintEngineExPrivate;
-class Q_OPENGL_EXPORT QGLTextureGlyphCache : public QObject, public QTextureGlyphCache
+class Q_OPENGL_EXPORT QGLTextureGlyphCache : public QObject, public QImageTextureGlyphCache
{
Q_OBJECT
public:
diff --git a/src/opengl/gl2paintengineex/qtriangulatingstroker.cpp b/src/opengl/gl2paintengineex/qtriangulatingstroker.cpp
index f677ce1..9bc099d 100644
--- a/src/opengl/gl2paintengineex/qtriangulatingstroker.cpp
+++ b/src/opengl/gl2paintengineex/qtriangulatingstroker.cpp
@@ -481,7 +481,8 @@ static void qdashprocessor_cubicTo(qreal, qreal, qreal, qreal, qreal, qreal, voi
}
QDashedStrokeProcessor::QDashedStrokeProcessor()
- : m_dash_stroker(0), m_inv_scale(1)
+ : m_points(0), m_types(0),
+ m_dash_stroker(0), m_inv_scale(1)
{
m_dash_stroker.setMoveToHook(qdashprocessor_moveTo);
m_dash_stroker.setLineToHook(qdashprocessor_lineTo);
@@ -499,6 +500,8 @@ void QDashedStrokeProcessor::process(const QVectorPath &path, const QPen &pen, c
m_points.reset();
m_types.reset();
+ m_points.reserve(path.elementCount());
+ m_types.reserve(path.elementCount());
qreal width = qpen_widthf(pen);
if (width == 0)
diff --git a/src/opengl/gl2paintengineex/qtriangulatingstroker_p.h b/src/opengl/gl2paintengineex/qtriangulatingstroker_p.h
index 956d7cc..ab27ed6 100644
--- a/src/opengl/gl2paintengineex/qtriangulatingstroker_p.h
+++ b/src/opengl/gl2paintengineex/qtriangulatingstroker_p.h
@@ -54,6 +54,7 @@ QT_BEGIN_NAMESPACE
class QTriangulatingStroker
{
public:
+ QTriangulatingStroker() : m_vertices(0) {}
void process(const QVectorPath &path, const QPen &pen, const QRectF &clip);
inline int vertexCount() const { return m_vertices.size(); }
diff --git a/src/opengl/gl2paintengineex/qtriangulator.cpp b/src/opengl/gl2paintengineex/qtriangulator.cpp
index ce917ff..df7cbc2 100644
--- a/src/opengl/gl2paintengineex/qtriangulator.cpp
+++ b/src/opengl/gl2paintengineex/qtriangulator.cpp
@@ -510,6 +510,7 @@ template <class T>
class QMaxHeap
{
public:
+ QMaxHeap() : m_data(0) {}
inline int size() const {return m_data.size();}
inline bool empty() const {return m_data.isEmpty();}
inline bool isEmpty() const {return m_data.isEmpty();}
@@ -1299,7 +1300,8 @@ public:
class ComplexToSimple
{
public:
- inline ComplexToSimple(QTriangulator *parent) : m_parent(parent) { }
+ inline ComplexToSimple(QTriangulator *parent) : m_parent(parent),
+ m_edges(0), m_events(0), m_splits(0) { }
void decompose();
private:
struct Edge
@@ -1412,7 +1414,7 @@ public:
class SimpleToMonotone
{
public:
- inline SimpleToMonotone(QTriangulator *parent) : m_parent(parent) { }
+ inline SimpleToMonotone(QTriangulator *parent) : m_parent(parent), m_edges(0), m_upperVertex(0) { }
void decompose();
private:
enum VertexType {MergeVertex, EndVertex, RegularVertex, StartVertex, SplitVertex};
@@ -1486,7 +1488,7 @@ public:
int m_length;
};
- inline QTriangulator() { }
+ inline QTriangulator() : m_vertices(0) { }
// Call this only once.
void initialize(const qreal *polygon, int count, uint hint, const QTransform &matrix);
@@ -2709,7 +2711,7 @@ void QTriangulator::SimpleToMonotone::monotoneDecomposition()
return;
Q_ASSERT(!m_edgeList.root);
- QDataBuffer<QPair<int, int> > diagonals;
+ QDataBuffer<QPair<int, int> > diagonals(m_upperVertex.size());
int i = 0;
for (int index = 1; index < m_edges.size(); ++index) {
@@ -2853,7 +2855,7 @@ bool QTriangulator::SimpleToMonotone::CompareVertices::operator () (int i, int j
void QTriangulator::MonotoneToTriangles::decompose()
{
QVector<quint32> result;
- QDataBuffer<int> stack;
+ QDataBuffer<int> stack(m_parent->m_indices.size());
m_first = 0;
// Require at least three more indices.
while (m_first + 3 <= m_parent->m_indices.size()) {
diff --git a/src/opengl/opengl.pro b/src/opengl/opengl.pro
index 6670d14..97c12b3 100644
--- a/src/opengl/opengl.pro
+++ b/src/opengl/opengl.pro
@@ -5,6 +5,7 @@ DEFINES += QT_BUILD_OPENGL_LIB
DEFINES += QT_NO_USING_NAMESPACE
win32-msvc*|win32-icc:QMAKE_LFLAGS += /BASE:0x63000000
solaris-cc*:QMAKE_CXXFLAGS_RELEASE -= -O2
+irix-cc*:QMAKE_CXXFLAGS += -no_prelink -ptused
unix:QMAKE_PKGCONFIG_REQUIRES = QtCore QtGui
diff --git a/src/opengl/qgl.cpp b/src/opengl/qgl.cpp
index 634231d..a43f1d4 100644
--- a/src/opengl/qgl.cpp
+++ b/src/opengl/qgl.cpp
@@ -91,6 +91,7 @@
#include "qcolormap.h"
#include "qfile.h"
#include "qlibrary.h"
+#include <qmutex.h>
QT_BEGIN_NAMESPACE
@@ -1255,6 +1256,8 @@ QGLFormat::OpenGLVersionFlags Q_AUTOTEST_EXPORT qOpenGLVersionFlagsFromString(co
QGLFormat::OpenGL_Version_2_1 |
QGLFormat::OpenGL_Version_3_0;
switch (versionString[2].toAscii()) {
+ case '3':
+ versionFlags |= QGLFormat::OpenGL_Version_3_3;
case '2':
versionFlags |= QGLFormat::OpenGL_Version_3_2;
case '1':
@@ -1263,9 +1266,23 @@ QGLFormat::OpenGLVersionFlags Q_AUTOTEST_EXPORT qOpenGLVersionFlagsFromString(co
break;
default:
versionFlags |= QGLFormat::OpenGL_Version_3_1 |
- QGLFormat::OpenGL_Version_3_2;
+ QGLFormat::OpenGL_Version_3_2 |
+ QGLFormat::OpenGL_Version_3_3;
break;
}
+ } else if (versionString.startsWith(QLatin1String("4."))) {
+ versionFlags |= QGLFormat::OpenGL_Version_1_1 |
+ QGLFormat::OpenGL_Version_1_2 |
+ QGLFormat::OpenGL_Version_1_3 |
+ QGLFormat::OpenGL_Version_1_4 |
+ QGLFormat::OpenGL_Version_1_5 |
+ QGLFormat::OpenGL_Version_2_0 |
+ QGLFormat::OpenGL_Version_2_1 |
+ QGLFormat::OpenGL_Version_3_0 |
+ QGLFormat::OpenGL_Version_3_1 |
+ QGLFormat::OpenGL_Version_3_2 |
+ QGLFormat::OpenGL_Version_3_3 |
+ QGLFormat::OpenGL_Version_4_0;
} else {
versionFlags |= QGLFormat::OpenGL_Version_1_1 |
QGLFormat::OpenGL_Version_1_2 |
@@ -1276,7 +1293,9 @@ QGLFormat::OpenGLVersionFlags Q_AUTOTEST_EXPORT qOpenGLVersionFlagsFromString(co
QGLFormat::OpenGL_Version_2_1 |
QGLFormat::OpenGL_Version_3_0 |
QGLFormat::OpenGL_Version_3_1 |
- QGLFormat::OpenGL_Version_3_2;
+ QGLFormat::OpenGL_Version_3_2 |
+ QGLFormat::OpenGL_Version_3_3 |
+ QGLFormat::OpenGL_Version_4_0;
}
}
return versionFlags;
@@ -1519,10 +1538,33 @@ bool operator!=(const QGLFormat& a, const QGLFormat& b)
return !(a == b);
}
+struct QGLContextGroupList {
+ void append(QGLContextGroup *group) {
+ QMutexLocker locker(&m_mutex);
+ m_list.append(group);
+ }
+
+ void remove(QGLContextGroup *group) {
+ QMutexLocker locker(&m_mutex);
+ m_list.removeOne(group);
+ }
+
+ QList<QGLContextGroup *> m_list;
+ QMutex m_mutex;
+};
+
+Q_GLOBAL_STATIC(QGLContextGroupList, qt_context_groups)
+
/*****************************************************************************
QGLContext implementation
*****************************************************************************/
+QGLContextGroup::QGLContextGroup(const QGLContext *context)
+ : m_context(context), m_guards(0), m_refs(1)
+{
+ qt_context_groups()->append(this);
+}
+
QGLContextGroup::~QGLContextGroup()
{
// Clear any remaining QGLSharedResourceGuard objects on the group.
@@ -1532,6 +1574,7 @@ QGLContextGroup::~QGLContextGroup()
guard->m_id = 0;
guard = guard->m_next;
}
+ qt_context_groups()->remove(this);
}
void QGLContextGroup::addGuard(QGLSharedResourceGuard *guard)
@@ -1619,6 +1662,9 @@ void QGLContextPrivate::init(QPaintDevice *dev, const QGLFormat &format)
current_fbo = 0;
default_fbo = 0;
active_engine = 0;
+ workaround_needsFullClearOnEveryFrame = false;
+ workaround_brokenFBOReadBack = false;
+ workaroundsCached = false;
for (int i = 0; i < QT_GL_VERTEX_ARRAY_TRACKED_COUNT; ++i)
vertexAttributeArraysEnabledState[i] = false;
}
@@ -1730,7 +1776,6 @@ QGLTextureCache::QGLTextureCache()
QGLTextureCache::~QGLTextureCache()
{
- Q_ASSERT(size() == 0);
QImagePixmapCleanupHooks::instance()->removePixmapDataModificationHook(cleanupTexturesForPixampData);
QImagePixmapCleanupHooks::instance()->removePixmapDataDestructionHook(cleanupBeforePixmapDestruction);
QImagePixmapCleanupHooks::instance()->removeImageHook(cleanupTexturesForCacheKey);
@@ -1741,7 +1786,7 @@ void QGLTextureCache::insert(QGLContext* ctx, qint64 key, QGLTexture* texture, i
QWriteLocker locker(&m_lock);
if (m_cache.totalCost() + cost > m_cache.maxCost()) {
// the cache is full - make an attempt to remove something
- const QList<qint64> keys = m_cache.keys();
+ const QList<QGLTextureCacheKey> keys = m_cache.keys();
int i = 0;
while (i < m_cache.count()
&& (m_cache.totalCost() + cost > m_cache.maxCost())) {
@@ -1751,13 +1796,26 @@ void QGLTextureCache::insert(QGLContext* ctx, qint64 key, QGLTexture* texture, i
++i;
}
}
- m_cache.insert(key, texture, cost);
+ const QGLTextureCacheKey cacheKey = {key, QGLContextPrivate::contextGroup(ctx)};
+ m_cache.insert(cacheKey, texture, cost);
+}
+
+void QGLTextureCache::remove(qint64 key)
+{
+ QWriteLocker locker(&m_lock);
+ QMutexLocker groupLocker(&qt_context_groups()->m_mutex);
+ QList<QGLContextGroup *>::const_iterator it = qt_context_groups()->m_list.constBegin();
+ while (it != qt_context_groups()->m_list.constEnd()) {
+ const QGLTextureCacheKey cacheKey = {key, *it};
+ m_cache.remove(cacheKey);
+ ++it;
+ }
}
bool QGLTextureCache::remove(QGLContext* ctx, GLuint textureId)
{
QWriteLocker locker(&m_lock);
- QList<qint64> keys = m_cache.keys();
+ QList<QGLTextureCacheKey> keys = m_cache.keys();
for (int i = 0; i < keys.size(); ++i) {
QGLTexture *tex = m_cache.object(keys.at(i));
if (tex->id == textureId && tex->context == ctx) {
@@ -1772,9 +1830,9 @@ bool QGLTextureCache::remove(QGLContext* ctx, GLuint textureId)
void QGLTextureCache::removeContextTextures(QGLContext* ctx)
{
QWriteLocker locker(&m_lock);
- QList<qint64> keys = m_cache.keys();
+ QList<QGLTextureCacheKey> keys = m_cache.keys();
for (int i = 0; i < keys.size(); ++i) {
- const qint64 &key = keys.at(i);
+ const QGLTextureCacheKey &key = keys.at(i);
if (m_cache.object(key)->context == ctx)
m_cache.remove(key);
}
@@ -1787,7 +1845,6 @@ void QGLTextureCache::removeContextTextures(QGLContext* ctx)
void QGLTextureCache::cleanupTexturesForCacheKey(qint64 cacheKey)
{
qt_gl_texture_cache()->remove(cacheKey);
- Q_ASSERT(qt_gl_texture_cache()->getTexture(cacheKey) == 0);
}
@@ -2430,7 +2487,7 @@ QGLTexture* QGLContextPrivate::bindTexture(const QImage &image, GLenum target, G
QGLTexture *QGLContextPrivate::textureCacheLookup(const qint64 key, GLenum target)
{
Q_Q(QGLContext);
- QGLTexture *texture = QGLTextureCache::instance()->getTexture(key);
+ QGLTexture *texture = QGLTextureCache::instance()->getTexture(q, key);
if (texture && texture->target == target
&& (texture->context == q || QGLContext::areSharing(q, texture->context)))
{
@@ -2780,23 +2837,27 @@ static void qDrawTextureRect(const QRectF &target, GLint textureWidth, GLint tex
/*!
\since 4.4
- Draws the given texture, \a textureId, to the given target rectangle,
- \a target, in OpenGL model space. The \a textureTarget should be a 2D
- texture target.
+ This function supports the following use cases:
+
+ \list
+ \i On OpenGL and OpenGL ES 1.x it draws the given texture, \a textureId,
+ to the given target rectangle, \a target, in OpenGL model space. The
+ \a textureTarget should be a 2D texture target.
+ \i On OpenGL and OpenGL ES 2.x, if a painter is active, not inside a
+ beginNativePainting / endNativePainting block, and uses the
+ engine with type QPaintEngine::OpenGL2, the function will draw the given
+ texture, \a textureId, to the given target rectangle, \a target,
+ respecting the current painter state. This will let you draw a texture
+ with the clip, transform, render hints, and composition mode set by the
+ painter. Note that the texture target needs to be GL_TEXTURE_2D for this
+ use case, and that this is the only supported use case under OpenGL ES 2.x.
+ \endlist
- \note This function is not supported under OpenGL/ES 2.0.
*/
void QGLContext::drawTexture(const QRectF &target, GLuint textureId, GLenum textureTarget)
{
-#ifndef QT_OPENGL_ES_2
-#ifdef QT_OPENGL_ES
- if (textureTarget != GL_TEXTURE_2D) {
- qWarning("QGLContext::drawTexture(): texture target must be GL_TEXTURE_2D on OpenGL ES");
- return;
- }
-#else
-
- if (d_ptr->active_engine &&
+#if !defined(QT_OPENGL_ES) || defined(QT_OPENGL_ES_2)
+ if (d_ptr->active_engine &&
d_ptr->active_engine->type() == QPaintEngine::OpenGL2) {
QGL2PaintEngineEx *eng = static_cast<QGL2PaintEngineEx*>(d_ptr->active_engine);
if (!eng->isNativePaintingActive()) {
@@ -2806,7 +2867,15 @@ void QGLContext::drawTexture(const QRectF &target, GLuint textureId, GLenum text
return;
}
}
+#endif
+#ifndef QT_OPENGL_ES_2
+#ifdef QT_OPENGL_ES
+ if (textureTarget != GL_TEXTURE_2D) {
+ qWarning("QGLContext::drawTexture(): texture target must be GL_TEXTURE_2D on OpenGL ES");
+ return;
+ }
+#else
const bool wasEnabled = glIsEnabled(GL_TEXTURE_2D);
GLint oldTexture;
glGetIntegerv(GL_TEXTURE_BINDING_2D, &oldTexture);
@@ -2828,7 +2897,7 @@ void QGLContext::drawTexture(const QRectF &target, GLuint textureId, GLenum text
Q_UNUSED(target);
Q_UNUSED(textureId);
Q_UNUSED(textureTarget);
- qWarning("drawTexture(const QRectF &target, GLuint textureId, GLenum textureTarget) not supported with OpenGL ES/2.0");
+ qWarning("drawTexture() with OpenGL ES 2.0 requires an active OpenGL2 paint engine");
#endif
}
@@ -2843,14 +2912,26 @@ void QGLContext::drawTexture(const QRectF &target, QMacCompatGLuint textureId, Q
/*!
\since 4.4
- Draws the given texture at the given \a point in OpenGL model
- space. The \a textureTarget should be a 2D texture target.
+ This function supports the following use cases:
+
+ \list
+ \i By default it draws the given texture, \a textureId,
+ at the given \a point in OpenGL model space. The
+ \a textureTarget should be a 2D texture target.
+ \i If a painter is active, not inside a
+ beginNativePainting / endNativePainting block, and uses the
+ engine with type QPaintEngine::OpenGL2, the function will draw the given
+ texture, \a textureId, at the given \a point,
+ respecting the current painter state. This will let you draw a texture
+ with the clip, transform, render hints, and composition mode set by the
+ painter. Note that the texture target needs to be GL_TEXTURE_2D for this
+ use case.
+ \endlist
- \note This function is not supported under OpenGL/ES.
+ \note This function is not supported under any version of OpenGL ES.
*/
void QGLContext::drawTexture(const QPointF &point, GLuint textureId, GLenum textureTarget)
{
- // this would be ok on OpenGL ES 2.0, but currently we don't have a define for that
#ifdef QT_OPENGL_ES
Q_UNUSED(point);
Q_UNUSED(textureId);
@@ -2871,7 +2952,7 @@ void QGLContext::drawTexture(const QPointF &point, GLuint textureId, GLenum text
glGetTexLevelParameteriv(textureTarget, 0, GL_TEXTURE_WIDTH, &textureWidth);
glGetTexLevelParameteriv(textureTarget, 0, GL_TEXTURE_HEIGHT, &textureHeight);
- if (d_ptr->active_engine &&
+ if (d_ptr->active_engine &&
d_ptr->active_engine->type() == QPaintEngine::OpenGL2) {
QGL2PaintEngineEx *eng = static_cast<QGL2PaintEngineEx*>(d_ptr->active_engine);
if (!eng->isNativePaintingActive()) {
@@ -3600,8 +3681,10 @@ QGLWidget::~QGLWidget()
bool doRelease = (glcx && glcx->windowCreated());
#endif
delete d->glcx;
+ d->glcx = 0;
#if defined(Q_WGL)
delete d->olcx;
+ d->olcx = 0;
#endif
#if defined(GLX_MESA_release_buffers) && defined(QGL_USE_MESA_EXT)
if (doRelease)
@@ -4918,11 +5001,8 @@ void QGLWidget::deleteTexture(QMacCompatGLuint id)
/*!
\since 4.4
- Draws the given texture, \a textureId to the given target rectangle,
- \a target, in OpenGL model space. The \a textureTarget should be a 2D
- texture target.
-
- Equivalent to the corresponding QGLContext::drawTexture().
+ Calls the corresponding QGLContext::drawTexture() on
+ this widget's context.
*/
void QGLWidget::drawTexture(const QRectF &target, GLuint textureId, GLenum textureTarget)
{
@@ -4942,10 +5022,8 @@ void QGLWidget::drawTexture(const QRectF &target, QMacCompatGLuint textureId, QM
/*!
\since 4.4
- Draws the given texture, \a textureId, at the given \a point in OpenGL
- model space. The \a textureTarget should be a 2D texture target.
-
- Equivalent to the corresponding QGLContext::drawTexture().
+ Calls the corresponding QGLContext::drawTexture() on
+ this widget's context.
*/
void QGLWidget::drawTexture(const QPointF &point, GLuint textureId, GLenum textureTarget)
{
diff --git a/src/opengl/qgl.h b/src/opengl/qgl.h
index 701aa8e..8da48ed 100644
--- a/src/opengl/qgl.h
+++ b/src/opengl/qgl.h
@@ -270,7 +270,9 @@ public:
OpenGL_ES_Version_2_0 = 0x00000800,
OpenGL_Version_3_0 = 0x00001000,
OpenGL_Version_3_1 = 0x00002000,
- OpenGL_Version_3_2 = 0x00004000
+ OpenGL_Version_3_2 = 0x00004000,
+ OpenGL_Version_3_3 = 0x00008000,
+ OpenGL_Version_4_0 = 0x00010000
};
Q_DECLARE_FLAGS(OpenGLVersionFlags, OpenGLVersionFlag)
@@ -435,6 +437,7 @@ private:
friend class QGLFramebufferObjectPrivate;
friend class QGLFBOGLPaintDevice;
friend class QGLPaintDevice;
+ friend class QGLWidgetGLPaintDevice;
friend class QX11GLPixmapData;
friend class QX11GLSharedContexts;
private:
diff --git a/src/opengl/qgl_egl.cpp b/src/opengl/qgl_egl.cpp
index 0fbbbf9..0a19531 100644
--- a/src/opengl/qgl_egl.cpp
+++ b/src/opengl/qgl_egl.cpp
@@ -185,8 +185,27 @@ void QGLContext::makeCurrent()
return;
}
- if (d->eglContext->makeCurrent(d->eglSurfaceForDevice()))
+ if (d->eglContext->makeCurrent(d->eglSurfaceForDevice())) {
QGLContextPrivate::setCurrentContext(this);
+ if (!d->workaroundsCached) {
+ d->workaroundsCached = true;
+ const char *renderer = reinterpret_cast<const char *>(glGetString(GL_RENDERER));
+ if (renderer && (strstr(renderer, "SGX") || strstr(renderer, "MBX"))) {
+ // PowerVR MBX/SGX chips needs to clear all buffers when starting to render
+ // a new frame, otherwise there will be a performance penalty to pay for
+ // each frame.
+ d->workaround_needsFullClearOnEveryFrame = true;
+
+ // Older PowerVR SGX drivers (like the one in the N900) have a
+ // bug which prevents glCopyTexSubImage2D() to work with a POT
+ // or GL_ALPHA texture bound to an FBO. The only way to
+ // identify that driver is to check the EGL version number for it.
+ const char *egl_version = eglQueryString(d->eglContext->display(), EGL_VERSION);
+ if (egl_version && strstr(egl_version, "1.3"))
+ d->workaround_brokenFBOReadBack = true;
+ }
+ }
+ }
}
void QGLContext::doneCurrent()
diff --git a/src/opengl/qgl_p.h b/src/opengl/qgl_p.h
index 042d5ae..a1be68f 100644
--- a/src/opengl/qgl_p.h
+++ b/src/opengl/qgl_p.h
@@ -181,6 +181,10 @@ public:
void initContext(QGLContext *context, const QGLWidget* shareWidget);
bool renderCxPm(QPixmap *pixmap);
void cleanupColormaps();
+ void aboutToDestroy() {
+ if (glcx)
+ glcx->reset();
+ }
QGLContext *glcx;
QGLWidgetGLPaintDevice glDevice;
@@ -234,7 +238,7 @@ public:
static void addShare(const QGLContext *context, const QGLContext *share);
static void removeShare(const QGLContext *context);
private:
- QGLContextGroup(const QGLContext *context) : m_context(context), m_guards(0), m_refs(1) { }
+ QGLContextGroup(const QGLContext *context);
QGLExtensionFuncs m_extensionFuncs;
const QGLContext *m_context; // context group's representative
@@ -348,9 +352,7 @@ public:
HBITMAP hbitmap;
HDC hbitmap_hdc;
#endif
-
-#if !defined(QT_NO_EGL)
- bool ownsEglContext;
+#ifndef QT_NO_EGL
QEglContext *eglContext;
EGLSurface eglSurface;
void destroyEglSurfaceForDevice();
@@ -391,6 +393,16 @@ public:
uint internal_context : 1;
uint version_flags_cached : 1;
uint extension_flags_cached : 1;
+
+ // workarounds for driver/hw bugs on different platforms
+ uint workaround_needsFullClearOnEveryFrame : 1;
+ uint workaround_brokenFBOReadBack : 1;
+ uint workaroundsCached : 1;
+
+#ifndef QT_NO_EGL
+ uint ownsEglContext : 1;
+#endif
+
QPaintDevice *paintDevice;
QColor transpColor;
QGLContext *q_ptr;
@@ -525,17 +537,33 @@ public:
QSize bindCompressedTexturePVR(const char *buf, int len);
};
+struct QGLTextureCacheKey {
+ qint64 key;
+ QGLContextGroup *group;
+};
+
+inline bool operator==(const QGLTextureCacheKey &a, const QGLTextureCacheKey &b)
+{
+ return a.key == b.key && a.group == b.group;
+}
+
+inline uint qHash(const QGLTextureCacheKey &key)
+{
+ return qHash(key.key) ^ qHash(key.group);
+}
+
+
class Q_AUTOTEST_EXPORT QGLTextureCache {
public:
QGLTextureCache();
~QGLTextureCache();
void insert(QGLContext *ctx, qint64 key, QGLTexture *texture, int cost);
- inline void remove(quint64 key);
+ void remove(qint64 key);
inline int size();
inline void setMaxCost(int newMax);
inline int maxCost();
- inline QGLTexture* getTexture(quint64 key);
+ inline QGLTexture* getTexture(QGLContext *ctx, qint64 key);
bool remove(QGLContext *ctx, GLuint textureId);
void removeContextTextures(QGLContext *ctx);
@@ -545,7 +573,7 @@ public:
static void cleanupBeforePixmapDestruction(QPixmapData* pixmap);
private:
- QCache<qint64, QGLTexture> m_cache;
+ QCache<QGLTextureCacheKey, QGLTexture> m_cache;
QReadWriteLock m_lock;
};
@@ -566,19 +594,13 @@ int QGLTextureCache::maxCost()
return m_cache.maxCost();
}
-QGLTexture* QGLTextureCache::getTexture(quint64 key)
+QGLTexture* QGLTextureCache::getTexture(QGLContext *ctx, qint64 key)
{
QReadLocker locker(&m_lock);
- return m_cache.object(key);
+ const QGLTextureCacheKey cacheKey = {key, QGLContextPrivate::contextGroup(ctx)};
+ return m_cache.object(cacheKey);
}
-void QGLTextureCache::remove(quint64 key)
-{
- QWriteLocker locker(&m_lock);
- m_cache.remove(key);
-}
-
-
extern Q_OPENGL_EXPORT QPaintEngine* qt_qgl_paint_engine();
bool qt_gl_preferGL2Engine();
diff --git a/src/opengl/qgl_x11.cpp b/src/opengl/qgl_x11.cpp
index d203646..bfb232d 100644
--- a/src/opengl/qgl_x11.cpp
+++ b/src/opengl/qgl_x11.cpp
@@ -115,6 +115,20 @@ extern const QX11Info *qt_x11Info(const QPaintDevice *pd);
#define GLX_FRONT_LEFT_EXT 0x20DE
#endif
+#ifndef GLX_ARB_create_context
+#define GLX_CONTEXT_DEBUG_BIT_ARB 0x00000001
+#define GLX_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB 0x00000002
+#define GLX_CONTEXT_MAJOR_VERSION_ARB 0x2091
+#define GLX_CONTEXT_MINOR_VERSION_ARB 0x2092
+#define GLX_CONTEXT_FLAGS_ARB 0x2094
+#endif
+
+#ifndef GLX_ARB_create_context_profile
+#define GLX_CONTEXT_CORE_PROFILE_BIT_ARB 0x00000001
+#define GLX_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB 0x00000002
+#define GLX_CONTEXT_PROFILE_MASK_ARB 0x9126
+#endif
+
/*
The qt_gl_choose_cmap function is internal and used by QGLWidget::setContext()
and GLX (not Windows). If the application can't find any sharable
@@ -401,6 +415,148 @@ bool QGLFormat::hasOpenGLOverlays()
return trans_colors.size() > 0;
}
+static bool buildSpec(int* spec, const QGLFormat& f, QPaintDevice* paintDevice,
+ int bufDepth, bool onlyFBConfig = false)
+{
+ int i = 0;
+ spec[i++] = GLX_LEVEL;
+ spec[i++] = f.plane();
+ const QX11Info *xinfo = qt_x11Info(paintDevice);
+ bool useFBConfig = onlyFBConfig;
+
+#if defined(GLX_VERSION_1_3) && !defined(QT_NO_XRENDER) && !defined(Q_OS_HPUX)
+ /*
+ HPUX defines GLX_VERSION_1_3 but does not implement the corresponding functions.
+ Specifically glXChooseFBConfig and glXGetVisualFromFBConfig are not implemented.
+ */
+ QWidget* widget = 0;
+ if (paintDevice->devType() == QInternal::Widget)
+ widget = static_cast<QWidget*>(paintDevice);
+
+ // Only use glXChooseFBConfig for widgets if we're trying to get an ARGB visual
+ if (widget && widget->testAttribute(Qt::WA_TranslucentBackground) && X11->use_xrender)
+ useFBConfig = true;
+#endif
+
+#if defined(GLX_VERSION_1_1) && defined(GLX_EXT_visual_info)
+ static bool useTranspExt = false;
+ static bool useTranspExtChecked = false;
+ if (f.plane() && !useTranspExtChecked && paintDevice) {
+ QGLExtensionMatcher extensions(glXQueryExtensionsString(xinfo->display(), xinfo->screen()));
+ useTranspExt = extensions.match("GLX_EXT_visual_info");
+ //# (A bit simplistic; that could theoretically be a substring)
+ if (useTranspExt) {
+ QByteArray cstr(glXGetClientString(xinfo->display(), GLX_VENDOR));
+ useTranspExt = !cstr.contains("Xi Graphics"); // bug workaround
+ if (useTranspExt) {
+ // bug workaround - some systems (eg. FireGL) refuses to return an overlay
+ // visual if the GLX_TRANSPARENT_TYPE_EXT attribute is specified, even if
+ // the implementation supports transparent overlays
+ int tmpSpec[] = { GLX_LEVEL, f.plane(), GLX_TRANSPARENT_TYPE_EXT,
+ f.rgba() ? GLX_TRANSPARENT_RGB_EXT : GLX_TRANSPARENT_INDEX_EXT,
+ XNone };
+ XVisualInfo * vinf = glXChooseVisual(xinfo->display(), xinfo->screen(), tmpSpec);
+ if (!vinf) {
+ useTranspExt = false;
+ }
+ }
+ }
+
+ useTranspExtChecked = true;
+ }
+ if (f.plane() && useTranspExt && !useFBConfig) {
+ // Required to avoid non-transparent overlay visual(!) on some systems
+ spec[i++] = GLX_TRANSPARENT_TYPE_EXT;
+ spec[i++] = f.rgba() ? GLX_TRANSPARENT_RGB_EXT : GLX_TRANSPARENT_INDEX_EXT;
+ }
+#endif
+
+#if defined(GLX_VERSION_1_3) && !defined(Q_OS_HPUX)
+ // GLX_RENDER_TYPE is only in glx >=1.3
+ if (useFBConfig) {
+ spec[i++] = GLX_RENDER_TYPE;
+ spec[i++] = f.rgba() ? GLX_RGBA_BIT : GLX_COLOR_INDEX_BIT;
+ }
+#endif
+
+ if (f.doubleBuffer())
+ spec[i++] = GLX_DOUBLEBUFFER;
+ if (useFBConfig)
+ spec[i++] = True;
+ if (f.depth()) {
+ spec[i++] = GLX_DEPTH_SIZE;
+ spec[i++] = f.depthBufferSize() == -1 ? 1 : f.depthBufferSize();
+ }
+ if (f.stereo()) {
+ spec[i++] = GLX_STEREO;
+ if (useFBConfig)
+ spec[i++] = True;
+ }
+ if (f.stencil()) {
+ spec[i++] = GLX_STENCIL_SIZE;
+ spec[i++] = f.stencilBufferSize() == -1 ? 1 : f.stencilBufferSize();
+ }
+ if (f.rgba()) {
+ if (!useFBConfig)
+ spec[i++] = GLX_RGBA;
+ spec[i++] = GLX_RED_SIZE;
+ spec[i++] = f.redBufferSize() == -1 ? 1 : f.redBufferSize();
+ spec[i++] = GLX_GREEN_SIZE;
+ spec[i++] = f.greenBufferSize() == -1 ? 1 : f.greenBufferSize();
+ spec[i++] = GLX_BLUE_SIZE;
+ spec[i++] = f.blueBufferSize() == -1 ? 1 : f.blueBufferSize();
+ if (f.alpha()) {
+ spec[i++] = GLX_ALPHA_SIZE;
+ spec[i++] = f.alphaBufferSize() == -1 ? 1 : f.alphaBufferSize();
+ }
+ if (f.accum()) {
+ spec[i++] = GLX_ACCUM_RED_SIZE;
+ spec[i++] = f.accumBufferSize() == -1 ? 1 : f.accumBufferSize();
+ spec[i++] = GLX_ACCUM_GREEN_SIZE;
+ spec[i++] = f.accumBufferSize() == -1 ? 1 : f.accumBufferSize();
+ spec[i++] = GLX_ACCUM_BLUE_SIZE;
+ spec[i++] = f.accumBufferSize() == -1 ? 1 : f.accumBufferSize();
+ if (f.alpha()) {
+ spec[i++] = GLX_ACCUM_ALPHA_SIZE;
+ spec[i++] = f.accumBufferSize() == -1 ? 1 : f.accumBufferSize();
+ }
+ }
+ } else {
+ spec[i++] = GLX_BUFFER_SIZE;
+ spec[i++] = bufDepth;
+ }
+
+ if (f.sampleBuffers()) {
+ spec[i++] = GLX_SAMPLE_BUFFERS_ARB;
+ spec[i++] = 1;
+ spec[i++] = GLX_SAMPLES_ARB;
+ spec[i++] = f.samples() == -1 ? 4 : f.samples();
+ }
+
+#if defined(GLX_VERSION_1_3) && !defined(Q_OS_HPUX)
+ if (useFBConfig) {
+ spec[i++] = GLX_DRAWABLE_TYPE;
+ switch(paintDevice->devType()) {
+ case QInternal::Pixmap:
+ spec[i++] = GLX_PIXMAP_BIT;
+ break;
+ case QInternal::Pbuffer:
+ spec[i++] = GLX_PBUFFER_BIT;
+ break;
+ default:
+ qWarning("QGLContext: Unknown paint device type %d", paintDevice->devType());
+ // Fall-through & assume it's a window
+ case QInternal::Widget:
+ spec[i++] = GLX_WINDOW_BIT;
+ break;
+ };
+ }
+#endif
+
+ spec[i] = XNone;
+ return useFBConfig;
+}
+
/*****************************************************************************
QGLContext UNIX/GLX-specific code
*****************************************************************************/
@@ -493,21 +649,85 @@ bool QGLContext::chooseContext(const QGLContext* shareContext)
shareContext = 0;
}
+ const int major = d->reqFormat.majorVersion();
+ const int minor = d->reqFormat.minorVersion();
+ const int profile = d->reqFormat.profile() == QGLFormat::CompatibilityProfile
+ ? GLX_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB
+ : GLX_CONTEXT_CORE_PROFILE_BIT_ARB;
+
d->cx = 0;
- if (shareContext) {
+
+#if defined(GLX_VERSION_1_3) && !defined(Q_OS_HPUX)
+ /*
+ HPUX defines GLX_VERSION_1_3 but does not implement the corresponding functions.
+ Specifically glXChooseFBConfig and glXGetVisualFromFBConfig are not implemented.
+ */
+ if ((major == 3 && minor >= 2) || major > 3) {
+ QGLTemporaryContext *tmpContext = 0;
+ if (!QGLContext::currentContext())
+ tmpContext = new QGLTemporaryContext;
+
+ int attributes[] = { GLX_CONTEXT_MAJOR_VERSION_ARB, major,
+ GLX_CONTEXT_MINOR_VERSION_ARB, minor,
+ GLX_CONTEXT_PROFILE_MASK_ARB, profile,
+ 0 };
+
+ typedef GLXContext ( * Q_PFNGLXCREATECONTEXTATTRIBSARBPROC)
+ (Display* dpy, GLXFBConfig config, GLXContext share_context, Bool direct, const int *attrib_list);
+
+
+ Q_PFNGLXCREATECONTEXTATTRIBSARBPROC glXCreateContextAttribs =
+ (Q_PFNGLXCREATECONTEXTATTRIBSARBPROC) qglx_getProcAddress("glXCreateContextAttribsARB");
+
+ if (glXCreateContextAttribs) {
+ int spec[45];
+ glXGetConfig(disp, (XVisualInfo*)d->vi, GLX_BUFFER_SIZE, &res);
+ buildSpec(spec, format(), d->paintDevice, res, true);
+
+ GLXFBConfig *configs;
+ int configCount = 0;
+ configs = glXChooseFBConfig(disp, xinfo->screen(), spec, &configCount);
+
+ if (configs && configCount > 0) {
+ d->cx = glXCreateContextAttribs(disp, configs[0],
+ shareContext ? (GLXContext)shareContext->d_func()->cx : 0, direct, attributes);
+ if (!d->cx && shareContext) {
+ shareContext = 0;
+ d->cx = glXCreateContextAttribs(disp, configs[0], 0, direct, attributes);
+ }
+ d->screen = ((XVisualInfo*)d->vi)->screen;
+ }
+ XFree(configs);
+ } else {
+ qWarning("QGLContext::chooseContext(): OpenGL %d.%d is not supported", major, minor);
+ }
+
+ if (tmpContext)
+ delete tmpContext;
+ }
+#else
+ Q_UNUSED(major);
+ Q_UNUSED(minor);
+ Q_UNUSED(profile);
+#endif
+
+ if (!d->cx && shareContext) {
d->cx = glXCreateContext(disp, (XVisualInfo *)d->vi,
(GLXContext)shareContext->d_func()->cx, direct);
d->screen = ((XVisualInfo*)d->vi)->screen;
- if (d->cx) {
- QGLContext *share = const_cast<QGLContext *>(shareContext);
- d->sharing = true;
- share->d_func()->sharing = true;
- }
}
if (!d->cx) {
d->cx = glXCreateContext(disp, (XVisualInfo *)d->vi, NULL, direct);
d->screen = ((XVisualInfo*)d->vi)->screen;
+ shareContext = 0;
+ }
+
+ if (shareContext && d->cx) {
+ QGLContext *share = const_cast<QGLContext *>(shareContext);
+ d->sharing = true;
+ share->d_func()->sharing = true;
}
+
if (!d->cx)
return false;
d->glFormat.setDirectRendering(glXIsDirect(disp, (GLXContext)d->cx));
@@ -606,143 +826,8 @@ void *QGLContext::tryVisual(const QGLFormat& f, int bufDepth)
{
Q_D(QGLContext);
int spec[45];
- int i = 0;
- spec[i++] = GLX_LEVEL;
- spec[i++] = f.plane();
const QX11Info *xinfo = qt_x11Info(d->paintDevice);
- bool useFBConfig = false;
-
-#if defined(GLX_VERSION_1_3) && !defined(QT_NO_XRENDER) && !defined(Q_OS_HPUX)
- /*
- HPUX defines GLX_VERSION_1_3 but does not implement the corresponding functions.
- Specifically glXChooseFBConfig and glXGetVisualFromFBConfig are not implemented.
- */
- QWidget* widget = 0;
- if (d->paintDevice->devType() == QInternal::Widget)
- widget = static_cast<QWidget*>(d->paintDevice);
-
- // Only use glXChooseFBConfig for widgets if we're trying to get an ARGB visual
- if (widget && widget->testAttribute(Qt::WA_TranslucentBackground) && X11->use_xrender)
- useFBConfig = true;
-#endif
-
-#if defined(GLX_VERSION_1_1) && defined(GLX_EXT_visual_info)
- static bool useTranspExt = false;
- static bool useTranspExtChecked = false;
- if (f.plane() && !useTranspExtChecked && d->paintDevice) {
- QGLExtensionMatcher extensions(glXQueryExtensionsString(xinfo->display(), xinfo->screen()));
- useTranspExt = extensions.match("GLX_EXT_visual_info");
- //# (A bit simplistic; that could theoretically be a substring)
- if (useTranspExt) {
- QByteArray cstr(glXGetClientString(xinfo->display(), GLX_VENDOR));
- useTranspExt = !cstr.contains("Xi Graphics"); // bug workaround
- if (useTranspExt) {
- // bug workaround - some systems (eg. FireGL) refuses to return an overlay
- // visual if the GLX_TRANSPARENT_TYPE_EXT attribute is specified, even if
- // the implementation supports transparent overlays
- int tmpSpec[] = { GLX_LEVEL, f.plane(), GLX_TRANSPARENT_TYPE_EXT,
- f.rgba() ? GLX_TRANSPARENT_RGB_EXT : GLX_TRANSPARENT_INDEX_EXT,
- XNone };
- XVisualInfo * vinf = glXChooseVisual(xinfo->display(), xinfo->screen(), tmpSpec);
- if (!vinf) {
- useTranspExt = false;
- }
- }
- }
-
- useTranspExtChecked = true;
- }
- if (f.plane() && useTranspExt && !useFBConfig) {
- // Required to avoid non-transparent overlay visual(!) on some systems
- spec[i++] = GLX_TRANSPARENT_TYPE_EXT;
- spec[i++] = f.rgba() ? GLX_TRANSPARENT_RGB_EXT : GLX_TRANSPARENT_INDEX_EXT;
- }
-#endif
-
-#if defined(GLX_VERSION_1_3) && !defined(Q_OS_HPUX)
- // GLX_RENDER_TYPE is only in glx >=1.3
- if (useFBConfig) {
- spec[i++] = GLX_RENDER_TYPE;
- spec[i++] = f.rgba() ? GLX_RGBA_BIT : GLX_COLOR_INDEX_BIT;
- }
-#endif
-
- if (f.doubleBuffer())
- spec[i++] = GLX_DOUBLEBUFFER;
- if (useFBConfig)
- spec[i++] = True;
- if (f.depth()) {
- spec[i++] = GLX_DEPTH_SIZE;
- spec[i++] = f.depthBufferSize() == -1 ? 1 : f.depthBufferSize();
- }
- if (f.stereo()) {
- spec[i++] = GLX_STEREO;
- if (useFBConfig)
- spec[i++] = True;
- }
- if (f.stencil()) {
- spec[i++] = GLX_STENCIL_SIZE;
- spec[i++] = f.stencilBufferSize() == -1 ? 1 : f.stencilBufferSize();
- }
- if (f.rgba()) {
- if (!useFBConfig)
- spec[i++] = GLX_RGBA;
- spec[i++] = GLX_RED_SIZE;
- spec[i++] = f.redBufferSize() == -1 ? 1 : f.redBufferSize();
- spec[i++] = GLX_GREEN_SIZE;
- spec[i++] = f.greenBufferSize() == -1 ? 1 : f.greenBufferSize();
- spec[i++] = GLX_BLUE_SIZE;
- spec[i++] = f.blueBufferSize() == -1 ? 1 : f.blueBufferSize();
- if (f.alpha()) {
- spec[i++] = GLX_ALPHA_SIZE;
- spec[i++] = f.alphaBufferSize() == -1 ? 1 : f.alphaBufferSize();
- }
- if (f.accum()) {
- spec[i++] = GLX_ACCUM_RED_SIZE;
- spec[i++] = f.accumBufferSize() == -1 ? 1 : f.accumBufferSize();
- spec[i++] = GLX_ACCUM_GREEN_SIZE;
- spec[i++] = f.accumBufferSize() == -1 ? 1 : f.accumBufferSize();
- spec[i++] = GLX_ACCUM_BLUE_SIZE;
- spec[i++] = f.accumBufferSize() == -1 ? 1 : f.accumBufferSize();
- if (f.alpha()) {
- spec[i++] = GLX_ACCUM_ALPHA_SIZE;
- spec[i++] = f.accumBufferSize() == -1 ? 1 : f.accumBufferSize();
- }
- }
- } else {
- spec[i++] = GLX_BUFFER_SIZE;
- spec[i++] = bufDepth;
- }
-
- if (f.sampleBuffers()) {
- spec[i++] = GLX_SAMPLE_BUFFERS_ARB;
- spec[i++] = 1;
- spec[i++] = GLX_SAMPLES_ARB;
- spec[i++] = f.samples() == -1 ? 4 : f.samples();
- }
-
-#if defined(GLX_VERSION_1_3) && !defined(Q_OS_HPUX)
- if (useFBConfig) {
- spec[i++] = GLX_DRAWABLE_TYPE;
- switch(d->paintDevice->devType()) {
- case QInternal::Pixmap:
- spec[i++] = GLX_PIXMAP_BIT;
- break;
- case QInternal::Pbuffer:
- spec[i++] = GLX_PBUFFER_BIT;
- break;
- default:
- qWarning("QGLContext: Unknown paint device type %d", d->paintDevice->devType());
- // Fall-through & assume it's a window
- case QInternal::Widget:
- spec[i++] = GLX_WINDOW_BIT;
- break;
- };
- }
-#endif
-
- spec[i] = XNone;
-
+ bool useFBConfig = buildSpec(spec, f, d->paintDevice, bufDepth, false);
XVisualInfo* chosenVisualInfo = 0;
@@ -755,7 +840,7 @@ void *QGLContext::tryVisual(const QGLFormat& f, int bufDepth)
if (!configs)
break; // fallback to trying glXChooseVisual
- for (i = 0; i < configCount; ++i) {
+ for (int i = 0; i < configCount; ++i) {
XVisualInfo* vi;
vi = glXGetVisualFromFBConfig(xinfo->display(), configs[i]);
if (!vi)
@@ -843,7 +928,7 @@ void QGLContext::makeCurrent()
} else if (d->paintDevice->devType() == QInternal::Pbuffer) {
ok = glXMakeCurrent(xinfo->display(), (GLXPbuffer)d->pbuf, (GLXContext)d->cx);
} else if (d->paintDevice->devType() == QInternal::Widget) {
- ok = glXMakeCurrent(xinfo->display(), ((QWidget *)d->paintDevice)->winId(), (GLXContext)d->cx);
+ ok = glXMakeCurrent(xinfo->display(), ((QWidget *)d->paintDevice)->internalWinId(), (GLXContext)d->cx);
}
if (!ok)
qWarning("QGLContext::makeCurrent(): Failed.");
@@ -1773,6 +1858,9 @@ QGLTexture *QGLContextPrivate::bindTextureFromNativePixmap(QPixmap *pixmap, cons
glXBindTexImageEXT(x11Info.display(), (GLXPixmap)pixmapData->gl_surface, GLX_FRONT_LEFT_EXT, 0);
glBindTexture(GL_TEXTURE_2D, textureId);
+ GLuint filtering = (options & QGLContext::LinearFilteringBindOption) ? GL_LINEAR : GL_NEAREST;
+ glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, filtering);
+ glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, filtering);
if (!((hasAlpha && RGBAConfigInverted) || (!hasAlpha && RGBConfigInverted)))
options &= ~QGLContext::InvertedYBindOption;
diff --git a/src/opengl/qglbuffer.cpp b/src/opengl/qglbuffer.cpp
index 223243c..d6e0109 100644
--- a/src/opengl/qglbuffer.cpp
+++ b/src/opengl/qglbuffer.cpp
@@ -42,6 +42,7 @@
#include <QtOpenGL/qgl.h>
#include <QtOpenGL/private/qgl_p.h>
#include <QtOpenGL/private/qglextensions_p.h>
+#include <QtCore/qatomic.h>
#include "qglbuffer.h"
QT_BEGIN_NAMESPACE
@@ -55,6 +56,20 @@ QT_BEGIN_NAMESPACE
Buffer objects are created in the GL server so that the
client application can avoid uploading vertices, indices,
texture image data, etc every time they are needed.
+
+ QGLBuffer objects can be copied around as a reference to the
+ underlying GL buffer object:
+
+ \code
+ QGLBuffer buffer1(QGLBuffer::IndexBuffer);
+ buffer1.create();
+
+ QGLBuffer buffer2 = buffer1;
+ \endcode
+
+ QGLBuffer performs a shallow copy when objects are copied in this
+ manner, but does not implement copy-on-write semantics. The original
+ object will be affected whenever the copy is modified.
*/
/*!
@@ -116,13 +131,15 @@ class QGLBufferPrivate
{
public:
QGLBufferPrivate(QGLBuffer::Type t)
- : type(t),
+ : ref(1),
+ type(t),
guard(0),
usagePattern(QGLBuffer::StaticDraw),
actualUsagePattern(QGLBuffer::StaticDraw)
{
}
+ QAtomicInt ref;
QGLBuffer::Type type;
QGLSharedResourceGuard guard;
QGLBuffer::UsagePattern usagePattern;
@@ -130,6 +147,19 @@ public:
};
/*!
+ Constructs a new buffer object of type QGLBuffer::VertexBuffer.
+
+ Note: this constructor just creates the QGLBuffer instance. The actual
+ buffer object in the GL server is not created until create() is called.
+
+ \sa create()
+*/
+QGLBuffer::QGLBuffer()
+ : d_ptr(new QGLBufferPrivate(QGLBuffer::VertexBuffer))
+{
+}
+
+/*!
Constructs a new buffer object of \a type.
Note: this constructor just creates the QGLBuffer instance. The actual
@@ -142,6 +172,18 @@ QGLBuffer::QGLBuffer(QGLBuffer::Type type)
{
}
+/*!
+ Constructs a shallow copy of \a other.
+
+ Note: QGLBuffer does not implement copy-on-write semantics,
+ so \a other will be affected whenever the copy is modified.
+*/
+QGLBuffer::QGLBuffer(const QGLBuffer &other)
+ : d_ptr(other.d_ptr)
+{
+ d_ptr->ref.ref();
+}
+
#define ctx d->guard.context()
/*!
@@ -150,13 +192,27 @@ QGLBuffer::QGLBuffer(QGLBuffer::Type type)
*/
QGLBuffer::~QGLBuffer()
{
- Q_D(QGLBuffer);
- GLuint bufferId = d->guard.id();
- if (bufferId) {
- // Switch to the original creating context to destroy it.
- QGLShareContextScope scope(d->guard.context());
- glDeleteBuffers(1, &bufferId);
+ if (!d_ptr->ref.deref()) {
+ destroy();
+ delete d_ptr;
+ }
+}
+
+/*!
+ Assigns a shallow copy of \a other to this object.
+
+ Note: QGLBuffer does not implement copy-on-write semantics,
+ so \a other will be affected whenever the copy is modified.
+*/
+QGLBuffer &QGLBuffer::operator=(const QGLBuffer &other)
+{
+ if (d_ptr != other.d_ptr) {
+ other.d_ptr->ref.ref();
+ if (!d_ptr->ref.deref())
+ destroy();
+ d_ptr = other.d_ptr;
}
+ return *this;
}
/*!
@@ -215,7 +271,7 @@ void QGLBuffer::setUsagePattern(QGLBuffer::UsagePattern value)
This function will return false if the GL implementation
does not support buffers, or there is no current QGLContext.
- \sa isCreated(), allocate(), write()
+ \sa isCreated(), allocate(), write(), destroy()
*/
bool QGLBuffer::create()
{
@@ -242,7 +298,7 @@ bool QGLBuffer::create()
/*!
Returns true if this buffer has been created; false otherwise.
- \sa create()
+ \sa create(), destroy()
*/
bool QGLBuffer::isCreated() const
{
@@ -251,6 +307,24 @@ bool QGLBuffer::isCreated() const
}
/*!
+ Destroys this buffer object, including the storage being
+ used in the GL server. All references to the buffer will
+ become invalid.
+*/
+void QGLBuffer::destroy()
+{
+ Q_D(QGLBuffer);
+ GLuint bufferId = d->guard.id();
+ if (bufferId) {
+ // Switch to the original creating context to destroy it.
+ QGLShareContextScope scope(d->guard.context());
+ glDeleteBuffers(1, &bufferId);
+ }
+ d->guard.setId(0);
+ d->guard.setContext(0);
+}
+
+/*!
Reads the \a count bytes in this buffer starting at \a offset
into \a data. Returns true on success; false if reading from
the buffer is not supported. Buffer reading is not supported
diff --git a/src/opengl/qglbuffer.h b/src/opengl/qglbuffer.h
index 2fe1f1f..a1b45ff 100644
--- a/src/opengl/qglbuffer.h
+++ b/src/opengl/qglbuffer.h
@@ -64,9 +64,13 @@ public:
PixelUnpackBuffer = 0x88EC // GL_PIXEL_UNPACK_BUFFER
};
+ QGLBuffer();
explicit QGLBuffer(QGLBuffer::Type type);
+ QGLBuffer(const QGLBuffer &other);
~QGLBuffer();
+ QGLBuffer &operator=(const QGLBuffer &other);
+
enum UsagePattern
{
StreamDraw = 0x88E0, // GL_STREAM_DRAW
@@ -95,6 +99,8 @@ public:
bool create();
bool isCreated() const;
+ void destroy();
+
bool bind() const;
void release() const;
@@ -114,9 +120,8 @@ public:
bool unmap();
private:
- QScopedPointer<QGLBufferPrivate> d_ptr;
+ QGLBufferPrivate *d_ptr;
- Q_DISABLE_COPY(QGLBuffer)
Q_DECLARE_PRIVATE(QGLBuffer)
};
diff --git a/src/opengl/qglframebufferobject.cpp b/src/opengl/qglframebufferobject.cpp
index 890b029..deffc20 100644
--- a/src/opengl/qglframebufferobject.cpp
+++ b/src/opengl/qglframebufferobject.cpp
@@ -1024,6 +1024,36 @@ QPaintEngine *QGLFramebufferObject::paintEngine() const
}
/*!
+ \fn bool QGLFramebufferObject::bindDefault()
+ \internal
+
+ Switches rendering back to the default, windowing system provided
+ framebuffer.
+ Returns true upon success, false otherwise.
+
+ \sa bind(), release()
+*/
+bool QGLFramebufferObject::bindDefault()
+{
+ QGLContext *ctx = const_cast<QGLContext *>(QGLContext::currentContext());
+
+ if (ctx) {
+ bool ext_detected = (QGLExtensions::glExtensions() & QGLExtensions::FramebufferObject);
+ if (!ext_detected || (ext_detected && !qt_resolve_framebufferobject_extensions(ctx)))
+ return false;
+
+ ctx->d_ptr->current_fbo = ctx->d_ptr->default_fbo;
+ glBindFramebuffer(GL_FRAMEBUFFER_EXT, ctx->d_ptr->default_fbo);
+#ifdef QT_DEBUG
+ } else {
+ qWarning("QGLFramebufferObject::bindDefault() called without current context.");
+#endif
+ }
+
+ return ctx != 0;
+}
+
+/*!
\fn bool QGLFramebufferObject::hasOpenGLFramebufferObjects()
Returns true if the OpenGL \c{GL_EXT_framebuffer_object} extension
diff --git a/src/opengl/qglframebufferobject.h b/src/opengl/qglframebufferobject.h
index 306b6ff..6ff6645 100644
--- a/src/opengl/qglframebufferobject.h
+++ b/src/opengl/qglframebufferobject.h
@@ -108,6 +108,8 @@ public:
QPaintEngine *paintEngine() const;
GLuint handle() const;
+ static bool bindDefault();
+
static bool hasOpenGLFramebufferObjects();
void drawTexture(const QRectF &target, GLuint textureId, GLenum textureTarget = GL_TEXTURE_2D);
diff --git a/src/opengl/qglpaintdevice.cpp b/src/opengl/qglpaintdevice.cpp
index e874e85..e1dcbfd 100644
--- a/src/opengl/qglpaintdevice.cpp
+++ b/src/opengl/qglpaintdevice.cpp
@@ -175,7 +175,10 @@ void QGLWidgetGLPaintDevice::beginPaint()
float alpha = c.alphaF();
glClearColor(c.redF() * alpha, c.greenF() * alpha, c.blueF() * alpha, alpha);
}
- glClear(GL_COLOR_BUFFER_BIT);
+ if (context()->d_func()->workaround_needsFullClearOnEveryFrame)
+ glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
+ else
+ glClear(GL_COLOR_BUFFER_BIT);
}
}
diff --git a/src/opengl/qglpixmapfilter.cpp b/src/opengl/qglpixmapfilter.cpp
index d5a11d9..bfa5ef1 100644
--- a/src/opengl/qglpixmapfilter.cpp
+++ b/src/opengl/qglpixmapfilter.cpp
@@ -591,10 +591,11 @@ bool QGLPixmapDropShadowFilter::processGL(QPainter *painter, const QPointF &pos,
qt_blurImage(image, r * qreal(0.5), false, 1);
- GLuint texture = generateBlurTexture(image.size(), GL_ALPHA);
-
- glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, image.width(), image.height(), GL_ALPHA,
- GL_UNSIGNED_BYTE, image.bits());
+ GLuint texture;
+ glGenTextures(1, &texture);
+ glBindTexture(GL_TEXTURE_2D, texture);
+ glTexImage2D(GL_TEXTURE_2D, 0, GL_ALPHA, image.width(), image.height(),
+ 0, GL_ALPHA, GL_UNSIGNED_BYTE, image.bits());
info = new QGLBlurTextureInfo(image, texture, r);
}
diff --git a/src/opengl/qpaintengine_opengl.cpp b/src/opengl/qpaintengine_opengl.cpp
index 306fd8b..12c487d 100644
--- a/src/opengl/qpaintengine_opengl.cpp
+++ b/src/opengl/qpaintengine_opengl.cpp
@@ -668,6 +668,7 @@ public:
, last_created_state(0)
, shader_ctx(0)
, grad_palette(0)
+ , tess_points(0)
, drawable_texture(0)
, ref_cleaner(this)
{}
@@ -1450,6 +1451,11 @@ bool QOpenGLPaintEngine::end()
d->device->endPaint();
qt_mask_texture_cache()->maintainCache();
+#if defined(Q_WS_X11)
+ // clear out the references we hold for textures bound with the
+ // texture_from_pixmap extension
+ ctx->d_func()->boundPixmaps.clear();
+#endif
return true;
}
@@ -1950,6 +1956,8 @@ void QOpenGLPaintEnginePrivate::pathToVertexArrays(const QPainterPath &path)
void QOpenGLPaintEnginePrivate::drawVertexArrays()
{
+ if (tess_points_stops.count() == 0)
+ return;
glEnableClientState(GL_VERTEX_ARRAY);
glVertexPointer(2, GL_DOUBLE, 0, tess_points.data());
int previous_stop = 0;
@@ -3947,7 +3955,7 @@ void QOpenGLPaintEnginePrivate::strokeLines(const QPainterPath &path)
enableClipping();
}
-extern bool qt_scaleForTransform(const QTransform &transform, qreal *scale); // qtransform.cpp
+Q_GUI_EXPORT bool qt_scaleForTransform(const QTransform &transform, qreal *scale); // qtransform.cpp
void QOpenGLPaintEnginePrivate::strokePath(const QPainterPath &path, bool use_cache)
{
@@ -4991,7 +4999,7 @@ void QOpenGLPaintEngine::drawTextItem(const QPointF &p, const QTextItem &textIte
{
QStaticTextItem staticTextItem;
- staticTextItem.chars = ti.chars;
+ staticTextItem.chars = const_cast<QChar *>(ti.chars);
staticTextItem.fontEngine = ti.fontEngine;
staticTextItem.glyphs = glyphs.data();
staticTextItem.numChars = ti.num_chars;