src/opengl/qglbuffer.cpp
changeset 33 3e2da88830cd
parent 30 5dc02b23752f
child 37 758a864f9613
--- a/src/opengl/qglbuffer.cpp	Tue Jul 06 15:10:48 2010 +0300
+++ b/src/opengl/qglbuffer.cpp	Wed Aug 18 10:37:55 2010 +0300
@@ -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 @@
     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 @@
 {
 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 @@
 };
 
 /*!
+    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 @@
 {
 }
 
+/*!
+    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,16 +192,30 @@
 */
 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;
+}
+
+/*!
     Returns the type of buffer represented by this object.
 */
 QGLBuffer::Type QGLBuffer::type() const
@@ -215,7 +271,7 @@
     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 @@
 /*!
     Returns true if this buffer has been created; false otherwise.
 
-    \sa create()
+    \sa create(), destroy()
 */
 bool QGLBuffer::isCreated() const
 {
@@ -251,6 +307,24 @@
 }
 
 /*!
+    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