summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorQt Continuous Integration System <qt-info@nokia.com>2010-09-23 07:25:18 (GMT)
committerQt Continuous Integration System <qt-info@nokia.com>2010-09-23 07:25:18 (GMT)
commit932e67e3e817f0e2625ff60594e6e536920a329a (patch)
treec63afe16124bb3af2429b7cf04afaa65760ad600 /src
parent979ab9bf9394210dc4812082fe40b083155447c5 (diff)
parent4f24b2fbe7fbbdae95b27381e258ec7b665445c5 (diff)
downloadQt-932e67e3e817f0e2625ff60594e6e536920a329a.zip
Qt-932e67e3e817f0e2625ff60594e6e536920a329a.tar.gz
Qt-932e67e3e817f0e2625ff60594e6e536920a329a.tar.bz2
Merge branch '4.7' of scm.dev.nokia.troll.no:qt/oslo-staging-2 into 4.7-integration
* '4.7' of scm.dev.nokia.troll.no:qt/oslo-staging-2: QPainter not restored correctly in Graphics View. Setting QGraphicsItem::ItemClipsChildrenToShape forces ItemClipsToShape Fix compilation Fixed drawing of QPixmaps with masks in the GL 2 and X11 engines. Fix warning on MSVC QThread: make sure start works even if called after exit Revert "Fixed painter path drawing on FBO without stencil buffer." Fix a crash with D&d on mingw Revert "Keep other text format with QTextOption::SuppressColors tag on" Fixed stencil buffer on FBOs with OpenGL ES. Keep other text format with QTextOption::SuppressColors tag on QTreeView: do not scroll to top if last item is removed
Diffstat (limited to 'src')
-rw-r--r--src/corelib/thread/qthread_unix.cpp2
-rw-r--r--src/corelib/thread/qthread_win.cpp2
-rw-r--r--src/gui/graphicsview/qgraphicsscene.cpp126
-rw-r--r--src/gui/graphicsview/qgraphicsview.cpp3
-rw-r--r--src/gui/image/qpixmap_x11.cpp11
-rw-r--r--src/gui/image/qpixmap_x11_p.h1
-rw-r--r--src/gui/image/qpixmapdata.cpp5
-rw-r--r--src/gui/image/qpixmapdata_p.h1
-rw-r--r--src/gui/itemviews/qtreeview.cpp4
-rw-r--r--src/gui/kernel/qdnd_win.cpp12
-rw-r--r--src/gui/styles/qstylehelper_p.h2
-rw-r--r--src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp28
-rw-r--r--src/opengl/qgl_x11.cpp4
-rw-r--r--src/opengl/qglframebufferobject.cpp105
-rw-r--r--src/opengl/qglframebufferobject_p.h5
15 files changed, 199 insertions, 112 deletions
diff --git a/src/corelib/thread/qthread_unix.cpp b/src/corelib/thread/qthread_unix.cpp
index 2824e15..a7601b6 100644
--- a/src/corelib/thread/qthread_unix.cpp
+++ b/src/corelib/thread/qthread_unix.cpp
@@ -514,6 +514,8 @@ void QThread::start(Priority priority)
d->running = true;
d->finished = false;
d->terminated = false;
+ d->returnCode = 0;
+ d->exited = false;
pthread_attr_t attr;
pthread_attr_init(&attr);
diff --git a/src/corelib/thread/qthread_win.cpp b/src/corelib/thread/qthread_win.cpp
index 37d5b87..f0cbe8d 100644
--- a/src/corelib/thread/qthread_win.cpp
+++ b/src/corelib/thread/qthread_win.cpp
@@ -405,6 +405,8 @@ void QThread::start(Priority priority)
d->running = true;
d->finished = false;
d->terminated = false;
+ d->exited = false;
+ d->returnCode = 0;
/*
NOTE: we create the thread in the suspended state, set the
diff --git a/src/gui/graphicsview/qgraphicsscene.cpp b/src/gui/graphicsview/qgraphicsscene.cpp
index 54fdf3f..8dc15bf 100644
--- a/src/gui/graphicsview/qgraphicsscene.cpp
+++ b/src/gui/graphicsview/qgraphicsscene.cpp
@@ -4814,6 +4814,27 @@ void QGraphicsScenePrivate::drawSubtreeRecursive(QGraphicsItem *item, QPainter *
}
}
+static inline void setClip(QPainter *painter, QGraphicsItem *item)
+{
+ painter->save();
+ QRectF clipRect;
+ const QPainterPath clipPath(item->shape());
+ if (QPathClipper::pathToRect(clipPath, &clipRect))
+ painter->setClipRect(clipRect, Qt::IntersectClip);
+ else
+ painter->setClipPath(clipPath, Qt::IntersectClip);
+}
+
+static inline void setWorldTransform(QPainter *painter, const QTransform *const transformPtr,
+ const QTransform *effectTransform)
+{
+ Q_ASSERT(transformPtr);
+ if (effectTransform)
+ painter->setWorldTransform(*transformPtr * *effectTransform);
+ else
+ painter->setWorldTransform(*transformPtr);
+}
+
void QGraphicsScenePrivate::draw(QGraphicsItem *item, QPainter *painter, const QTransform *const viewTransform,
const QTransform *const transformPtr, QRegion *exposedRegion, QWidget *widget,
qreal opacity, const QTransform *effectTransform,
@@ -4822,36 +4843,37 @@ void QGraphicsScenePrivate::draw(QGraphicsItem *item, QPainter *painter, const Q
const bool itemIsFullyTransparent = QGraphicsItemPrivate::isOpacityNull(opacity);
const bool itemClipsChildrenToShape = (item->d_ptr->flags & QGraphicsItem::ItemClipsChildrenToShape);
const bool itemHasChildren = !item->d_ptr->children.isEmpty();
+ bool setChildClip = itemClipsChildrenToShape;
+ bool itemHasChildrenStackedBehind = false;
int i = 0;
if (itemHasChildren) {
+ if (itemClipsChildrenToShape)
+ setWorldTransform(painter, transformPtr, effectTransform);
+
item->d_ptr->ensureSortedChildren();
+ // Items with the 'ItemStacksBehindParent' flag are put in front of the list
+ // so all we have to do is to check the first item.
+ itemHasChildrenStackedBehind = (item->d_ptr->children.at(0)->d_ptr->flags
+ & QGraphicsItem::ItemStacksBehindParent);
- if (itemClipsChildrenToShape) {
- painter->save();
- Q_ASSERT(transformPtr);
- if (effectTransform)
- painter->setWorldTransform(*transformPtr * *effectTransform);
- else
- painter->setWorldTransform(*transformPtr);
- QRectF clipRect;
- const QPainterPath clipPath(item->shape());
- if (QPathClipper::pathToRect(clipPath, &clipRect))
- painter->setClipRect(clipRect, Qt::IntersectClip);
- else
- painter->setClipPath(clipPath, Qt::IntersectClip);
- }
+ if (itemHasChildrenStackedBehind) {
+ if (itemClipsChildrenToShape) {
+ setClip(painter, item);
+ setChildClip = false;
+ }
- // Draw children behind
- for (i = 0; i < item->d_ptr->children.size(); ++i) {
- QGraphicsItem *child = item->d_ptr->children.at(i);
- if (wasDirtyParentSceneTransform)
- child->d_ptr->dirtySceneTransform = 1;
- if (!(child->d_ptr->flags & QGraphicsItem::ItemStacksBehindParent))
- break;
- if (itemIsFullyTransparent && !(child->d_ptr->flags & QGraphicsItem::ItemIgnoresParentOpacity))
- continue;
- drawSubtreeRecursive(child, painter, viewTransform, exposedRegion, widget, opacity, effectTransform);
+ // Draw children behind
+ for (i = 0; i < item->d_ptr->children.size(); ++i) {
+ QGraphicsItem *child = item->d_ptr->children.at(i);
+ if (wasDirtyParentSceneTransform)
+ child->d_ptr->dirtySceneTransform = 1;
+ if (!(child->d_ptr->flags & QGraphicsItem::ItemStacksBehindParent))
+ break;
+ if (itemIsFullyTransparent && !(child->d_ptr->flags & QGraphicsItem::ItemIgnoresParentOpacity))
+ continue;
+ drawSubtreeRecursive(child, painter, viewTransform, exposedRegion, widget, opacity, effectTransform);
+ }
}
}
@@ -4864,38 +4886,50 @@ void QGraphicsScenePrivate::draw(QGraphicsItem *item, QPainter *painter, const Q
? *exposedRegion : QRegion(), exposedRegion == 0);
const bool itemClipsToShape = item->d_ptr->flags & QGraphicsItem::ItemClipsToShape;
- const bool savePainter = itemClipsToShape || painterStateProtection;
- if (savePainter)
- painter->save();
+ bool restorePainterClip = false;
if (!itemHasChildren || !itemClipsChildrenToShape) {
- if (effectTransform)
- painter->setWorldTransform(*transformPtr * *effectTransform);
- else
- painter->setWorldTransform(*transformPtr);
+ // Item does not have children or clip children to shape.
+ setWorldTransform(painter, transformPtr, effectTransform);
+ if ((restorePainterClip = itemClipsToShape))
+ setClip(painter, item);
+ } else if (itemHasChildrenStackedBehind){
+ // Item clips children to shape and has children stacked behind, which means
+ // the painter is already clipped to the item's shape.
+ if (itemClipsToShape) {
+ // The clip is already correct. Ensure correct world transform.
+ setWorldTransform(painter, transformPtr, effectTransform);
+ } else {
+ // Remove clip (this also ensures correct world transform).
+ painter->restore();
+ setChildClip = true;
+ }
+ } else if (itemClipsToShape) {
+ // Item clips children and itself to shape. It does not have hildren stacked
+ // behind, which means the clip has not yet been set. We set it now and re-use it
+ // for the children.
+ setClip(painter, item);
+ setChildClip = false;
}
- if (itemClipsToShape) {
- QRectF clipRect;
- const QPainterPath clipPath(item->shape());
- if (QPathClipper::pathToRect(clipPath, &clipRect))
- painter->setClipRect(clipRect, Qt::IntersectClip);
- else
- painter->setClipPath(clipPath, Qt::IntersectClip);
- }
- painter->setOpacity(opacity);
+ if (painterStateProtection && !restorePainterClip)
+ painter->save();
+ painter->setOpacity(opacity);
if (!item->d_ptr->cacheMode && !item->d_ptr->isWidget)
item->paint(painter, &styleOptionTmp, widget);
else
drawItemHelper(item, painter, &styleOptionTmp, widget, painterStateProtection);
- if (savePainter)
+ if (painterStateProtection || restorePainterClip)
painter->restore();
}
// Draw children in front
if (itemHasChildren) {
+ if (setChildClip)
+ setClip(painter, item);
+
for (; i < item->d_ptr->children.size(); ++i) {
QGraphicsItem *child = item->d_ptr->children.at(i);
if (wasDirtyParentSceneTransform)
@@ -4904,11 +4938,11 @@ void QGraphicsScenePrivate::draw(QGraphicsItem *item, QPainter *painter, const Q
continue;
drawSubtreeRecursive(child, painter, viewTransform, exposedRegion, widget, opacity, effectTransform);
}
- }
- // Restore child clip
- if (itemHasChildren && itemClipsChildrenToShape)
- painter->restore();
+ // Restore child clip
+ if (itemClipsChildrenToShape)
+ painter->restore();
+ }
}
void QGraphicsScenePrivate::markDirty(QGraphicsItem *item, const QRectF &rect, bool invalidateChildren,
@@ -5271,6 +5305,7 @@ void QGraphicsScene::drawItems(QPainter *painter,
if (!d->unpolishedItems.isEmpty())
d->_q_polishItems();
+ const qreal opacity = painter->opacity();
QTransform viewTransform = painter->worldTransform();
Q_UNUSED(options);
@@ -5304,6 +5339,7 @@ void QGraphicsScene::drawItems(QPainter *painter,
topLevelItems.at(i)->d_ptr->itemDiscovered = 0;
painter->setWorldTransform(viewTransform);
+ painter->setOpacity(opacity);
}
/*!
diff --git a/src/gui/graphicsview/qgraphicsview.cpp b/src/gui/graphicsview/qgraphicsview.cpp
index c8aca80..a566c8e 100644
--- a/src/gui/graphicsview/qgraphicsview.cpp
+++ b/src/gui/graphicsview/qgraphicsview.cpp
@@ -3475,7 +3475,8 @@ void QGraphicsView::paintEvent(QPaintEvent *event)
// IndirectPainting (the else branch), because in that case we always save()
// and restore() in QGraphicsScene::drawItems().
if (!d->scene->d_func()->painterStateProtection)
- painter.setWorldTransform(viewTransform);
+ painter.setOpacity(1.0);
+ painter.setWorldTransform(viewTransform);
} else {
// Make sure we don't have unpolished items before we draw
if (!d->scene->d_func()->unpolishedItems.isEmpty())
diff --git a/src/gui/image/qpixmap_x11.cpp b/src/gui/image/qpixmap_x11.cpp
index 3d9c363..32676ba 100644
--- a/src/gui/image/qpixmap_x11.cpp
+++ b/src/gui/image/qpixmap_x11.cpp
@@ -1321,6 +1321,15 @@ QBitmap QX11PixmapData::mask() const
return mask;
}
+bool QX11PixmapData::hasMask() const
+{
+ return
+#ifndef QT_NO_XRENDER
+ (picture && d == 32) ||
+#endif
+ (d == 1) || x11_mask;
+}
+
/*!
Sets a mask bitmap.
@@ -1549,7 +1558,7 @@ QImage QX11PixmapData::toImage(const QRect &rect) const
if (!xiWrapper.xi)
return QImage();
- if (canTakeQImageFromXImage(xiWrapper))
+ if (!x11_mask && canTakeQImageFromXImage(xiWrapper))
return takeQImageFromXImage(xiWrapper);
QImage image = toImage(xiWrapper, rect);
diff --git a/src/gui/image/qpixmap_x11_p.h b/src/gui/image/qpixmap_x11_p.h
index 821fb69..fcad1a2 100644
--- a/src/gui/image/qpixmap_x11_p.h
+++ b/src/gui/image/qpixmap_x11_p.h
@@ -82,6 +82,7 @@ public:
void fill(const QColor &color);
QBitmap mask() const;
+ bool hasMask() const;
void setMask(const QBitmap &mask);
bool hasAlphaChannel() const;
void setAlphaChannel(const QPixmap &alphaChannel);
diff --git a/src/gui/image/qpixmapdata.cpp b/src/gui/image/qpixmapdata.cpp
index ef1f6c4..2813ed1 100644
--- a/src/gui/image/qpixmapdata.cpp
+++ b/src/gui/image/qpixmapdata.cpp
@@ -239,6 +239,11 @@ QBitmap QPixmapData::mask() const
return QBitmap::fromImage(mask);
}
+bool QPixmapData::hasMask() const
+{
+ return hasAlphaChannel();
+}
+
QPixmap QPixmapData::transformed(const QTransform &matrix,
Qt::TransformationMode mode) const
{
diff --git a/src/gui/image/qpixmapdata_p.h b/src/gui/image/qpixmapdata_p.h
index ec62b0b..c341930 100644
--- a/src/gui/image/qpixmapdata_p.h
+++ b/src/gui/image/qpixmapdata_p.h
@@ -99,6 +99,7 @@ public:
virtual int metric(QPaintDevice::PaintDeviceMetric metric) const = 0;
virtual void fill(const QColor &color) = 0;
virtual QBitmap mask() const;
+ virtual bool hasMask() const;
virtual void setMask(const QBitmap &mask);
virtual bool hasAlphaChannel() const = 0;
virtual QPixmap transformed(const QTransform &matrix,
diff --git a/src/gui/itemviews/qtreeview.cpp b/src/gui/itemviews/qtreeview.cpp
index b797776..40b51fe 100644
--- a/src/gui/itemviews/qtreeview.cpp
+++ b/src/gui/itemviews/qtreeview.cpp
@@ -3435,6 +3435,10 @@ void QTreeViewPrivate::updateScrollBars()
if (!viewportSize.isValid())
viewportSize = QSize(0, 0);
+ if (viewItems.isEmpty()) {
+ q->doItemsLayout();
+ }
+
int itemsInViewport = 0;
if (uniformRowHeights) {
if (defaultItemHeight <= 0)
diff --git a/src/gui/kernel/qdnd_win.cpp b/src/gui/kernel/qdnd_win.cpp
index a164c2a..7083886 100644
--- a/src/gui/kernel/qdnd_win.cpp
+++ b/src/gui/kernel/qdnd_win.cpp
@@ -515,7 +515,7 @@ static inline Qt::MouseButtons keystate_to_mousebutton(DWORD grfKeyState)
//---------------------------------------------------------------------
// IDropSource Methods
//---------------------------------------------------------------------
-STDMETHODIMP
+QT_ENSURE_STACK_ALIGNED_FOR_SSE STDMETHODIMP
QOleDropSource::QueryContinueDrag(BOOL fEscapePressed, DWORD grfKeyState)
{
#ifdef QDND_DEBUG
@@ -545,7 +545,7 @@ QOleDropSource::QueryContinueDrag(BOOL fEscapePressed, DWORD grfKeyState)
}
}
-STDMETHODIMP
+QT_ENSURE_STACK_ALIGNED_FOR_SSE STDMETHODIMP
QOleDropSource::GiveFeedback(DWORD dwEffect)
{
Qt::DropAction action = translateToQDragDropAction(dwEffect);
@@ -626,7 +626,7 @@ QOleDropTarget::Release(void)
// IDropTarget Methods
//---------------------------------------------------------------------
-STDMETHODIMP
+QT_ENSURE_STACK_ALIGNED_FOR_SSE STDMETHODIMP
QOleDropTarget::DragEnter(LPDATAOBJECT pDataObj, DWORD grfKeyState, POINTL pt, LPDWORD pdwEffect)
{
#ifdef QDND_DEBUG
@@ -688,7 +688,7 @@ void QOleDropTarget::sendDragEnterEvent(QWidget *dragEnterWidget, DWORD grfKeySt
}
-STDMETHODIMP
+QT_ENSURE_STACK_ALIGNED_FOR_SSE STDMETHODIMP
QOleDropTarget::DragOver(DWORD grfKeyState, POINTL pt, LPDWORD pdwEffect)
{
#ifdef QDND_DEBUG
@@ -758,7 +758,7 @@ QOleDropTarget::DragOver(DWORD grfKeyState, POINTL pt, LPDWORD pdwEffect)
return NOERROR;
}
-STDMETHODIMP
+QT_ENSURE_STACK_ALIGNED_FOR_SSE STDMETHODIMP
QOleDropTarget::DragLeave()
{
#ifdef QDND_DEBUG
@@ -785,7 +785,7 @@ QOleDropTarget::DragLeave()
#define KEY_STATE_BUTTON_MASK (MK_LBUTTON | MK_MBUTTON | MK_RBUTTON)
-STDMETHODIMP
+QT_ENSURE_STACK_ALIGNED_FOR_SSE STDMETHODIMP
QOleDropTarget::Drop(LPDATAOBJECT /*pDataObj*/, DWORD grfKeyState, POINTL pt, LPDWORD pdwEffect)
{
#ifdef QDND_DEBUG
diff --git a/src/gui/styles/qstylehelper_p.h b/src/gui/styles/qstylehelper_p.h
index 71fce55..3759929 100644
--- a/src/gui/styles/qstylehelper_p.h
+++ b/src/gui/styles/qstylehelper_p.h
@@ -108,7 +108,7 @@ template <typename T>
{
typedef HexString<T> type;
enum { ExactSize = true };
- static int size(const HexString<T> &str) { return sizeof(str.val) * 2; }
+ static int size(const HexString<T> &) { return sizeof(T) * 2; }
static inline void appendTo(const HexString<T> &str, QChar *&out) { str.write(out); }
};
diff --git a/src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp b/src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp
index 2347e66..6eb5a36 100644
--- a/src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp
+++ b/src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp
@@ -866,32 +866,6 @@ void QGL2PaintEngineExPrivate::fill(const QVectorPath& path)
if (do_vectorpath_cache)
path.makeCacheable();
- if (!device->format().stencil()) {
- // If there is no stencil buffer, triangulate the path instead.
-
- QRectF bbox = path.controlPointRect();
- // If the path doesn't fit within these limits, it is possible that the triangulation will fail.
- bool withinLimits = (bbox.left() > -0x8000 * inverseScale)
- && (bbox.right() < 0x8000 * inverseScale)
- && (bbox.top() > -0x8000 * inverseScale)
- && (bbox.bottom() < 0x8000 * inverseScale);
- if (withinLimits) {
- QTriangleSet polys = qTriangulate(path, QTransform().scale(1 / inverseScale, 1 / inverseScale));
-
- QVarLengthArray<float> vertices(polys.vertices.size());
- for (int i = 0; i < polys.vertices.size(); ++i)
- vertices[i] = float(inverseScale * polys.vertices.at(i));
-
- prepareForDraw(currentBrush.isOpaque());
- setVertexAttributePointer(QT_VERTEX_COORDS_ATTR, vertices.constData());
- glDrawElements(GL_TRIANGLES, polys.indices.size(), GL_UNSIGNED_INT, polys.indices.constData());
- } else {
- // We can't handle big, concave painter paths with OpenGL without stencil buffer.
- qWarning("Painter path exceeds +/-32767 pixels.");
- }
- return;
- }
-
// The path is too complicated & needs the stencil technique
vertexCoordinateArray.clear();
vertexCoordinateArray.addPath(path, inverseScale, false);
@@ -1340,7 +1314,7 @@ void QGL2PaintEngineEx::drawPixmap(const QRectF& dest, const QPixmap & pixmap, c
QGLRect srcRect(src.left(), top, src.right(), bottom);
bool isBitmap = pixmap.isQBitmap();
- bool isOpaque = !isBitmap && !pixmap.hasAlphaChannel();
+ bool isOpaque = !isBitmap && !pixmap.hasAlphaChannel() && !pixmap.pixmapData()->hasMask();
d->updateTextureFilter(GL_TEXTURE_2D, GL_CLAMP_TO_EDGE,
state()->renderHints & QPainter::SmoothPixmapTransform, texture->id);
diff --git a/src/opengl/qgl_x11.cpp b/src/opengl/qgl_x11.cpp
index f3a4c95..7f4c670 100644
--- a/src/opengl/qgl_x11.cpp
+++ b/src/opengl/qgl_x11.cpp
@@ -1776,6 +1776,10 @@ QGLTexture *QGLContextPrivate::bindTextureFromNativePixmap(QPixmap *pixmap, cons
QX11PixmapData *pixmapData = static_cast<QX11PixmapData*>(pixmap->data_ptr().data());
Q_ASSERT(pixmapData->classId() == QPixmapData::X11Class);
+ // We can't use TFP if the pixmap has a separate X11 mask
+ if (pixmapData->x11_mask)
+ return 0;
+
if (!qt_resolveTextureFromPixmap(paintDevice))
return 0;
diff --git a/src/opengl/qglframebufferobject.cpp b/src/opengl/qglframebufferobject.cpp
index adbba85..6c9b288 100644
--- a/src/opengl/qglframebufferobject.cpp
+++ b/src/opengl/qglframebufferobject.cpp
@@ -324,10 +324,6 @@ void QGLFBOGLPaintDevice::setFBO(QGLFramebufferObject* f,
fboFormat.setStencil(true);
} else if (attachment == QGLFramebufferObject::Depth) {
fboFormat.setDepth(true);
- fboFormat.setStencil(false);
- } else {
- fboFormat.setDepth(false);
- fboFormat.setStencil(false);
}
GLenum format = f->format().internalTextureFormat();
@@ -472,13 +468,17 @@ void QGLFramebufferObjectPrivate::init(QGLFramebufferObject *q, const QSize &sz,
glGetRenderbufferParameteriv(GL_RENDERBUFFER_EXT, GL_RENDERBUFFER_SAMPLES_EXT, &samples);
}
+ // In practice, a combined depth-stencil buffer is supported by all desktop platforms, while a
+ // separate stencil buffer is not. On embedded devices however, a combined depth-stencil buffer
+ // might not be supported while separate buffers are, according to QTBUG-12861.
+
if (attachment == QGLFramebufferObject::CombinedDepthStencil
&& (QGLExtensions::glExtensions() & QGLExtensions::PackedDepthStencil)) {
// depth and stencil buffer needs another extension
- glGenRenderbuffers(1, &depth_stencil_buffer);
- Q_ASSERT(!glIsRenderbuffer(depth_stencil_buffer));
- glBindRenderbuffer(GL_RENDERBUFFER_EXT, depth_stencil_buffer);
- Q_ASSERT(glIsRenderbuffer(depth_stencil_buffer));
+ glGenRenderbuffers(1, &depth_buffer);
+ Q_ASSERT(!glIsRenderbuffer(depth_buffer));
+ glBindRenderbuffer(GL_RENDERBUFFER_EXT, depth_buffer);
+ Q_ASSERT(glIsRenderbuffer(depth_buffer));
if (samples != 0 && glRenderbufferStorageMultisampleEXT)
glRenderbufferStorageMultisampleEXT(GL_RENDERBUFFER_EXT, samples,
GL_DEPTH24_STENCIL8_EXT, size.width(), size.height());
@@ -486,24 +486,26 @@ void QGLFramebufferObjectPrivate::init(QGLFramebufferObject *q, const QSize &sz,
glRenderbufferStorage(GL_RENDERBUFFER_EXT,
GL_DEPTH24_STENCIL8_EXT, size.width(), size.height());
- GLint i = 0;
- glGetRenderbufferParameteriv(GL_RENDERBUFFER_EXT, GL_RENDERBUFFER_DEPTH_SIZE_EXT, &i);
+ stencil_buffer = depth_buffer;
glFramebufferRenderbuffer(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT,
- GL_RENDERBUFFER_EXT, depth_stencil_buffer);
+ GL_RENDERBUFFER_EXT, depth_buffer);
glFramebufferRenderbuffer(GL_FRAMEBUFFER_EXT, GL_STENCIL_ATTACHMENT_EXT,
- GL_RENDERBUFFER_EXT, depth_stencil_buffer);
- fbo_attachment = QGLFramebufferObject::CombinedDepthStencil;
+ GL_RENDERBUFFER_EXT, stencil_buffer);
valid = checkFramebufferStatus();
- if (!valid)
- glDeleteRenderbuffers(1, &depth_stencil_buffer);
- } else if (attachment == QGLFramebufferObject::Depth
- || attachment == QGLFramebufferObject::CombinedDepthStencil)
+ if (!valid) {
+ glDeleteRenderbuffers(1, &depth_buffer);
+ stencil_buffer = depth_buffer = 0;
+ }
+ }
+
+ if (depth_buffer == 0 && (attachment == QGLFramebufferObject::CombinedDepthStencil
+ || (attachment == QGLFramebufferObject::Depth)))
{
- glGenRenderbuffers(1, &depth_stencil_buffer);
- Q_ASSERT(!glIsRenderbuffer(depth_stencil_buffer));
- glBindRenderbuffer(GL_RENDERBUFFER_EXT, depth_stencil_buffer);
- Q_ASSERT(glIsRenderbuffer(depth_stencil_buffer));
+ glGenRenderbuffers(1, &depth_buffer);
+ Q_ASSERT(!glIsRenderbuffer(depth_buffer));
+ glBindRenderbuffer(GL_RENDERBUFFER_EXT, depth_buffer);
+ Q_ASSERT(glIsRenderbuffer(depth_buffer));
if (samples != 0 && glRenderbufferStorageMultisampleEXT) {
#ifdef QT_OPENGL_ES
#define GL_DEPTH_COMPONENT16 0x81A5
@@ -521,14 +523,53 @@ void QGLFramebufferObjectPrivate::init(QGLFramebufferObject *q, const QSize &sz,
glRenderbufferStorage(GL_RENDERBUFFER_EXT, GL_DEPTH_COMPONENT, size.width(), size.height());
#endif
}
- GLint i = 0;
- glGetRenderbufferParameteriv(GL_RENDERBUFFER_EXT, GL_RENDERBUFFER_DEPTH_SIZE_EXT, &i);
glFramebufferRenderbuffer(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT,
- GL_RENDERBUFFER_EXT, depth_stencil_buffer);
- fbo_attachment = QGLFramebufferObject::Depth;
+ GL_RENDERBUFFER_EXT, depth_buffer);
valid = checkFramebufferStatus();
- if (!valid)
- glDeleteRenderbuffers(1, &depth_stencil_buffer);
+ if (!valid) {
+ glDeleteRenderbuffers(1, &depth_buffer);
+ depth_buffer = 0;
+ }
+ }
+
+ if (stencil_buffer == 0 && (attachment == QGLFramebufferObject::CombinedDepthStencil)) {
+ glGenRenderbuffers(1, &stencil_buffer);
+ Q_ASSERT(!glIsRenderbuffer(stencil_buffer));
+ glBindRenderbuffer(GL_RENDERBUFFER_EXT, stencil_buffer);
+ Q_ASSERT(glIsRenderbuffer(stencil_buffer));
+ if (samples != 0 && glRenderbufferStorageMultisampleEXT) {
+#ifdef QT_OPENGL_ES
+ glRenderbufferStorageMultisampleEXT(GL_RENDERBUFFER_EXT, samples,
+ GL_STENCIL_INDEX8_EXT, size.width(), size.height());
+#else
+ glRenderbufferStorageMultisampleEXT(GL_RENDERBUFFER_EXT, samples,
+ GL_STENCIL_INDEX, size.width(), size.height());
+#endif
+ } else {
+#ifdef QT_OPENGL_ES
+ glRenderbufferStorage(GL_RENDERBUFFER_EXT, GL_STENCIL_INDEX8_EXT,
+ size.width(), size.height());
+#else
+ glRenderbufferStorage(GL_RENDERBUFFER_EXT, GL_STENCIL_INDEX,
+ size.width(), size.height());
+#endif
+ }
+ glFramebufferRenderbuffer(GL_FRAMEBUFFER_EXT, GL_STENCIL_ATTACHMENT_EXT,
+ GL_RENDERBUFFER_EXT, stencil_buffer);
+ valid = checkFramebufferStatus();
+ if (!valid) {
+ glDeleteRenderbuffers(1, &stencil_buffer);
+ stencil_buffer = 0;
+ }
+ }
+
+ // The FBO might have become valid after removing the depth or stencil buffer.
+ valid = checkFramebufferStatus();
+
+ if (depth_buffer && stencil_buffer) {
+ fbo_attachment = QGLFramebufferObject::CombinedDepthStencil;
+ } else if (depth_buffer) {
+ fbo_attachment = QGLFramebufferObject::Depth;
} else {
fbo_attachment = QGLFramebufferObject::NoAttachment;
}
@@ -539,6 +580,10 @@ void QGLFramebufferObjectPrivate::init(QGLFramebufferObject *q, const QSize &sz,
glDeleteRenderbuffers(1, &color_buffer);
else
glDeleteTextures(1, &texture);
+ if (depth_buffer)
+ glDeleteRenderbuffers(1, &depth_buffer);
+ if (stencil_buffer && depth_buffer != stencil_buffer)
+ glDeleteRenderbuffers(1, &stencil_buffer);
glDeleteFramebuffers(1, &fbo);
fbo_guard.setId(0);
}
@@ -821,8 +866,10 @@ QGLFramebufferObject::~QGLFramebufferObject()
glDeleteTextures(1, &d->texture);
if (d->color_buffer)
glDeleteRenderbuffers(1, &d->color_buffer);
- if (d->depth_stencil_buffer)
- glDeleteRenderbuffers(1, &d->depth_stencil_buffer);
+ if (d->depth_buffer)
+ glDeleteRenderbuffers(1, &d->depth_buffer);
+ if (d->stencil_buffer && d->stencil_buffer != d->depth_buffer)
+ glDeleteRenderbuffers(1, &d->stencil_buffer);
GLuint fbo = d->fbo();
glDeleteFramebuffers(1, &fbo);
}
diff --git a/src/opengl/qglframebufferobject_p.h b/src/opengl/qglframebufferobject_p.h
index d8ff012..58b4e9e 100644
--- a/src/opengl/qglframebufferobject_p.h
+++ b/src/opengl/qglframebufferobject_p.h
@@ -126,7 +126,7 @@ private:
class QGLFramebufferObjectPrivate
{
public:
- QGLFramebufferObjectPrivate() : fbo_guard(0), texture(0), depth_stencil_buffer(0)
+ QGLFramebufferObjectPrivate() : fbo_guard(0), texture(0), depth_buffer(0), stencil_buffer(0)
, color_buffer(0), valid(false), engine(0) {}
~QGLFramebufferObjectPrivate() {}
@@ -136,7 +136,8 @@ public:
bool checkFramebufferStatus() const;
QGLSharedResourceGuard fbo_guard;
GLuint texture;
- GLuint depth_stencil_buffer;
+ GLuint depth_buffer;
+ GLuint stencil_buffer;
GLuint color_buffer;
GLenum target;
QSize size;