Line | Source Code | Coverage |
---|
1 | | - |
2 | | - |
3 | | - |
4 | | - |
5 | void QOpenGLFramebufferObjectFormat::detach() | - |
6 | { | - |
7 | if (d->ref.load() != 1) { never evaluated: d->ref.load() != 1 | 0 |
8 | QOpenGLFramebufferObjectFormatPrivate *newd | - |
9 | = new QOpenGLFramebufferObjectFormatPrivate(d); | - |
10 | if (!d->ref.deref()) never evaluated: !d->ref.deref() | 0 |
11 | delete d; never executed: delete d; | 0 |
12 | d = newd; | - |
13 | } | 0 |
14 | } | 0 |
15 | QOpenGLFramebufferObjectFormat::QOpenGLFramebufferObjectFormat() | - |
16 | { | - |
17 | d = new QOpenGLFramebufferObjectFormatPrivate; | - |
18 | } | 0 |
19 | | - |
20 | | - |
21 | | - |
22 | | - |
23 | | - |
24 | QOpenGLFramebufferObjectFormat::QOpenGLFramebufferObjectFormat(const QOpenGLFramebufferObjectFormat &other) | - |
25 | { | - |
26 | d = other.d; | - |
27 | d->ref.ref(); | - |
28 | } | 0 |
29 | | - |
30 | | - |
31 | | - |
32 | | - |
33 | | - |
34 | QOpenGLFramebufferObjectFormat &QOpenGLFramebufferObjectFormat::operator=(const QOpenGLFramebufferObjectFormat &other) | - |
35 | { | - |
36 | if (d != other.d) { never evaluated: d != other.d | 0 |
37 | other.d->ref.ref(); | - |
38 | if (!d->ref.deref()) never evaluated: !d->ref.deref() | 0 |
39 | delete d; never executed: delete d; | 0 |
40 | d = other.d; | - |
41 | } | 0 |
42 | return *this; never executed: return *this; | 0 |
43 | } | - |
44 | | - |
45 | | - |
46 | | - |
47 | | - |
48 | QOpenGLFramebufferObjectFormat::~QOpenGLFramebufferObjectFormat() | - |
49 | { | - |
50 | if (!d->ref.deref()) never evaluated: !d->ref.deref() | 0 |
51 | delete d; never executed: delete d; | 0 |
52 | } | 0 |
53 | void QOpenGLFramebufferObjectFormat::setSamples(int samples) | - |
54 | { | - |
55 | detach(); | - |
56 | d->samples = samples; | - |
57 | } | 0 |
58 | int QOpenGLFramebufferObjectFormat::samples() const | - |
59 | { | - |
60 | return d->samples; never executed: return d->samples; | 0 |
61 | } | - |
62 | void QOpenGLFramebufferObjectFormat::setMipmap(bool enabled) | - |
63 | { | - |
64 | detach(); | - |
65 | d->mipmap = enabled; | - |
66 | } | 0 |
67 | | - |
68 | | - |
69 | | - |
70 | | - |
71 | | - |
72 | | - |
73 | bool QOpenGLFramebufferObjectFormat::mipmap() const | - |
74 | { | - |
75 | return d->mipmap; never executed: return d->mipmap; | 0 |
76 | } | - |
77 | | - |
78 | | - |
79 | | - |
80 | | - |
81 | | - |
82 | | - |
83 | void QOpenGLFramebufferObjectFormat::setAttachment(QOpenGLFramebufferObject::Attachment attachment) | - |
84 | { | - |
85 | detach(); | - |
86 | d->attachment = attachment; | - |
87 | } | 0 |
88 | | - |
89 | | - |
90 | | - |
91 | | - |
92 | | - |
93 | | - |
94 | | - |
95 | QOpenGLFramebufferObject::Attachment QOpenGLFramebufferObjectFormat::attachment() const | - |
96 | { | - |
97 | return d->attachment; never executed: return d->attachment; | 0 |
98 | } | - |
99 | | - |
100 | | - |
101 | | - |
102 | | - |
103 | | - |
104 | | - |
105 | | - |
106 | void QOpenGLFramebufferObjectFormat::setTextureTarget(GLenum target) | - |
107 | { | - |
108 | detach(); | - |
109 | d->target = target; | - |
110 | } | 0 |
111 | GLenum QOpenGLFramebufferObjectFormat::textureTarget() const | - |
112 | { | - |
113 | return d->target; never executed: return d->target; | 0 |
114 | } | - |
115 | void QOpenGLFramebufferObjectFormat::setInternalTextureFormat(GLenum internalTextureFormat) | - |
116 | { | - |
117 | detach(); | - |
118 | d->internal_format = internalTextureFormat; | - |
119 | } | 0 |
120 | GLenum QOpenGLFramebufferObjectFormat::internalTextureFormat() const | - |
121 | { | - |
122 | return d->internal_format; never executed: return d->internal_format; | 0 |
123 | } | - |
124 | | - |
125 | | - |
126 | | - |
127 | | - |
128 | | - |
129 | bool QOpenGLFramebufferObjectFormat::operator==(const QOpenGLFramebufferObjectFormat& other) const | - |
130 | { | - |
131 | if (d == other.d) never evaluated: d == other.d | 0 |
132 | return true; never executed: return true; | 0 |
133 | else | - |
134 | return d->equals(other.d); never executed: return d->equals(other.d); | 0 |
135 | } | - |
136 | | - |
137 | | - |
138 | | - |
139 | | - |
140 | | - |
141 | bool QOpenGLFramebufferObjectFormat::operator!=(const QOpenGLFramebufferObjectFormat& other) const | - |
142 | { | - |
143 | return !(*this == other); never executed: return !(*this == other); | 0 |
144 | } | - |
145 | | - |
146 | bool QOpenGLFramebufferObjectPrivate::checkFramebufferStatus(QOpenGLContext *ctx) const | - |
147 | { | - |
148 | if (!ctx) | 0 |
149 | return false; never executed: return false; | 0 |
150 | GLenum status = ctx->functions()->glCheckFramebufferStatus(0x8D40); | - |
151 | switch(status) { | - |
152 | case 0x0: | - |
153 | case 0x8CD5: | - |
154 | return true; never executed: return true; | 0 |
155 | case 0x8CDD: | - |
156 | QMessageLogger("opengl/qopenglframebufferobject.cpp", 353, __PRETTY_FUNCTION__).debug("QOpenGLFramebufferObject: Unsupported framebuffer format."); | - |
157 | break; | 0 |
158 | case 0x8CD6: | - |
159 | QMessageLogger("opengl/qopenglframebufferobject.cpp", 356, __PRETTY_FUNCTION__).debug("QOpenGLFramebufferObject: Framebuffer incomplete attachment."); | - |
160 | break; | 0 |
161 | case 0x8CD7: | - |
162 | QMessageLogger("opengl/qopenglframebufferobject.cpp", 359, __PRETTY_FUNCTION__).debug("QOpenGLFramebufferObject: Framebuffer incomplete, missing attachment."); | - |
163 | break; | 0 |
164 | case 0x8CDB: | - |
165 | QMessageLogger("opengl/qopenglframebufferobject.cpp", 378, __PRETTY_FUNCTION__).debug("QOpenGLFramebufferObject: Framebuffer incomplete, missing draw buffer."); | - |
166 | break; | 0 |
167 | | - |
168 | | - |
169 | case 0x8CDC: | - |
170 | QMessageLogger("opengl/qopenglframebufferobject.cpp", 383, __PRETTY_FUNCTION__).debug("QOpenGLFramebufferObject: Framebuffer incomplete, missing read buffer."); | - |
171 | break; | 0 |
172 | | - |
173 | | - |
174 | case 0x8D56: | - |
175 | QMessageLogger("opengl/qopenglframebufferobject.cpp", 388, __PRETTY_FUNCTION__).debug("QOpenGLFramebufferObject: Framebuffer incomplete, attachments must have same number of samples per pixel."); | - |
176 | break; | 0 |
177 | | - |
178 | default: | - |
179 | QMessageLogger("opengl/qopenglframebufferobject.cpp", 392, __PRETTY_FUNCTION__).debug() <<"QOpenGLFramebufferObject: An undefined error has occurred: "<< status; | - |
180 | break; | 0 |
181 | } | - |
182 | return false; never executed: return false; | 0 |
183 | } | - |
184 | | - |
185 | namespace | - |
186 | { | - |
187 | void freeFramebufferFunc(QOpenGLFunctions *funcs, GLuint id) | - |
188 | { | - |
189 | funcs->glDeleteFramebuffers(1, &id); | - |
190 | } | 0 |
191 | | - |
192 | void freeRenderbufferFunc(QOpenGLFunctions *funcs, GLuint id) | - |
193 | { | - |
194 | funcs->glDeleteRenderbuffers(1, &id); | - |
195 | } | 0 |
196 | | - |
197 | void freeTextureFunc(QOpenGLFunctions *, GLuint id) | - |
198 | { | - |
199 | glDeleteTextures(1, &id); | - |
200 | } | 0 |
201 | } | - |
202 | | - |
203 | void QOpenGLFramebufferObjectPrivate::init(QOpenGLFramebufferObject *, const QSize &sz, | - |
204 | QOpenGLFramebufferObject::Attachment attachment, | - |
205 | GLenum texture_target, GLenum internal_format, | - |
206 | GLint samples, bool mipmap) | - |
207 | { | - |
208 | QOpenGLContext *ctx = QOpenGLContext::currentContext(); | - |
209 | | - |
210 | funcs.initializeOpenGLFunctions(); | - |
211 | | - |
212 | if (!funcs.hasOpenGLFeature(QOpenGLFunctions::Framebuffers)) never evaluated: !funcs.hasOpenGLFeature(QOpenGLFunctions::Framebuffers) | 0 |
213 | return; | 0 |
214 | | - |
215 | size = sz; | - |
216 | target = texture_target; | - |
217 | | - |
218 | | - |
219 | {}; | - |
220 | GLuint fbo = 0; | - |
221 | | - |
222 | funcs.glGenFramebuffers(1, &fbo); | - |
223 | funcs.glBindFramebuffer(0x8D40, fbo); | - |
224 | | - |
225 | GLuint texture = 0; | - |
226 | GLuint color_buffer = 0; | - |
227 | | - |
228 | {}; | - |
229 | | - |
230 | if (samples == 0) { never evaluated: samples == 0 | 0 |
231 | glGenTextures(1, &texture); | - |
232 | glBindTexture(target, texture); | - |
233 | | - |
234 | glTexParameteri(target, 0x2801, 0x2600); | - |
235 | glTexParameteri(target, 0x2800, 0x2600); | - |
236 | glTexParameteri(target, 0x2802, 0x812F); | - |
237 | glTexParameteri(target, 0x2803, 0x812F); | - |
238 | | - |
239 | glTexImage2D(target, 0, internal_format, size.width(), size.height(), 0, | - |
240 | 0x1908, 0x1401, __null); | - |
241 | if (mipmap) { | 0 |
242 | int width = size.width(); | - |
243 | int height = size.height(); | - |
244 | int level = 0; | - |
245 | while (width > 1 || height > 1) { never evaluated: width > 1 never evaluated: height > 1 | 0 |
246 | width = qMax(1, width >> 1); | - |
247 | height = qMax(1, height >> 1); | - |
248 | ++level; | - |
249 | glTexImage2D(target, level, internal_format, width, height, 0, | - |
250 | 0x1908, 0x1401, __null); | - |
251 | } | 0 |
252 | } | 0 |
253 | funcs.glFramebufferTexture2D(0x8D40, 0x8CE0, | - |
254 | target, texture, 0); | - |
255 | | - |
256 | {}; | - |
257 | valid = checkFramebufferStatus(ctx); | - |
258 | glBindTexture(target, 0); | - |
259 | | - |
260 | color_buffer = 0; | - |
261 | } else { | 0 |
262 | mipmap = false; | - |
263 | GLint maxSamples; | - |
264 | glGetIntegerv(0x8D57, &maxSamples); | - |
265 | | - |
266 | samples = qBound(0, int(samples), int(maxSamples)); | - |
267 | | - |
268 | funcs.glGenRenderbuffers(1, &color_buffer); | - |
269 | funcs.glBindRenderbuffer(0x8D41, color_buffer); | - |
270 | if (funcs.hasOpenGLExtension(QOpenGLExtensions::FramebufferMultisample) && samples > 0) { never evaluated: funcs.hasOpenGLExtension(QOpenGLExtensions::FramebufferMultisample) never evaluated: samples > 0 | 0 |
271 | funcs.glRenderbufferStorageMultisample(0x8D41, samples, | - |
272 | internal_format, size.width(), size.height()); | - |
273 | } else { | 0 |
274 | samples = 0; | - |
275 | funcs.glRenderbufferStorage(0x8D41, internal_format, | - |
276 | size.width(), size.height()); | - |
277 | } | 0 |
278 | | - |
279 | funcs.glFramebufferRenderbuffer(0x8D40, 0x8CE0, | - |
280 | 0x8D41, color_buffer); | - |
281 | | - |
282 | {}; | - |
283 | valid = checkFramebufferStatus(ctx); | - |
284 | | - |
285 | if (valid) | 0 |
286 | funcs.glGetRenderbufferParameteriv(0x8D41, 0x8CAB, &samples); never executed: funcs.glGetRenderbufferParameteriv(0x8D41, 0x8CAB, &samples); | 0 |
287 | } | 0 |
288 | | - |
289 | format.setTextureTarget(target); | - |
290 | format.setSamples(int(samples)); | - |
291 | format.setInternalTextureFormat(internal_format); | - |
292 | format.setMipmap(mipmap); | - |
293 | | - |
294 | initAttachments(ctx, attachment); | - |
295 | | - |
296 | funcs.glBindFramebuffer(0x8D40, ctx->d_func()->current_fbo); | - |
297 | if (valid) { | 0 |
298 | fbo_guard = new QOpenGLSharedResourceGuard(ctx, fbo, freeFramebufferFunc); | - |
299 | if (color_buffer) never evaluated: color_buffer | 0 |
300 | color_buffer_guard = new QOpenGLSharedResourceGuard(ctx, color_buffer, freeRenderbufferFunc); never executed: color_buffer_guard = new QOpenGLSharedResourceGuard(ctx, color_buffer, freeRenderbufferFunc); | 0 |
301 | else | - |
302 | texture_guard = new QOpenGLSharedResourceGuard(ctx, texture, freeTextureFunc); never executed: texture_guard = new QOpenGLSharedResourceGuard(ctx, texture, freeTextureFunc); | 0 |
303 | } else { | - |
304 | if (color_buffer) never evaluated: color_buffer | 0 |
305 | funcs.glDeleteRenderbuffers(1, &color_buffer); never executed: funcs.glDeleteRenderbuffers(1, &color_buffer); | 0 |
306 | else | - |
307 | glDeleteTextures(1, &texture); never executed: glDeleteTextures(1, &texture); | 0 |
308 | funcs.glDeleteFramebuffers(1, &fbo); | - |
309 | } | 0 |
310 | {}; | - |
311 | } | - |
312 | | - |
313 | void QOpenGLFramebufferObjectPrivate::initAttachments(QOpenGLContext *ctx, QOpenGLFramebufferObject::Attachment attachment) | - |
314 | { | - |
315 | int samples = format.samples(); | - |
316 | | - |
317 | | - |
318 | if (depth_buffer_guard) { never evaluated: depth_buffer_guard | 0 |
319 | funcs.glFramebufferRenderbuffer(0x8D40, 0x8D00, 0x8D41, 0); | - |
320 | depth_buffer_guard->free(); | - |
321 | } | 0 |
322 | if (stencil_buffer_guard) { never evaluated: stencil_buffer_guard | 0 |
323 | funcs.glFramebufferRenderbuffer(0x8D40, 0x8D20, 0x8D41, 0); | - |
324 | if (stencil_buffer_guard != depth_buffer_guard) never evaluated: stencil_buffer_guard != depth_buffer_guard | 0 |
325 | stencil_buffer_guard->free(); never executed: stencil_buffer_guard->free(); | 0 |
326 | } | 0 |
327 | | - |
328 | depth_buffer_guard = 0; | - |
329 | stencil_buffer_guard = 0; | - |
330 | | - |
331 | GLuint depth_buffer = 0; | - |
332 | GLuint stencil_buffer = 0; | - |
333 | | - |
334 | | - |
335 | | - |
336 | | - |
337 | | - |
338 | if (attachment == QOpenGLFramebufferObject::CombinedDepthStencil never evaluated: attachment == QOpenGLFramebufferObject::CombinedDepthStencil | 0 |
339 | && funcs.hasOpenGLExtension(QOpenGLExtensions::PackedDepthStencil)) never evaluated: funcs.hasOpenGLExtension(QOpenGLExtensions::PackedDepthStencil) | 0 |
340 | { | - |
341 | | - |
342 | funcs.glGenRenderbuffers(1, &depth_buffer); | - |
343 | funcs.glBindRenderbuffer(0x8D41, depth_buffer); | - |
344 | qt_noop(); | - |
345 | if (samples != 0 && funcs.hasOpenGLExtension(QOpenGLExtensions::FramebufferMultisample)) never evaluated: samples != 0 never evaluated: funcs.hasOpenGLExtension(QOpenGLExtensions::FramebufferMultisample) | 0 |
346 | funcs.glRenderbufferStorageMultisample(0x8D41, samples, | 0 |
347 | 0x88F0, size.width(), size.height()); never executed: funcs.glRenderbufferStorageMultisample(0x8D41, samples, 0x88F0, size.width(), size.height()); | 0 |
348 | else | - |
349 | funcs.glRenderbufferStorage(0x8D41, | 0 |
350 | 0x88F0, size.width(), size.height()); never executed: funcs.glRenderbufferStorage(0x8D41, 0x88F0, size.width(), size.height()); | 0 |
351 | | - |
352 | stencil_buffer = depth_buffer; | - |
353 | funcs.glFramebufferRenderbuffer(0x8D40, 0x8D00, | - |
354 | 0x8D41, depth_buffer); | - |
355 | funcs.glFramebufferRenderbuffer(0x8D40, 0x8D20, | - |
356 | 0x8D41, stencil_buffer); | - |
357 | | - |
358 | valid = checkFramebufferStatus(ctx); | - |
359 | if (!valid) { | 0 |
360 | funcs.glDeleteRenderbuffers(1, &depth_buffer); | - |
361 | stencil_buffer = depth_buffer = 0; | - |
362 | } | 0 |
363 | } | 0 |
364 | | - |
365 | if (depth_buffer == 0 && (attachment == QOpenGLFramebufferObject::CombinedDepthStencil never evaluated: depth_buffer == 0 never evaluated: attachment == QOpenGLFramebufferObject::CombinedDepthStencil | 0 |
366 | || (attachment == QOpenGLFramebufferObject::Depth))) never evaluated: (attachment == QOpenGLFramebufferObject::Depth) | 0 |
367 | { | - |
368 | funcs.glGenRenderbuffers(1, &depth_buffer); | - |
369 | funcs.glBindRenderbuffer(0x8D41, depth_buffer); | - |
370 | qt_noop(); | - |
371 | if (samples != 0 && funcs.hasOpenGLExtension(QOpenGLExtensions::FramebufferMultisample)) { never evaluated: samples != 0 never evaluated: funcs.hasOpenGLExtension(QOpenGLExtensions::FramebufferMultisample) | 0 |
372 | funcs.glRenderbufferStorageMultisample(0x8D41, samples, | - |
373 | 0x1902, size.width(), size.height()); | - |
374 | | - |
375 | } else { | 0 |
376 | funcs.glRenderbufferStorage(0x8D41, 0x1902, size.width(), size.height()); | - |
377 | | - |
378 | } | 0 |
379 | funcs.glFramebufferRenderbuffer(0x8D40, 0x8D00, | - |
380 | 0x8D41, depth_buffer); | - |
381 | valid = checkFramebufferStatus(ctx); | - |
382 | if (!valid) { | 0 |
383 | funcs.glDeleteRenderbuffers(1, &depth_buffer); | - |
384 | depth_buffer = 0; | - |
385 | } | 0 |
386 | } | 0 |
387 | | - |
388 | if (stencil_buffer == 0 && (attachment == QOpenGLFramebufferObject::CombinedDepthStencil)) { never evaluated: stencil_buffer == 0 never evaluated: (attachment == QOpenGLFramebufferObject::CombinedDepthStencil) | 0 |
389 | funcs.glGenRenderbuffers(1, &stencil_buffer); | - |
390 | funcs.glBindRenderbuffer(0x8D41, stencil_buffer); | - |
391 | qt_noop(); | - |
392 | if (samples != 0 && funcs.hasOpenGLExtension(QOpenGLExtensions::FramebufferMultisample)) { never evaluated: samples != 0 never evaluated: funcs.hasOpenGLExtension(QOpenGLExtensions::FramebufferMultisample) | 0 |
393 | | - |
394 | | - |
395 | | - |
396 | | - |
397 | funcs.glRenderbufferStorageMultisample(0x8D41, samples, | - |
398 | 0x1901, size.width(), size.height()); | - |
399 | | - |
400 | } else { | 0 |
401 | | - |
402 | | - |
403 | | - |
404 | | - |
405 | funcs.glRenderbufferStorage(0x8D41, 0x1901, | - |
406 | size.width(), size.height()); | - |
407 | | - |
408 | } | 0 |
409 | funcs.glFramebufferRenderbuffer(0x8D40, 0x8D20, | - |
410 | 0x8D41, stencil_buffer); | - |
411 | valid = checkFramebufferStatus(ctx); | - |
412 | if (!valid) { | 0 |
413 | funcs.glDeleteRenderbuffers(1, &stencil_buffer); | - |
414 | stencil_buffer = 0; | - |
415 | } | 0 |
416 | } | 0 |
417 | | - |
418 | | - |
419 | valid = checkFramebufferStatus(ctx); | - |
420 | | - |
421 | if (depth_buffer && stencil_buffer) { never evaluated: depth_buffer never evaluated: stencil_buffer | 0 |
422 | fbo_attachment = QOpenGLFramebufferObject::CombinedDepthStencil; | - |
423 | } else if (depth_buffer) { never evaluated: depth_buffer | 0 |
424 | fbo_attachment = QOpenGLFramebufferObject::Depth; | - |
425 | } else { | 0 |
426 | fbo_attachment = QOpenGLFramebufferObject::NoAttachment; | - |
427 | } | 0 |
428 | | - |
429 | if (valid) { | 0 |
430 | if (depth_buffer) never evaluated: depth_buffer | 0 |
431 | depth_buffer_guard = new QOpenGLSharedResourceGuard(ctx, depth_buffer, freeRenderbufferFunc); never executed: depth_buffer_guard = new QOpenGLSharedResourceGuard(ctx, depth_buffer, freeRenderbufferFunc); | 0 |
432 | if (stencil_buffer) { never evaluated: stencil_buffer | 0 |
433 | if (stencil_buffer == depth_buffer) never evaluated: stencil_buffer == depth_buffer | 0 |
434 | stencil_buffer_guard = depth_buffer_guard; never executed: stencil_buffer_guard = depth_buffer_guard; | 0 |
435 | else | - |
436 | stencil_buffer_guard = new QOpenGLSharedResourceGuard(ctx, stencil_buffer, freeRenderbufferFunc); never executed: stencil_buffer_guard = new QOpenGLSharedResourceGuard(ctx, stencil_buffer, freeRenderbufferFunc); | 0 |
437 | } | - |
438 | } else { | 0 |
439 | if (depth_buffer) never evaluated: depth_buffer | 0 |
440 | funcs.glDeleteRenderbuffers(1, &depth_buffer); never executed: funcs.glDeleteRenderbuffers(1, &depth_buffer); | 0 |
441 | if (stencil_buffer && depth_buffer != stencil_buffer) never evaluated: stencil_buffer never evaluated: depth_buffer != stencil_buffer | 0 |
442 | funcs.glDeleteRenderbuffers(1, &stencil_buffer); never executed: funcs.glDeleteRenderbuffers(1, &stencil_buffer); | 0 |
443 | } | 0 |
444 | {}; | - |
445 | | - |
446 | format.setAttachment(fbo_attachment); | - |
447 | } | 0 |
448 | QOpenGLFramebufferObject::QOpenGLFramebufferObject(const QSize &size, GLenum target) | - |
449 | : d_ptr(new QOpenGLFramebufferObjectPrivate) | - |
450 | { | - |
451 | QOpenGLFramebufferObjectPrivate * const d = d_func(); | - |
452 | d->init(this, size, NoAttachment, target, 0x8058); | - |
453 | } | 0 |
454 | QOpenGLFramebufferObject::QOpenGLFramebufferObject(int width, int height, GLenum target) | - |
455 | : d_ptr(new QOpenGLFramebufferObjectPrivate) | - |
456 | { | - |
457 | QOpenGLFramebufferObjectPrivate * const d = d_func(); | - |
458 | d->init(this, QSize(width, height), NoAttachment, target, 0x8058); | - |
459 | } | 0 |
460 | | - |
461 | | - |
462 | | - |
463 | | - |
464 | | - |
465 | | - |
466 | | - |
467 | QOpenGLFramebufferObject::QOpenGLFramebufferObject(const QSize &size, const QOpenGLFramebufferObjectFormat &format) | - |
468 | : d_ptr(new QOpenGLFramebufferObjectPrivate) | - |
469 | { | - |
470 | QOpenGLFramebufferObjectPrivate * const d = d_func(); | - |
471 | d->init(this, size, format.attachment(), format.textureTarget(), format.internalTextureFormat(), | - |
472 | format.samples(), format.mipmap()); | - |
473 | } | 0 |
474 | | - |
475 | | - |
476 | | - |
477 | | - |
478 | | - |
479 | | - |
480 | | - |
481 | QOpenGLFramebufferObject::QOpenGLFramebufferObject(int width, int height, const QOpenGLFramebufferObjectFormat &format) | - |
482 | : d_ptr(new QOpenGLFramebufferObjectPrivate) | - |
483 | { | - |
484 | QOpenGLFramebufferObjectPrivate * const d = d_func(); | - |
485 | d->init(this, QSize(width, height), format.attachment(), format.textureTarget(), | - |
486 | format.internalTextureFormat(), format.samples(), format.mipmap()); | - |
487 | } | 0 |
488 | QOpenGLFramebufferObject::QOpenGLFramebufferObject(int width, int height, Attachment attachment, | - |
489 | GLenum target, GLenum internal_format) | - |
490 | : d_ptr(new QOpenGLFramebufferObjectPrivate) | - |
491 | { | - |
492 | QOpenGLFramebufferObjectPrivate * const d = d_func(); | - |
493 | d->init(this, QSize(width, height), attachment, target, internal_format); | - |
494 | } | 0 |
495 | QOpenGLFramebufferObject::QOpenGLFramebufferObject(const QSize &size, Attachment attachment, | - |
496 | GLenum target, GLenum internal_format) | - |
497 | : d_ptr(new QOpenGLFramebufferObjectPrivate) | - |
498 | { | - |
499 | QOpenGLFramebufferObjectPrivate * const d = d_func(); | - |
500 | d->init(this, size, attachment, target, internal_format); | - |
501 | } | 0 |
502 | | - |
503 | | - |
504 | | - |
505 | | - |
506 | | - |
507 | | - |
508 | QOpenGLFramebufferObject::~QOpenGLFramebufferObject() | - |
509 | { | - |
510 | QOpenGLFramebufferObjectPrivate * const d = d_func(); | - |
511 | | - |
512 | if (d->texture_guard) never evaluated: d->texture_guard | 0 |
513 | d->texture_guard->free(); never executed: d->texture_guard->free(); | 0 |
514 | if (d->color_buffer_guard) never evaluated: d->color_buffer_guard | 0 |
515 | d->color_buffer_guard->free(); never executed: d->color_buffer_guard->free(); | 0 |
516 | if (d->depth_buffer_guard) never evaluated: d->depth_buffer_guard | 0 |
517 | d->depth_buffer_guard->free(); never executed: d->depth_buffer_guard->free(); | 0 |
518 | if (d->stencil_buffer_guard && d->stencil_buffer_guard != d->depth_buffer_guard) never evaluated: d->stencil_buffer_guard never evaluated: d->stencil_buffer_guard != d->depth_buffer_guard | 0 |
519 | d->stencil_buffer_guard->free(); never executed: d->stencil_buffer_guard->free(); | 0 |
520 | if (d->fbo_guard) never evaluated: d->fbo_guard | 0 |
521 | d->fbo_guard->free(); never executed: d->fbo_guard->free(); | 0 |
522 | } | 0 |
523 | bool QOpenGLFramebufferObject::isValid() const | - |
524 | { | - |
525 | const QOpenGLFramebufferObjectPrivate * const d = d_func(); | - |
526 | return d->valid && d->fbo_guard && d->fbo_guard->id(); never executed: return d->valid && d->fbo_guard && d->fbo_guard->id(); | 0 |
527 | } | - |
528 | bool QOpenGLFramebufferObject::bind() | - |
529 | { | - |
530 | if (!isValid()) never evaluated: !isValid() | 0 |
531 | return false; never executed: return false; | 0 |
532 | QOpenGLFramebufferObjectPrivate * const d = d_func(); | - |
533 | QOpenGLContext *current = QOpenGLContext::currentContext(); | - |
534 | if (!current) never evaluated: !current | 0 |
535 | return false; never executed: return false; | 0 |
536 | | - |
537 | | - |
538 | | - |
539 | | - |
540 | d->funcs.glBindFramebuffer(0x8D40, d->fbo()); | - |
541 | d->valid = d->checkFramebufferStatus(current); | - |
542 | if (d->valid && current) never evaluated: d->valid | 0 |
543 | current->d_func()->current_fbo = d->fbo(); never executed: current->d_func()->current_fbo = d->fbo(); | 0 |
544 | return d->valid; never executed: return d->valid; | 0 |
545 | } | - |
546 | bool QOpenGLFramebufferObject::release() | - |
547 | { | - |
548 | if (!isValid()) never evaluated: !isValid() | 0 |
549 | return false; never executed: return false; | 0 |
550 | | - |
551 | QOpenGLContext *current = QOpenGLContext::currentContext(); | - |
552 | if (!current) never evaluated: !current | 0 |
553 | return false; never executed: return false; | 0 |
554 | | - |
555 | QOpenGLFramebufferObjectPrivate * const d = d_func(); | - |
556 | | - |
557 | | - |
558 | | - |
559 | | - |
560 | | - |
561 | if (current) { | 0 |
562 | current->d_func()->current_fbo = current->defaultFramebufferObject(); | - |
563 | d->funcs.glBindFramebuffer(0x8D40, current->d_func()->current_fbo); | - |
564 | } | 0 |
565 | | - |
566 | return true; never executed: return true; | 0 |
567 | } | - |
568 | GLuint QOpenGLFramebufferObject::texture() const | - |
569 | { | - |
570 | const QOpenGLFramebufferObjectPrivate * const d = d_func(); | - |
571 | return d->texture_guard ? d->texture_guard->id() : 0; never executed: return d->texture_guard ? d->texture_guard->id() : 0; | 0 |
572 | } | - |
573 | | - |
574 | | - |
575 | | - |
576 | | - |
577 | | - |
578 | | - |
579 | | - |
580 | QSize QOpenGLFramebufferObject::size() const | - |
581 | { | - |
582 | const QOpenGLFramebufferObjectPrivate * const d = d_func(); | - |
583 | return d->size; never executed: return d->size; | 0 |
584 | } | - |
585 | QOpenGLFramebufferObjectFormat QOpenGLFramebufferObject::format() const | - |
586 | { | - |
587 | const QOpenGLFramebufferObjectPrivate * const d = d_func(); | - |
588 | return d->format; never executed: return d->format; | 0 |
589 | } | - |
590 | | - |
591 | __attribute__((visibility("default"))) QImage qt_gl_read_framebuffer(const QSize &size, bool alpha_format, bool include_alpha) | - |
592 | { | - |
593 | QImage img(size, (alpha_format && include_alpha) ? QImage::Format_ARGB32_Premultiplied | - |
594 | : QImage::Format_RGB32); | - |
595 | int w = size.width(); | - |
596 | int h = size.height(); | - |
597 | | - |
598 | | - |
599 | | - |
600 | | - |
601 | GLint fmt = 0x80E1; | - |
602 | | - |
603 | while (glGetError()); never evaluated: glGetError() | 0 |
604 | glReadPixels(0, 0, w, h, fmt, 0x1401, img.bits()); | - |
605 | if (glGetError()) { never evaluated: glGetError() | 0 |
606 | glReadPixels(0, 0, w, h, 0x1908, 0x1401, img.bits()); | - |
607 | img = img.rgbSwapped(); | - |
608 | } | 0 |
609 | return img.mirrored(); never executed: return img.mirrored(); | 0 |
610 | } | - |
611 | | - |
612 | | - |
613 | | - |
614 | | - |
615 | | - |
616 | | - |
617 | QImage QOpenGLFramebufferObject::toImage() const | - |
618 | { | - |
619 | const QOpenGLFramebufferObjectPrivate * const d = d_func(); | - |
620 | if (!d->valid) never evaluated: !d->valid | 0 |
621 | return QImage(); never executed: return QImage(); | 0 |
622 | | - |
623 | | - |
624 | if (format().samples() != 0) { never evaluated: format().samples() != 0 | 0 |
625 | QOpenGLFramebufferObject temp(size(), QOpenGLFramebufferObjectFormat()); | - |
626 | | - |
627 | QRect rect(QPoint(0, 0), size()); | - |
628 | blitFramebuffer(&temp, rect, const_cast<QOpenGLFramebufferObject *>(this), rect); | - |
629 | | - |
630 | return temp.toImage(); never executed: return temp.toImage(); | 0 |
631 | } | - |
632 | | - |
633 | bool wasBound = isBound(); | - |
634 | if (!wasBound) never evaluated: !wasBound | 0 |
635 | const_cast<QOpenGLFramebufferObject *>(this)->bind(); never executed: const_cast<QOpenGLFramebufferObject *>(this)->bind(); | 0 |
636 | QImage image = qt_gl_read_framebuffer(d->size, format().internalTextureFormat() != 0x1907, true); | - |
637 | if (!wasBound) never evaluated: !wasBound | 0 |
638 | const_cast<QOpenGLFramebufferObject *>(this)->release(); never executed: const_cast<QOpenGLFramebufferObject *>(this)->release(); | 0 |
639 | | - |
640 | return image; never executed: return image; | 0 |
641 | } | - |
642 | bool QOpenGLFramebufferObject::bindDefault() | - |
643 | { | - |
644 | QOpenGLContext *ctx = const_cast<QOpenGLContext *>(QOpenGLContext::currentContext()); | - |
645 | QOpenGLFunctions functions(ctx); | - |
646 | | - |
647 | if (ctx) { | 0 |
648 | ctx->d_func()->current_fbo = ctx->defaultFramebufferObject(); | - |
649 | functions.glBindFramebuffer(0x8D40, ctx->d_func()->current_fbo); | - |
650 | | - |
651 | | - |
652 | | - |
653 | | - |
654 | } | 0 |
655 | | - |
656 | return ctx != 0; never executed: return ctx != 0; | 0 |
657 | } | - |
658 | | - |
659 | | - |
660 | | - |
661 | | - |
662 | | - |
663 | | - |
664 | | - |
665 | bool QOpenGLFramebufferObject::hasOpenGLFramebufferObjects() | - |
666 | { | - |
667 | return QOpenGLFunctions(QOpenGLContext::currentContext()).hasOpenGLFeature(QOpenGLFunctions::Framebuffers); never executed: return QOpenGLFunctions(QOpenGLContext::currentContext()).hasOpenGLFeature(QOpenGLFunctions::Framebuffers); | 0 |
668 | } | - |
669 | GLuint QOpenGLFramebufferObject::handle() const | - |
670 | { | - |
671 | const QOpenGLFramebufferObjectPrivate * const d = d_func(); | - |
672 | return d->fbo(); never executed: return d->fbo(); | 0 |
673 | } | - |
674 | | - |
675 | | - |
676 | | - |
677 | | - |
678 | | - |
679 | | - |
680 | QOpenGLFramebufferObject::Attachment QOpenGLFramebufferObject::attachment() const | - |
681 | { | - |
682 | const QOpenGLFramebufferObjectPrivate * const d = d_func(); | - |
683 | if (d->valid) never evaluated: d->valid | 0 |
684 | return d->fbo_attachment; never executed: return d->fbo_attachment; | 0 |
685 | return NoAttachment; never executed: return NoAttachment; | 0 |
686 | } | - |
687 | | - |
688 | | - |
689 | | - |
690 | | - |
691 | | - |
692 | | - |
693 | | - |
694 | void QOpenGLFramebufferObject::setAttachment(QOpenGLFramebufferObject::Attachment attachment) | - |
695 | { | - |
696 | QOpenGLFramebufferObjectPrivate * const d = d_func(); | - |
697 | if (attachment == d->fbo_attachment || !isValid()) never evaluated: attachment == d->fbo_attachment never evaluated: !isValid() | 0 |
698 | return; | 0 |
699 | QOpenGLContext *current = QOpenGLContext::currentContext(); | - |
700 | if (!current) never evaluated: !current | 0 |
701 | return; | 0 |
702 | | - |
703 | | - |
704 | | - |
705 | | - |
706 | d->funcs.glBindFramebuffer(0x8D40, d->fbo()); | - |
707 | d->initAttachments(current, attachment); | - |
708 | if (current->d_func()->current_fbo != d->fbo()) never evaluated: current->d_func()->current_fbo != d->fbo() | 0 |
709 | d->funcs.glBindFramebuffer(0x8D40, current->d_func()->current_fbo); never executed: d->funcs.glBindFramebuffer(0x8D40, current->d_func()->current_fbo); | 0 |
710 | } | 0 |
711 | | - |
712 | | - |
713 | | - |
714 | | - |
715 | | - |
716 | | - |
717 | bool QOpenGLFramebufferObject::isBound() const | - |
718 | { | - |
719 | const QOpenGLFramebufferObjectPrivate * const d = d_func(); | - |
720 | QOpenGLContext *current = QOpenGLContext::currentContext(); | - |
721 | return current ? current->d_func()->current_fbo == d->fbo() : false; never executed: return current ? current->d_func()->current_fbo == d->fbo() : false; | 0 |
722 | } | - |
723 | bool QOpenGLFramebufferObject::hasOpenGLFramebufferBlit() | - |
724 | { | - |
725 | return QOpenGLExtensions(QOpenGLContext::currentContext()).hasOpenGLExtension(QOpenGLExtensions::FramebufferBlit); never executed: return QOpenGLExtensions(QOpenGLContext::currentContext()).hasOpenGLExtension(QOpenGLExtensions::FramebufferBlit); | 0 |
726 | } | - |
727 | | - |
728 | | - |
729 | | - |
730 | | - |
731 | | - |
732 | | - |
733 | | - |
734 | void QOpenGLFramebufferObject::blitFramebuffer(QOpenGLFramebufferObject *target, | - |
735 | QOpenGLFramebufferObject *source, | - |
736 | GLbitfield buffers, GLenum filter) | - |
737 | { | - |
738 | if (!target && !source) | 0 |
739 | return; | 0 |
740 | | - |
741 | QSize targetSize; | - |
742 | QSize sourceSize; | - |
743 | | - |
744 | if (target) | 0 |
745 | targetSize = target->size(); never executed: targetSize = target->size(); | 0 |
746 | if (source) | 0 |
747 | sourceSize = source->size(); never executed: sourceSize = source->size(); | 0 |
748 | | - |
749 | if (targetSize.isEmpty()) never evaluated: targetSize.isEmpty() | 0 |
750 | targetSize = sourceSize; never executed: targetSize = sourceSize; | 0 |
751 | else if (sourceSize.isEmpty()) never evaluated: sourceSize.isEmpty() | 0 |
752 | sourceSize = targetSize; never executed: sourceSize = targetSize; | 0 |
753 | | - |
754 | blitFramebuffer(target, QRect(QPoint(0, 0), targetSize), | - |
755 | source, QRect(QPoint(0, 0), sourceSize), | - |
756 | buffers, filter); | - |
757 | } | 0 |
758 | void QOpenGLFramebufferObject::blitFramebuffer(QOpenGLFramebufferObject *target, const QRect &targetRect, | - |
759 | QOpenGLFramebufferObject *source, const QRect &sourceRect, | - |
760 | GLbitfield buffers, | - |
761 | GLenum filter) | - |
762 | { | - |
763 | QOpenGLContext *ctx = QOpenGLContext::currentContext(); | - |
764 | if (!ctx) | 0 |
765 | return; | 0 |
766 | | - |
767 | QOpenGLExtensions extensions(ctx); | - |
768 | if (!extensions.hasOpenGLExtension(QOpenGLExtensions::FramebufferBlit)) never evaluated: !extensions.hasOpenGLExtension(QOpenGLExtensions::FramebufferBlit) | 0 |
769 | return; | 0 |
770 | | - |
771 | const int sx0 = sourceRect.left(); | - |
772 | const int sx1 = sourceRect.left() + sourceRect.width(); | - |
773 | const int sy0 = sourceRect.top(); | - |
774 | const int sy1 = sourceRect.top() + sourceRect.height(); | - |
775 | | - |
776 | const int tx0 = targetRect.left(); | - |
777 | const int tx1 = targetRect.left() + targetRect.width(); | - |
778 | const int ty0 = targetRect.top(); | - |
779 | const int ty1 = targetRect.top() + targetRect.height(); | - |
780 | | - |
781 | extensions.glBindFramebuffer(0x8CA8, source ? source->handle() : 0); | - |
782 | extensions.glBindFramebuffer(0x8CA9, target ? target->handle() : 0); | - |
783 | | - |
784 | extensions.glBlitFramebuffer(sx0, sy0, sx1, sy1, | - |
785 | tx0, ty0, tx1, ty1, | - |
786 | buffers, filter); | - |
787 | | - |
788 | extensions.glBindFramebuffer(0x8D40, ctx->d_func()->current_fbo); | - |
789 | } | 0 |
790 | | - |
791 | | - |
792 | | - |
| | |