From 6d908473ec1a8c72f4bbb9d772e801024c3a62a0 Mon Sep 17 00:00:00 2001 From: Rhys Weatherley Date: Mon, 7 Sep 2009 10:18:46 +1000 Subject: Performance: Convert QGLFormat to use implicit sharing QGLFormat was being deep-copied many times per frame because of code like this: if (context()->format().doubleBuffer()) { ... This change modifies QGLFormat to use implicit sharing to reduce the overhead of the above type of checks. Reviewed-by: Sarah Smith --- src/opengl/qgl.cpp | 38 ++++++++++++++++++++++++++++++++++---- src/opengl/qgl.h | 4 ++-- src/opengl/qgl_p.h | 21 ++++++++++++++++++++- 3 files changed, 56 insertions(+), 7 deletions(-) diff --git a/src/opengl/qgl.cpp b/src/opengl/qgl.cpp index ef07447..aa67677 100644 --- a/src/opengl/qgl.cpp +++ b/src/opengl/qgl.cpp @@ -349,13 +349,26 @@ QGLFormat::QGLFormat(QGL::FormatOptions options, int plane) } /*! + \internal +*/ +void QGLFormat::detach() +{ + if (d->ref != 1) { + QGLFormatPrivate *newd = new QGLFormatPrivate(d); + if (!d->ref.deref()) + delete d; + d = newd; + } +} + +/*! Constructs a copy of \a other. */ QGLFormat::QGLFormat(const QGLFormat &other) { - d = new QGLFormatPrivate; - *d = *other.d; + d = other.d; + d->ref.ref(); } /*! @@ -364,7 +377,12 @@ QGLFormat::QGLFormat(const QGLFormat &other) QGLFormat &QGLFormat::operator=(const QGLFormat &other) { - *d = *other.d; + if (d != other.d) { + other.d->ref.ref(); + if (!d->ref.deref()) + delete d; + d = other.d; + } return *this; } @@ -373,7 +391,8 @@ QGLFormat &QGLFormat::operator=(const QGLFormat &other) */ QGLFormat::~QGLFormat() { - delete d; + if (!d->ref.deref()) + delete d; } /*! @@ -649,6 +668,7 @@ int QGLFormat::samples() const */ void QGLFormat::setSamples(int numSamples) { + detach(); if (numSamples < 0) { qWarning("QGLFormat::setSamples: Cannot have negative number of samples per pixel %d", numSamples); return; @@ -676,6 +696,7 @@ void QGLFormat::setSamples(int numSamples) */ void QGLFormat::setSwapInterval(int interval) { + detach(); d->swapInterval = interval; } @@ -743,6 +764,7 @@ int QGLFormat::plane() const */ void QGLFormat::setPlane(int plane) { + detach(); d->pln = plane; } @@ -754,6 +776,7 @@ void QGLFormat::setPlane(int plane) void QGLFormat::setOption(QGL::FormatOptions opt) { + detach(); if (opt & 0xffff) d->opts |= opt; else @@ -783,6 +806,7 @@ bool QGLFormat::testOption(QGL::FormatOptions opt) const */ void QGLFormat::setDepthBufferSize(int size) { + detach(); if (size < 0) { qWarning("QGLFormat::setDepthBufferSize: Cannot set negative depth buffer size %d", size); return; @@ -809,6 +833,7 @@ int QGLFormat::depthBufferSize() const */ void QGLFormat::setRedBufferSize(int size) { + detach(); if (size < 0) { qWarning("QGLFormat::setRedBufferSize: Cannot set negative red buffer size %d", size); return; @@ -837,6 +862,7 @@ int QGLFormat::redBufferSize() const */ void QGLFormat::setGreenBufferSize(int size) { + detach(); if (size < 0) { qWarning("QGLFormat::setGreenBufferSize: Cannot set negative green buffer size %d", size); return; @@ -865,6 +891,7 @@ int QGLFormat::greenBufferSize() const */ void QGLFormat::setBlueBufferSize(int size) { + detach(); if (size < 0) { qWarning("QGLFormat::setBlueBufferSize: Cannot set negative blue buffer size %d", size); return; @@ -892,6 +919,7 @@ int QGLFormat::blueBufferSize() const */ void QGLFormat::setAlphaBufferSize(int size) { + detach(); if (size < 0) { qWarning("QGLFormat::setAlphaBufferSize: Cannot set negative alpha buffer size %d", size); return; @@ -918,6 +946,7 @@ int QGLFormat::alphaBufferSize() const */ void QGLFormat::setAccumBufferSize(int size) { + detach(); if (size < 0) { qWarning("QGLFormat::setAccumBufferSize: Cannot set negative accumulate buffer size %d", size); return; @@ -942,6 +971,7 @@ int QGLFormat::accumBufferSize() const */ void QGLFormat::setStencilBufferSize(int size) { + detach(); if (size < 0) { qWarning("QGLFormat::setStencilBufferSize: Cannot set negative stencil buffer size %d", size); return; diff --git a/src/opengl/qgl.h b/src/opengl/qgl.h index 89f1676..0d72469 100644 --- a/src/opengl/qgl.h +++ b/src/opengl/qgl.h @@ -255,6 +255,8 @@ public: private: QGLFormatPrivate *d; + void detach(); + friend Q_OPENGL_EXPORT bool operator==(const QGLFormat&, const QGLFormat&); friend Q_OPENGL_EXPORT bool operator!=(const QGLFormat&, const QGLFormat&); }; @@ -277,7 +279,6 @@ public: bool isSharing() const; void reset(); - // ### Qt 5: make format() return a const ref instead QGLFormat format() const; QGLFormat requestedFormat() const; void setFormat(const QGLFormat& format); @@ -443,7 +444,6 @@ public: bool doubleBuffer() const; void swapBuffers(); - // ### Qt 5: make format() return a const ref instead QGLFormat format() const; void setFormat(const QGLFormat& format); diff --git a/src/opengl/qgl_p.h b/src/opengl/qgl_p.h index 72ec35e..d4b7597 100644 --- a/src/opengl/qgl_p.h +++ b/src/opengl/qgl_p.h @@ -59,6 +59,7 @@ #include "QtCore/qthread.h" #include "QtCore/qthreadstorage.h" #include "QtCore/qhash.h" +#include "QtCore/qatomic.h" #include "private/qwidget_p.h" #include "qcache.h" @@ -127,7 +128,9 @@ QT_END_INCLUDE_NAMESPACE class QGLFormatPrivate { public: - QGLFormatPrivate() { + QGLFormatPrivate() + : ref(1) + { opts = QGL::DoubleBuffer | QGL::DepthBuffer | QGL::Rgba | QGL::DirectRendering | QGL::StencilBuffer; #if defined(QT_OPENGL_ES_2) opts |= QGL::SampleBuffers; @@ -137,6 +140,22 @@ public: numSamples = -1; swapInterval = -1; } + QGLFormatPrivate(const QGLFormatPrivate *other) + : ref(1), + opts(other->opts), + pln(other->pln), + depthSize(other->depthSize), + accumSize(other->accumSize), + stencilSize(other->stencilSize), + redSize(other->redSize), + greenSize(other->greenSize), + blueSize(other->blueSize), + alphaSize(other->alphaSize), + numSamples(other->numSamples), + swapInterval(other->swapInterval) + { + } + QAtomicInt ref; QGL::FormatOptions opts; int pln; int depthSize; -- cgit v0.12