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
Framebuffer(rx::Renderer * renderer)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
~Framebuffer()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
lookupRenderbuffer(GLenum type,GLuint handle) const48 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
setColorbuffer(unsigned int colorAttachment,GLenum type,GLuint colorbuffer)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
setDepthbuffer(GLenum type,GLuint depthbuffer)80 void Framebuffer::setDepthbuffer(GLenum type, GLuint depthbuffer)
81 {
82 mDepthbufferType = (depthbuffer != 0) ? type : GL_NONE;
83 mDepthbufferPointer.set(lookupRenderbuffer(type, depthbuffer));
84 }
85
setStencilbuffer(GLenum type,GLuint stencilbuffer)86 void Framebuffer::setStencilbuffer(GLenum type, GLuint stencilbuffer)
87 {
88 mStencilbufferType = (stencilbuffer != 0) ? type : GL_NONE;
89 mStencilbufferPointer.set(lookupRenderbuffer(type, stencilbuffer));
90 }
91
detachTexture(GLuint texture)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
detachRenderbuffer(GLuint renderbuffer)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
getRenderTargetSerial(unsigned int colorAttachment) const140 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
getDepthbufferSerial() const154 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
getStencilbufferSerial() const166 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
getColorbuffer(unsigned int colorAttachment) const178 Renderbuffer *Framebuffer::getColorbuffer(unsigned int colorAttachment) const
179 {
180 ASSERT(colorAttachment < IMPLEMENTATION_MAX_DRAW_BUFFERS);
181 return mColorbufferPointers[colorAttachment].get();
182 }
183
getDepthbuffer() const184 Renderbuffer *Framebuffer::getDepthbuffer() const
185 {
186 return mDepthbufferPointer.get();
187 }
188
getStencilbuffer() const189 Renderbuffer *Framebuffer::getStencilbuffer() const
190 {
191 return mStencilbufferPointer.get();
192 }
193
getDepthOrStencilbuffer() const194 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
getReadColorbuffer() const206 Renderbuffer *Framebuffer::getReadColorbuffer() const
207 {
208 // Will require more logic if glReadBuffers is supported
209 return mColorbufferPointers[0].get();
210 }
211
getReadColorbufferType() const212 GLenum Framebuffer::getReadColorbufferType() const
213 {
214 // Will require more logic if glReadBuffers is supported
215 return mColorbufferTypes[0];
216 }
217
getFirstColorbuffer() const218 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
getColorbufferType(unsigned int colorAttachment) const231 GLenum Framebuffer::getColorbufferType(unsigned int colorAttachment) const
232 {
233 ASSERT(colorAttachment < IMPLEMENTATION_MAX_DRAW_BUFFERS);
234 return mColorbufferTypes[colorAttachment];
235 }
236
getDepthbufferType() const237 GLenum Framebuffer::getDepthbufferType() const
238 {
239 return mDepthbufferType;
240 }
241
getStencilbufferType() const242 GLenum Framebuffer::getStencilbufferType() const
243 {
244 return mStencilbufferType;
245 }
246
getColorbufferHandle(unsigned int colorAttachment) const247 GLuint Framebuffer::getColorbufferHandle(unsigned int colorAttachment) const
248 {
249 ASSERT(colorAttachment < IMPLEMENTATION_MAX_DRAW_BUFFERS);
250 return mColorbufferPointers[colorAttachment].id();
251 }
252
getDepthbufferHandle() const253 GLuint Framebuffer::getDepthbufferHandle() const
254 {
255 return mDepthbufferPointer.id();
256 }
257
getStencilbufferHandle() const258 GLuint Framebuffer::getStencilbufferHandle() const
259 {
260 return mStencilbufferPointer.id();
261 }
262
getDrawBufferState(unsigned int colorAttachment) const263 GLenum Framebuffer::getDrawBufferState(unsigned int colorAttachment) const
264 {
265 return mDrawBufferStates[colorAttachment];
266 }
267
setDrawBufferState(unsigned int colorAttachment,GLenum drawBuffer)268 void Framebuffer::setDrawBufferState(unsigned int colorAttachment, GLenum drawBuffer)
269 {
270 mDrawBufferStates[colorAttachment] = drawBuffer;
271 }
272
isEnabledColorAttachment(unsigned int colorAttachment) const273 bool Framebuffer::isEnabledColorAttachment(unsigned int colorAttachment) const
274 {
275 return (mColorbufferTypes[colorAttachment] != GL_NONE && mDrawBufferStates[colorAttachment] != GL_NONE);
276 }
277
hasEnabledColorAttachment() const278 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
hasStencil() const291 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
usingExtendedDrawBuffers() const306 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
completeness() const319 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
DefaultFramebuffer(rx::Renderer * renderer,Colorbuffer * colorbuffer,DepthStencilbuffer * depthStencil)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
getSamples() const578 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
completeness() const596 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 }
604