53 \ingroup painting-3D |
54 \ingroup painting-3D |
54 |
55 |
55 Buffer objects are created in the GL server so that the |
56 Buffer objects are created in the GL server so that the |
56 client application can avoid uploading vertices, indices, |
57 client application can avoid uploading vertices, indices, |
57 texture image data, etc every time they are needed. |
58 texture image data, etc every time they are needed. |
|
59 |
|
60 QGLBuffer objects can be copied around as a reference to the |
|
61 underlying GL buffer object: |
|
62 |
|
63 \code |
|
64 QGLBuffer buffer1(QGLBuffer::IndexBuffer); |
|
65 buffer1.create(); |
|
66 |
|
67 QGLBuffer buffer2 = buffer1; |
|
68 \endcode |
|
69 |
|
70 QGLBuffer performs a shallow copy when objects are copied in this |
|
71 manner, but does not implement copy-on-write semantics. The original |
|
72 object will be affected whenever the copy is modified. |
58 */ |
73 */ |
59 |
74 |
60 /*! |
75 /*! |
61 \enum QGLBuffer::Type |
76 \enum QGLBuffer::Type |
62 This enum defines the type of GL buffer object to create with QGLBuffer. |
77 This enum defines the type of GL buffer object to create with QGLBuffer. |
114 |
129 |
115 class QGLBufferPrivate |
130 class QGLBufferPrivate |
116 { |
131 { |
117 public: |
132 public: |
118 QGLBufferPrivate(QGLBuffer::Type t) |
133 QGLBufferPrivate(QGLBuffer::Type t) |
119 : type(t), |
134 : ref(1), |
|
135 type(t), |
120 guard(0), |
136 guard(0), |
121 usagePattern(QGLBuffer::StaticDraw), |
137 usagePattern(QGLBuffer::StaticDraw), |
122 actualUsagePattern(QGLBuffer::StaticDraw) |
138 actualUsagePattern(QGLBuffer::StaticDraw) |
123 { |
139 { |
124 } |
140 } |
125 |
141 |
|
142 QAtomicInt ref; |
126 QGLBuffer::Type type; |
143 QGLBuffer::Type type; |
127 QGLSharedResourceGuard guard; |
144 QGLSharedResourceGuard guard; |
128 QGLBuffer::UsagePattern usagePattern; |
145 QGLBuffer::UsagePattern usagePattern; |
129 QGLBuffer::UsagePattern actualUsagePattern; |
146 QGLBuffer::UsagePattern actualUsagePattern; |
130 }; |
147 }; |
131 |
148 |
132 /*! |
149 /*! |
133 Constructs a new buffer object of \a type. |
150 Constructs a new buffer object of type QGLBuffer::VertexBuffer. |
134 |
151 |
135 Note: this constructor just creates the QGLBuffer instance. The actual |
152 Note: this constructor just creates the QGLBuffer instance. The actual |
136 buffer object in the GL server is not created until create() is called. |
153 buffer object in the GL server is not created until create() is called. |
137 |
154 |
138 \sa create() |
155 \sa create() |
139 */ |
156 */ |
|
157 QGLBuffer::QGLBuffer() |
|
158 : d_ptr(new QGLBufferPrivate(QGLBuffer::VertexBuffer)) |
|
159 { |
|
160 } |
|
161 |
|
162 /*! |
|
163 Constructs a new buffer object of \a type. |
|
164 |
|
165 Note: this constructor just creates the QGLBuffer instance. The actual |
|
166 buffer object in the GL server is not created until create() is called. |
|
167 |
|
168 \sa create() |
|
169 */ |
140 QGLBuffer::QGLBuffer(QGLBuffer::Type type) |
170 QGLBuffer::QGLBuffer(QGLBuffer::Type type) |
141 : d_ptr(new QGLBufferPrivate(type)) |
171 : d_ptr(new QGLBufferPrivate(type)) |
142 { |
172 { |
143 } |
173 } |
144 |
174 |
|
175 /*! |
|
176 Constructs a shallow copy of \a other. |
|
177 |
|
178 Note: QGLBuffer does not implement copy-on-write semantics, |
|
179 so \a other will be affected whenever the copy is modified. |
|
180 */ |
|
181 QGLBuffer::QGLBuffer(const QGLBuffer &other) |
|
182 : d_ptr(other.d_ptr) |
|
183 { |
|
184 d_ptr->ref.ref(); |
|
185 } |
|
186 |
145 #define ctx d->guard.context() |
187 #define ctx d->guard.context() |
146 |
188 |
147 /*! |
189 /*! |
148 Destroys this buffer object, including the storage being |
190 Destroys this buffer object, including the storage being |
149 used in the GL server. |
191 used in the GL server. |
150 */ |
192 */ |
151 QGLBuffer::~QGLBuffer() |
193 QGLBuffer::~QGLBuffer() |
152 { |
194 { |
153 Q_D(QGLBuffer); |
195 if (!d_ptr->ref.deref()) { |
154 GLuint bufferId = d->guard.id(); |
196 destroy(); |
155 if (bufferId) { |
197 delete d_ptr; |
156 // Switch to the original creating context to destroy it. |
|
157 QGLShareContextScope scope(d->guard.context()); |
|
158 glDeleteBuffers(1, &bufferId); |
|
159 } |
198 } |
|
199 } |
|
200 |
|
201 /*! |
|
202 Assigns a shallow copy of \a other to this object. |
|
203 |
|
204 Note: QGLBuffer does not implement copy-on-write semantics, |
|
205 so \a other will be affected whenever the copy is modified. |
|
206 */ |
|
207 QGLBuffer &QGLBuffer::operator=(const QGLBuffer &other) |
|
208 { |
|
209 if (d_ptr != other.d_ptr) { |
|
210 other.d_ptr->ref.ref(); |
|
211 if (!d_ptr->ref.deref()) |
|
212 destroy(); |
|
213 d_ptr = other.d_ptr; |
|
214 } |
|
215 return *this; |
160 } |
216 } |
161 |
217 |
162 /*! |
218 /*! |
163 Returns the type of buffer represented by this object. |
219 Returns the type of buffer represented by this object. |
164 */ |
220 */ |
213 that context (or any other context that is shared with it). |
269 that context (or any other context that is shared with it). |
214 |
270 |
215 This function will return false if the GL implementation |
271 This function will return false if the GL implementation |
216 does not support buffers, or there is no current QGLContext. |
272 does not support buffers, or there is no current QGLContext. |
217 |
273 |
218 \sa isCreated(), allocate(), write() |
274 \sa isCreated(), allocate(), write(), destroy() |
219 */ |
275 */ |
220 bool QGLBuffer::create() |
276 bool QGLBuffer::create() |
221 { |
277 { |
222 Q_D(QGLBuffer); |
278 Q_D(QGLBuffer); |
223 if (d->guard.id()) |
279 if (d->guard.id()) |
240 #define ctx d->guard.context() |
296 #define ctx d->guard.context() |
241 |
297 |
242 /*! |
298 /*! |
243 Returns true if this buffer has been created; false otherwise. |
299 Returns true if this buffer has been created; false otherwise. |
244 |
300 |
245 \sa create() |
301 \sa create(), destroy() |
246 */ |
302 */ |
247 bool QGLBuffer::isCreated() const |
303 bool QGLBuffer::isCreated() const |
248 { |
304 { |
249 Q_D(const QGLBuffer); |
305 Q_D(const QGLBuffer); |
250 return d->guard.id() != 0; |
306 return d->guard.id() != 0; |
|
307 } |
|
308 |
|
309 /*! |
|
310 Destroys this buffer object, including the storage being |
|
311 used in the GL server. All references to the buffer will |
|
312 become invalid. |
|
313 */ |
|
314 void QGLBuffer::destroy() |
|
315 { |
|
316 Q_D(QGLBuffer); |
|
317 GLuint bufferId = d->guard.id(); |
|
318 if (bufferId) { |
|
319 // Switch to the original creating context to destroy it. |
|
320 QGLShareContextScope scope(d->guard.context()); |
|
321 glDeleteBuffers(1, &bufferId); |
|
322 } |
|
323 d->guard.setId(0); |
|
324 d->guard.setContext(0); |
251 } |
325 } |
252 |
326 |
253 /*! |
327 /*! |
254 Reads the \a count bytes in this buffer starting at \a offset |
328 Reads the \a count bytes in this buffer starting at \a offset |
255 into \a data. Returns true on success; false if reading from |
329 into \a data. Returns true on success; false if reading from |