|
1 #include "precompiled.h" |
|
2 // |
|
3 // Copyright (c) 2002-2013 The ANGLE Project Authors. All rights reserved. |
|
4 // Use of this source code is governed by a BSD-style license that can be |
|
5 // found in the LICENSE file. |
|
6 // |
|
7 |
|
8 // Framebuffer.cpp: Implements the gl::Framebuffer class. Implements GL framebuffer |
|
9 // objects and related functionality. [OpenGL ES 2.0.24] section 4.4 page 105. |
|
10 |
|
11 #include "libGLESv2/Framebuffer.h" |
|
12 |
|
13 #include "libGLESv2/main.h" |
|
14 #include "libGLESv2/utilities.h" |
|
15 #include "libGLESv2/Texture.h" |
|
16 #include "libGLESv2/Context.h" |
|
17 #include "libGLESv2/renderer/Renderer.h" |
|
18 #include "libGLESv2/Renderbuffer.h" |
|
19 |
|
20 namespace gl |
|
21 { |
|
22 |
|
23 Framebuffer::Framebuffer(rx::Renderer *renderer) |
|
24 : mRenderer(renderer) |
|
25 { |
|
26 for (unsigned int colorAttachment = 0; colorAttachment < IMPLEMENTATION_MAX_DRAW_BUFFERS; colorAttachment++) |
|
27 { |
|
28 mColorbufferTypes[colorAttachment] = GL_NONE; |
|
29 mDrawBufferStates[colorAttachment] = GL_NONE; |
|
30 } |
|
31 mDrawBufferStates[0] = GL_COLOR_ATTACHMENT0_EXT; |
|
32 mReadBufferState = GL_COLOR_ATTACHMENT0_EXT; |
|
33 |
|
34 mDepthbufferType = GL_NONE; |
|
35 mStencilbufferType = GL_NONE; |
|
36 } |
|
37 |
|
38 Framebuffer::~Framebuffer() |
|
39 { |
|
40 for (unsigned int colorAttachment = 0; colorAttachment < IMPLEMENTATION_MAX_DRAW_BUFFERS; colorAttachment++) |
|
41 { |
|
42 mColorbufferPointers[colorAttachment].set(NULL); |
|
43 } |
|
44 mDepthbufferPointer.set(NULL); |
|
45 mStencilbufferPointer.set(NULL); |
|
46 } |
|
47 |
|
48 Renderbuffer *Framebuffer::lookupRenderbuffer(GLenum type, GLuint handle) const |
|
49 { |
|
50 gl::Context *context = gl::getContext(); |
|
51 Renderbuffer *buffer = NULL; |
|
52 |
|
53 if (type == GL_NONE) |
|
54 { |
|
55 buffer = NULL; |
|
56 } |
|
57 else if (type == GL_RENDERBUFFER) |
|
58 { |
|
59 buffer = context->getRenderbuffer(handle); |
|
60 } |
|
61 else if (IsInternalTextureTarget(type)) |
|
62 { |
|
63 buffer = context->getTexture(handle)->getRenderbuffer(type); |
|
64 } |
|
65 else |
|
66 { |
|
67 UNREACHABLE(); |
|
68 } |
|
69 |
|
70 return buffer; |
|
71 } |
|
72 |
|
73 void Framebuffer::setColorbuffer(unsigned int colorAttachment, GLenum type, GLuint colorbuffer) |
|
74 { |
|
75 ASSERT(colorAttachment < IMPLEMENTATION_MAX_DRAW_BUFFERS); |
|
76 mColorbufferTypes[colorAttachment] = (colorbuffer != 0) ? type : GL_NONE; |
|
77 mColorbufferPointers[colorAttachment].set(lookupRenderbuffer(type, colorbuffer)); |
|
78 } |
|
79 |
|
80 void Framebuffer::setDepthbuffer(GLenum type, GLuint depthbuffer) |
|
81 { |
|
82 mDepthbufferType = (depthbuffer != 0) ? type : GL_NONE; |
|
83 mDepthbufferPointer.set(lookupRenderbuffer(type, depthbuffer)); |
|
84 } |
|
85 |
|
86 void Framebuffer::setStencilbuffer(GLenum type, GLuint stencilbuffer) |
|
87 { |
|
88 mStencilbufferType = (stencilbuffer != 0) ? type : GL_NONE; |
|
89 mStencilbufferPointer.set(lookupRenderbuffer(type, stencilbuffer)); |
|
90 } |
|
91 |
|
92 void Framebuffer::detachTexture(GLuint texture) |
|
93 { |
|
94 for (unsigned int colorAttachment = 0; colorAttachment < IMPLEMENTATION_MAX_DRAW_BUFFERS; colorAttachment++) |
|
95 { |
|
96 if (mColorbufferPointers[colorAttachment].id() == texture && IsInternalTextureTarget(mColorbufferTypes[colorAttachment])) |
|
97 { |
|
98 mColorbufferTypes[colorAttachment] = GL_NONE; |
|
99 mColorbufferPointers[colorAttachment].set(NULL); |
|
100 } |
|
101 } |
|
102 |
|
103 if (mDepthbufferPointer.id() == texture && IsInternalTextureTarget(mDepthbufferType)) |
|
104 { |
|
105 mDepthbufferType = GL_NONE; |
|
106 mDepthbufferPointer.set(NULL); |
|
107 } |
|
108 |
|
109 if (mStencilbufferPointer.id() == texture && IsInternalTextureTarget(mStencilbufferType)) |
|
110 { |
|
111 mStencilbufferType = GL_NONE; |
|
112 mStencilbufferPointer.set(NULL); |
|
113 } |
|
114 } |
|
115 |
|
116 void Framebuffer::detachRenderbuffer(GLuint renderbuffer) |
|
117 { |
|
118 for (unsigned int colorAttachment = 0; colorAttachment < IMPLEMENTATION_MAX_DRAW_BUFFERS; colorAttachment++) |
|
119 { |
|
120 if (mColorbufferPointers[colorAttachment].id() == renderbuffer && mColorbufferTypes[colorAttachment] == GL_RENDERBUFFER) |
|
121 { |
|
122 mColorbufferTypes[colorAttachment] = GL_NONE; |
|
123 mColorbufferPointers[colorAttachment].set(NULL); |
|
124 } |
|
125 } |
|
126 |
|
127 if (mDepthbufferPointer.id() == renderbuffer && mDepthbufferType == GL_RENDERBUFFER) |
|
128 { |
|
129 mDepthbufferType = GL_NONE; |
|
130 mDepthbufferPointer.set(NULL); |
|
131 } |
|
132 |
|
133 if (mStencilbufferPointer.id() == renderbuffer && mStencilbufferType == GL_RENDERBUFFER) |
|
134 { |
|
135 mStencilbufferType = GL_NONE; |
|
136 mStencilbufferPointer.set(NULL); |
|
137 } |
|
138 } |
|
139 |
|
140 unsigned int Framebuffer::getRenderTargetSerial(unsigned int colorAttachment) const |
|
141 { |
|
142 ASSERT(colorAttachment < IMPLEMENTATION_MAX_DRAW_BUFFERS); |
|
143 |
|
144 Renderbuffer *colorbuffer = mColorbufferPointers[colorAttachment].get(); |
|
145 |
|
146 if (colorbuffer) |
|
147 { |
|
148 return colorbuffer->getSerial(); |
|
149 } |
|
150 |
|
151 return 0; |
|
152 } |
|
153 |
|
154 unsigned int Framebuffer::getDepthbufferSerial() const |
|
155 { |
|
156 Renderbuffer *depthbuffer = mDepthbufferPointer.get(); |
|
157 |
|
158 if (depthbuffer) |
|
159 { |
|
160 return depthbuffer->getSerial(); |
|
161 } |
|
162 |
|
163 return 0; |
|
164 } |
|
165 |
|
166 unsigned int Framebuffer::getStencilbufferSerial() const |
|
167 { |
|
168 Renderbuffer *stencilbuffer = mStencilbufferPointer.get(); |
|
169 |
|
170 if (stencilbuffer) |
|
171 { |
|
172 return stencilbuffer->getSerial(); |
|
173 } |
|
174 |
|
175 return 0; |
|
176 } |
|
177 |
|
178 Renderbuffer *Framebuffer::getColorbuffer(unsigned int colorAttachment) const |
|
179 { |
|
180 ASSERT(colorAttachment < IMPLEMENTATION_MAX_DRAW_BUFFERS); |
|
181 return mColorbufferPointers[colorAttachment].get(); |
|
182 } |
|
183 |
|
184 Renderbuffer *Framebuffer::getDepthbuffer() const |
|
185 { |
|
186 return mDepthbufferPointer.get(); |
|
187 } |
|
188 |
|
189 Renderbuffer *Framebuffer::getStencilbuffer() const |
|
190 { |
|
191 return mStencilbufferPointer.get(); |
|
192 } |
|
193 |
|
194 Renderbuffer *Framebuffer::getDepthOrStencilbuffer() const |
|
195 { |
|
196 Renderbuffer *depthstencilbuffer = mDepthbufferPointer.get(); |
|
197 |
|
198 if (!depthstencilbuffer) |
|
199 { |
|
200 depthstencilbuffer = mStencilbufferPointer.get(); |
|
201 } |
|
202 |
|
203 return depthstencilbuffer; |
|
204 } |
|
205 |
|
206 Renderbuffer *Framebuffer::getReadColorbuffer() const |
|
207 { |
|
208 // Will require more logic if glReadBuffers is supported |
|
209 return mColorbufferPointers[0].get(); |
|
210 } |
|
211 |
|
212 GLenum Framebuffer::getReadColorbufferType() const |
|
213 { |
|
214 // Will require more logic if glReadBuffers is supported |
|
215 return mColorbufferTypes[0]; |
|
216 } |
|
217 |
|
218 Renderbuffer *Framebuffer::getFirstColorbuffer() const |
|
219 { |
|
220 for (unsigned int colorAttachment = 0; colorAttachment < IMPLEMENTATION_MAX_DRAW_BUFFERS; colorAttachment++) |
|
221 { |
|
222 if (mColorbufferTypes[colorAttachment] != GL_NONE) |
|
223 { |
|
224 return mColorbufferPointers[colorAttachment].get(); |
|
225 } |
|
226 } |
|
227 |
|
228 return NULL; |
|
229 } |
|
230 |
|
231 GLenum Framebuffer::getColorbufferType(unsigned int colorAttachment) const |
|
232 { |
|
233 ASSERT(colorAttachment < IMPLEMENTATION_MAX_DRAW_BUFFERS); |
|
234 return mColorbufferTypes[colorAttachment]; |
|
235 } |
|
236 |
|
237 GLenum Framebuffer::getDepthbufferType() const |
|
238 { |
|
239 return mDepthbufferType; |
|
240 } |
|
241 |
|
242 GLenum Framebuffer::getStencilbufferType() const |
|
243 { |
|
244 return mStencilbufferType; |
|
245 } |
|
246 |
|
247 GLuint Framebuffer::getColorbufferHandle(unsigned int colorAttachment) const |
|
248 { |
|
249 ASSERT(colorAttachment < IMPLEMENTATION_MAX_DRAW_BUFFERS); |
|
250 return mColorbufferPointers[colorAttachment].id(); |
|
251 } |
|
252 |
|
253 GLuint Framebuffer::getDepthbufferHandle() const |
|
254 { |
|
255 return mDepthbufferPointer.id(); |
|
256 } |
|
257 |
|
258 GLuint Framebuffer::getStencilbufferHandle() const |
|
259 { |
|
260 return mStencilbufferPointer.id(); |
|
261 } |
|
262 |
|
263 GLenum Framebuffer::getDrawBufferState(unsigned int colorAttachment) const |
|
264 { |
|
265 return mDrawBufferStates[colorAttachment]; |
|
266 } |
|
267 |
|
268 void Framebuffer::setDrawBufferState(unsigned int colorAttachment, GLenum drawBuffer) |
|
269 { |
|
270 mDrawBufferStates[colorAttachment] = drawBuffer; |
|
271 } |
|
272 |
|
273 bool Framebuffer::isEnabledColorAttachment(unsigned int colorAttachment) const |
|
274 { |
|
275 return (mColorbufferTypes[colorAttachment] != GL_NONE && mDrawBufferStates[colorAttachment] != GL_NONE); |
|
276 } |
|
277 |
|
278 bool Framebuffer::hasEnabledColorAttachment() const |
|
279 { |
|
280 for (unsigned int colorAttachment = 0; colorAttachment < gl::IMPLEMENTATION_MAX_DRAW_BUFFERS; colorAttachment++) |
|
281 { |
|
282 if (isEnabledColorAttachment(colorAttachment)) |
|
283 { |
|
284 return true; |
|
285 } |
|
286 } |
|
287 |
|
288 return false; |
|
289 } |
|
290 |
|
291 bool Framebuffer::hasStencil() const |
|
292 { |
|
293 if (mStencilbufferType != GL_NONE) |
|
294 { |
|
295 const Renderbuffer *stencilbufferObject = getStencilbuffer(); |
|
296 |
|
297 if (stencilbufferObject) |
|
298 { |
|
299 return stencilbufferObject->getStencilSize() > 0; |
|
300 } |
|
301 } |
|
302 |
|
303 return false; |
|
304 } |
|
305 |
|
306 bool Framebuffer::usingExtendedDrawBuffers() const |
|
307 { |
|
308 for (unsigned int colorAttachment = 1; colorAttachment < IMPLEMENTATION_MAX_DRAW_BUFFERS; colorAttachment++) |
|
309 { |
|
310 if (isEnabledColorAttachment(colorAttachment)) |
|
311 { |
|
312 return true; |
|
313 } |
|
314 } |
|
315 |
|
316 return false; |
|
317 } |
|
318 |
|
319 GLenum Framebuffer::completeness() const |
|
320 { |
|
321 int width = 0; |
|
322 int height = 0; |
|
323 int colorbufferSize = 0; |
|
324 int samples = -1; |
|
325 bool missingAttachment = true; |
|
326 |
|
327 for (unsigned int colorAttachment = 0; colorAttachment < IMPLEMENTATION_MAX_DRAW_BUFFERS; colorAttachment++) |
|
328 { |
|
329 if (mColorbufferTypes[colorAttachment] != GL_NONE) |
|
330 { |
|
331 const Renderbuffer *colorbuffer = getColorbuffer(colorAttachment); |
|
332 |
|
333 if (!colorbuffer) |
|
334 { |
|
335 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT; |
|
336 } |
|
337 |
|
338 if (colorbuffer->getWidth() == 0 || colorbuffer->getHeight() == 0) |
|
339 { |
|
340 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT; |
|
341 } |
|
342 |
|
343 if (mColorbufferTypes[colorAttachment] == GL_RENDERBUFFER) |
|
344 { |
|
345 if (!gl::IsColorRenderable(colorbuffer->getInternalFormat())) |
|
346 { |
|
347 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT; |
|
348 } |
|
349 } |
|
350 else if (IsInternalTextureTarget(mColorbufferTypes[colorAttachment])) |
|
351 { |
|
352 GLint internalformat = colorbuffer->getInternalFormat(); |
|
353 GLenum format = gl::ExtractFormat(internalformat); |
|
354 |
|
355 if (IsCompressed(format) || |
|
356 format == GL_ALPHA || |
|
357 format == GL_LUMINANCE || |
|
358 format == GL_LUMINANCE_ALPHA) |
|
359 { |
|
360 return GL_FRAMEBUFFER_UNSUPPORTED; |
|
361 } |
|
362 |
|
363 bool filtering, renderable; |
|
364 |
|
365 if ((gl::IsFloat32Format(internalformat) && !mRenderer->getFloat32TextureSupport(&filtering, &renderable)) || |
|
366 (gl::IsFloat16Format(internalformat) && !mRenderer->getFloat16TextureSupport(&filtering, &renderable))) |
|
367 { |
|
368 return GL_FRAMEBUFFER_UNSUPPORTED; |
|
369 } |
|
370 |
|
371 if (gl::IsDepthTexture(internalformat) || gl::IsStencilTexture(internalformat)) |
|
372 { |
|
373 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT; |
|
374 } |
|
375 } |
|
376 else |
|
377 { |
|
378 UNREACHABLE(); |
|
379 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT; |
|
380 } |
|
381 |
|
382 if (!missingAttachment) |
|
383 { |
|
384 // all color attachments must have the same width and height |
|
385 if (colorbuffer->getWidth() != width || colorbuffer->getHeight() != height) |
|
386 { |
|
387 return GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS; |
|
388 } |
|
389 |
|
390 // APPLE_framebuffer_multisample, which EXT_draw_buffers refers to, requires that |
|
391 // all color attachments have the same number of samples for the FBO to be complete. |
|
392 if (colorbuffer->getSamples() != samples) |
|
393 { |
|
394 return GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE_EXT; |
|
395 } |
|
396 |
|
397 // all color attachments attachments must have the same number of bitplanes |
|
398 if (gl::ComputePixelSize(colorbuffer->getInternalFormat()) != colorbufferSize) |
|
399 { |
|
400 return GL_FRAMEBUFFER_UNSUPPORTED; |
|
401 } |
|
402 |
|
403 // D3D11 does not allow for overlapping RenderTargetViews, so ensure uniqueness |
|
404 for (unsigned int previousColorAttachment = 0; previousColorAttachment < colorAttachment; previousColorAttachment++) |
|
405 { |
|
406 if (mColorbufferPointers[colorAttachment].get() == mColorbufferPointers[previousColorAttachment].get()) |
|
407 { |
|
408 return GL_FRAMEBUFFER_UNSUPPORTED; |
|
409 } |
|
410 } |
|
411 } |
|
412 else |
|
413 { |
|
414 width = colorbuffer->getWidth(); |
|
415 height = colorbuffer->getHeight(); |
|
416 samples = colorbuffer->getSamples(); |
|
417 colorbufferSize = gl::ComputePixelSize(colorbuffer->getInternalFormat()); |
|
418 missingAttachment = false; |
|
419 } |
|
420 } |
|
421 } |
|
422 |
|
423 const Renderbuffer *depthbuffer = NULL; |
|
424 const Renderbuffer *stencilbuffer = NULL; |
|
425 |
|
426 if (mDepthbufferType != GL_NONE) |
|
427 { |
|
428 depthbuffer = getDepthbuffer(); |
|
429 |
|
430 if (!depthbuffer) |
|
431 { |
|
432 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT; |
|
433 } |
|
434 |
|
435 if (depthbuffer->getWidth() == 0 || depthbuffer->getHeight() == 0) |
|
436 { |
|
437 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT; |
|
438 } |
|
439 |
|
440 if (mDepthbufferType == GL_RENDERBUFFER) |
|
441 { |
|
442 if (!gl::IsDepthRenderable(depthbuffer->getInternalFormat())) |
|
443 { |
|
444 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT; |
|
445 } |
|
446 } |
|
447 else if (IsInternalTextureTarget(mDepthbufferType)) |
|
448 { |
|
449 GLint internalformat = depthbuffer->getInternalFormat(); |
|
450 |
|
451 // depth texture attachments require OES/ANGLE_depth_texture |
|
452 if (!mRenderer->getDepthTextureSupport()) |
|
453 { |
|
454 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT; |
|
455 } |
|
456 |
|
457 if (!gl::IsDepthTexture(internalformat)) |
|
458 { |
|
459 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT; |
|
460 } |
|
461 } |
|
462 else |
|
463 { |
|
464 UNREACHABLE(); |
|
465 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT; |
|
466 } |
|
467 |
|
468 if (missingAttachment) |
|
469 { |
|
470 width = depthbuffer->getWidth(); |
|
471 height = depthbuffer->getHeight(); |
|
472 samples = depthbuffer->getSamples(); |
|
473 missingAttachment = false; |
|
474 } |
|
475 else if (width != depthbuffer->getWidth() || height != depthbuffer->getHeight()) |
|
476 { |
|
477 return GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS; |
|
478 } |
|
479 else if (samples != depthbuffer->getSamples()) |
|
480 { |
|
481 return GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE_ANGLE; |
|
482 } |
|
483 } |
|
484 |
|
485 if (mStencilbufferType != GL_NONE) |
|
486 { |
|
487 stencilbuffer = getStencilbuffer(); |
|
488 |
|
489 if (!stencilbuffer) |
|
490 { |
|
491 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT; |
|
492 } |
|
493 |
|
494 if (stencilbuffer->getWidth() == 0 || stencilbuffer->getHeight() == 0) |
|
495 { |
|
496 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT; |
|
497 } |
|
498 |
|
499 if (mStencilbufferType == GL_RENDERBUFFER) |
|
500 { |
|
501 if (!gl::IsStencilRenderable(stencilbuffer->getInternalFormat())) |
|
502 { |
|
503 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT; |
|
504 } |
|
505 } |
|
506 else if (IsInternalTextureTarget(mStencilbufferType)) |
|
507 { |
|
508 GLint internalformat = stencilbuffer->getInternalFormat(); |
|
509 |
|
510 // texture stencil attachments come along as part |
|
511 // of OES_packed_depth_stencil + OES/ANGLE_depth_texture |
|
512 if (!mRenderer->getDepthTextureSupport()) |
|
513 { |
|
514 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT; |
|
515 } |
|
516 |
|
517 if (!gl::IsStencilTexture(internalformat)) |
|
518 { |
|
519 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT; |
|
520 } |
|
521 } |
|
522 else |
|
523 { |
|
524 UNREACHABLE(); |
|
525 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT; |
|
526 } |
|
527 |
|
528 if (missingAttachment) |
|
529 { |
|
530 width = stencilbuffer->getWidth(); |
|
531 height = stencilbuffer->getHeight(); |
|
532 samples = stencilbuffer->getSamples(); |
|
533 missingAttachment = false; |
|
534 } |
|
535 else if (width != stencilbuffer->getWidth() || height != stencilbuffer->getHeight()) |
|
536 { |
|
537 return GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS; |
|
538 } |
|
539 else if (samples != stencilbuffer->getSamples()) |
|
540 { |
|
541 return GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE_ANGLE; |
|
542 } |
|
543 } |
|
544 |
|
545 // if we have both a depth and stencil buffer, they must refer to the same object |
|
546 // since we only support packed_depth_stencil and not separate depth and stencil |
|
547 if (depthbuffer && stencilbuffer && (depthbuffer != stencilbuffer)) |
|
548 { |
|
549 return GL_FRAMEBUFFER_UNSUPPORTED; |
|
550 } |
|
551 |
|
552 // we need to have at least one attachment to be complete |
|
553 if (missingAttachment) |
|
554 { |
|
555 return GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT; |
|
556 } |
|
557 |
|
558 return GL_FRAMEBUFFER_COMPLETE; |
|
559 } |
|
560 |
|
561 DefaultFramebuffer::DefaultFramebuffer(rx::Renderer *renderer, Colorbuffer *colorbuffer, DepthStencilbuffer *depthStencil) |
|
562 : Framebuffer(renderer) |
|
563 { |
|
564 mColorbufferPointers[0].set(new Renderbuffer(mRenderer, 0, colorbuffer)); |
|
565 |
|
566 Renderbuffer *depthStencilRenderbuffer = new Renderbuffer(mRenderer, 0, depthStencil); |
|
567 mDepthbufferPointer.set(depthStencilRenderbuffer); |
|
568 mStencilbufferPointer.set(depthStencilRenderbuffer); |
|
569 |
|
570 mColorbufferTypes[0] = GL_RENDERBUFFER; |
|
571 mDepthbufferType = (depthStencilRenderbuffer->getDepthSize() != 0) ? GL_RENDERBUFFER : GL_NONE; |
|
572 mStencilbufferType = (depthStencilRenderbuffer->getStencilSize() != 0) ? GL_RENDERBUFFER : GL_NONE; |
|
573 |
|
574 mDrawBufferStates[0] = GL_BACK; |
|
575 mReadBufferState = GL_BACK; |
|
576 } |
|
577 |
|
578 int Framebuffer::getSamples() const |
|
579 { |
|
580 if (completeness() == GL_FRAMEBUFFER_COMPLETE) |
|
581 { |
|
582 // for a complete framebuffer, all attachments must have the same sample count |
|
583 // in this case return the first nonzero sample size |
|
584 for (unsigned int colorAttachment = 0; colorAttachment < IMPLEMENTATION_MAX_DRAW_BUFFERS; colorAttachment++) |
|
585 { |
|
586 if (mColorbufferTypes[colorAttachment] != GL_NONE) |
|
587 { |
|
588 return getColorbuffer(colorAttachment)->getSamples(); |
|
589 } |
|
590 } |
|
591 } |
|
592 |
|
593 return 0; |
|
594 } |
|
595 |
|
596 GLenum DefaultFramebuffer::completeness() const |
|
597 { |
|
598 // The default framebuffer *must* always be complete, though it may not be |
|
599 // subject to the same rules as application FBOs. ie, it could have 0x0 size. |
|
600 return GL_FRAMEBUFFER_COMPLETE; |
|
601 } |
|
602 |
|
603 } |