Update To 11.40.268.0
[platform/framework/web/crosswalk.git] / src / third_party / angle / src / libGLESv2 / Framebuffer.cpp
1 //
2 // Copyright (c) 2002-2014 The ANGLE Project Authors. All rights reserved.
3 // Use of this source code is governed by a BSD-style license that can be
4 // found in the LICENSE file.
5 //
6
7 // Framebuffer.cpp: Implements the gl::Framebuffer class. Implements GL framebuffer
8 // objects and related functionality. [OpenGL ES 2.0.24] section 4.4 page 105.
9
10 #include "libGLESv2/Framebuffer.h"
11 #include "libGLESv2/main.h"
12 #include "libGLESv2/formatutils.h"
13 #include "libGLESv2/Texture.h"
14 #include "libGLESv2/Context.h"
15 #include "libGLESv2/Renderbuffer.h"
16 #include "libGLESv2/FramebufferAttachment.h"
17 #include "libGLESv2/renderer/Renderer.h"
18 #include "libGLESv2/renderer/RenderTarget.h"
19 #include "libGLESv2/renderer/Workarounds.h"
20 #include "libGLESv2/renderer/d3d/TextureD3D.h"
21
22 #include "common/utilities.h"
23
24 namespace rx
25 {
26 gl::Error GetAttachmentRenderTarget(gl::FramebufferAttachment *attachment, RenderTarget **outRT)
27 {
28     if (attachment->isTexture())
29     {
30         gl::Texture *texture = attachment->getTexture();
31         ASSERT(texture);
32         TextureD3D *textureD3D = TextureD3D::makeTextureD3D(texture->getImplementation());
33         const gl::ImageIndex *index = attachment->getTextureImageIndex();
34         ASSERT(index);
35         return textureD3D->getRenderTarget(*index, outRT);
36     }
37     else
38     {
39         gl::Renderbuffer *renderbuffer = attachment->getRenderbuffer();
40         ASSERT(renderbuffer);
41
42         // TODO: cast to RenderbufferD3D
43         *outRT = renderbuffer->getStorage()->getRenderTarget();
44         return gl::Error(GL_NO_ERROR);
45     }
46 }
47
48 // Note: RenderTarget serials should ideally be in the RenderTargets themselves.
49 unsigned int GetAttachmentSerial(gl::FramebufferAttachment *attachment)
50 {
51     if (attachment->isTexture())
52     {
53         gl::Texture *texture = attachment->getTexture();
54         ASSERT(texture);
55         TextureD3D *textureD3D = TextureD3D::makeTextureD3D(texture->getImplementation());
56         const gl::ImageIndex *index = attachment->getTextureImageIndex();
57         ASSERT(index);
58         return textureD3D->getRenderTargetSerial(*index);
59     }
60
61     gl::Renderbuffer *renderbuffer = attachment->getRenderbuffer();
62     ASSERT(renderbuffer);
63
64     // TODO: cast to RenderbufferD3D
65     return renderbuffer->getStorage()->getSerial();
66 }
67
68 }
69
70 namespace gl
71 {
72
73 Framebuffer::Framebuffer(rx::Renderer *renderer, GLuint id)
74     : mRenderer(renderer),
75       mId(id),
76       mReadBufferState(GL_COLOR_ATTACHMENT0_EXT),
77       mDepthbuffer(NULL),
78       mStencilbuffer(NULL)
79 {
80     for (unsigned int colorAttachment = 0; colorAttachment < IMPLEMENTATION_MAX_DRAW_BUFFERS; colorAttachment++)
81     {
82         mColorbuffers[colorAttachment] = NULL;
83         mDrawBufferStates[colorAttachment] = GL_NONE;
84     }
85     mDrawBufferStates[0] = GL_COLOR_ATTACHMENT0_EXT;
86 }
87
88 Framebuffer::~Framebuffer()
89 {
90     for (unsigned int colorAttachment = 0; colorAttachment < IMPLEMENTATION_MAX_DRAW_BUFFERS; colorAttachment++)
91     {
92         SafeDelete(mColorbuffers[colorAttachment]);
93     }
94     SafeDelete(mDepthbuffer);
95     SafeDelete(mStencilbuffer);
96 }
97
98 FramebufferAttachment *Framebuffer::createAttachment(GLenum binding, GLenum type, GLuint handle, GLint level, GLint layer) const
99 {
100     if (handle == 0)
101     {
102         return NULL;
103     }
104
105     gl::Context *context = gl::getContext();
106
107     switch (type)
108     {
109       case GL_NONE:
110         return NULL;
111
112       case GL_RENDERBUFFER:
113         return new RenderbufferAttachment(binding, context->getRenderbuffer(handle));
114
115       case GL_TEXTURE_2D:
116         {
117             Texture *texture = context->getTexture(handle);
118             if (texture && texture->getTarget() == GL_TEXTURE_2D)
119             {
120                 return new TextureAttachment(binding, texture, ImageIndex::Make2D(level));
121             }
122             else
123             {
124                 return NULL;
125             }
126         }
127
128       case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
129       case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
130       case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
131       case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
132       case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
133       case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
134         {
135             Texture *texture = context->getTexture(handle);
136             if (texture && texture->getTarget() == GL_TEXTURE_CUBE_MAP)
137             {
138                 return new TextureAttachment(binding, texture, ImageIndex::MakeCube(type, level));
139             }
140             else
141             {
142                 return NULL;
143             }
144         }
145
146       case GL_TEXTURE_3D:
147         {
148             Texture *texture = context->getTexture(handle);
149             if (texture && texture->getTarget() == GL_TEXTURE_3D)
150             {
151                 return new TextureAttachment(binding, texture, ImageIndex::Make3D(level, layer));
152             }
153             else
154             {
155                 return NULL;
156             }
157         }
158
159       case GL_TEXTURE_2D_ARRAY:
160         {
161             Texture *texture = context->getTexture(handle);
162             if (texture && texture->getTarget() == GL_TEXTURE_2D_ARRAY)
163             {
164                 return new TextureAttachment(binding, texture, ImageIndex::Make2DArray(level, layer));
165             }
166             else
167             {
168                 return NULL;
169             }
170         }
171
172       default:
173         UNREACHABLE();
174         return NULL;
175     }
176 }
177
178 void Framebuffer::setColorbuffer(unsigned int colorAttachment, GLenum type, GLuint colorbuffer, GLint level, GLint layer)
179 {
180     ASSERT(colorAttachment < IMPLEMENTATION_MAX_DRAW_BUFFERS);
181     SafeDelete(mColorbuffers[colorAttachment]);
182     GLenum binding = colorAttachment + GL_COLOR_ATTACHMENT0;
183     mColorbuffers[colorAttachment] = createAttachment(binding, type, colorbuffer, level, layer);
184 }
185
186 void Framebuffer::setDepthbuffer(GLenum type, GLuint depthbuffer, GLint level, GLint layer)
187 {
188     SafeDelete(mDepthbuffer);
189     mDepthbuffer = createAttachment(GL_DEPTH_ATTACHMENT, type, depthbuffer, level, layer);
190 }
191
192 void Framebuffer::setStencilbuffer(GLenum type, GLuint stencilbuffer, GLint level, GLint layer)
193 {
194     SafeDelete(mStencilbuffer);
195     mStencilbuffer = createAttachment(GL_STENCIL_ATTACHMENT, type, stencilbuffer, level, layer);
196 }
197
198 void Framebuffer::setDepthStencilBuffer(GLenum type, GLuint depthStencilBuffer, GLint level, GLint layer)
199 {
200     FramebufferAttachment *attachment = createAttachment(GL_DEPTH_STENCIL_ATTACHMENT, type, depthStencilBuffer, level, layer);
201
202     SafeDelete(mDepthbuffer);
203     SafeDelete(mStencilbuffer);
204
205     // ensure this is a legitimate depth+stencil format
206     if (attachment && attachment->getDepthSize() > 0 && attachment->getStencilSize() > 0)
207     {
208         mDepthbuffer = attachment;
209
210         // Make a new attachment object to ensure we do not double-delete
211         // See angle issue 686
212         mStencilbuffer = createAttachment(GL_DEPTH_STENCIL_ATTACHMENT, type, depthStencilBuffer, level, layer);
213     }
214 }
215
216 void Framebuffer::detachTexture(GLuint textureId)
217 {
218     for (unsigned int colorAttachment = 0; colorAttachment < IMPLEMENTATION_MAX_DRAW_BUFFERS; colorAttachment++)
219     {
220         FramebufferAttachment *attachment = mColorbuffers[colorAttachment];
221
222         if (attachment && attachment->isTextureWithId(textureId))
223         {
224             SafeDelete(mColorbuffers[colorAttachment]);
225         }
226     }
227
228     if (mDepthbuffer && mDepthbuffer->isTextureWithId(textureId))
229     {
230         SafeDelete(mDepthbuffer);
231     }
232
233     if (mStencilbuffer && mStencilbuffer->isTextureWithId(textureId))
234     {
235         SafeDelete(mStencilbuffer);
236     }
237 }
238
239 void Framebuffer::detachRenderbuffer(GLuint renderbufferId)
240 {
241     for (unsigned int colorAttachment = 0; colorAttachment < IMPLEMENTATION_MAX_DRAW_BUFFERS; colorAttachment++)
242     {
243         FramebufferAttachment *attachment = mColorbuffers[colorAttachment];
244
245         if (attachment && attachment->isRenderbufferWithId(renderbufferId))
246         {
247             SafeDelete(mColorbuffers[colorAttachment]);
248         }
249     }
250
251     if (mDepthbuffer && mDepthbuffer->isRenderbufferWithId(renderbufferId))
252     {
253         SafeDelete(mDepthbuffer);
254     }
255
256     if (mStencilbuffer && mStencilbuffer->isRenderbufferWithId(renderbufferId))
257     {
258         SafeDelete(mStencilbuffer);
259     }
260 }
261
262 FramebufferAttachment *Framebuffer::getColorbuffer(unsigned int colorAttachment) const
263 {
264     ASSERT(colorAttachment < IMPLEMENTATION_MAX_DRAW_BUFFERS);
265     return mColorbuffers[colorAttachment];
266 }
267
268 FramebufferAttachment *Framebuffer::getDepthbuffer() const
269 {
270     return mDepthbuffer;
271 }
272
273 FramebufferAttachment *Framebuffer::getStencilbuffer() const
274 {
275     return mStencilbuffer;
276 }
277
278 FramebufferAttachment *Framebuffer::getDepthStencilBuffer() const
279 {
280     return (hasValidDepthStencil() ? mDepthbuffer : NULL);
281 }
282
283 FramebufferAttachment *Framebuffer::getDepthOrStencilbuffer() const
284 {
285     FramebufferAttachment *depthstencilbuffer = mDepthbuffer;
286     
287     if (!depthstencilbuffer)
288     {
289         depthstencilbuffer = mStencilbuffer;
290     }
291
292     return depthstencilbuffer;
293 }
294
295 FramebufferAttachment *Framebuffer::getReadColorbuffer() const
296 {
297     // Will require more logic if glReadBuffers is supported
298     return mColorbuffers[0];
299 }
300
301 GLenum Framebuffer::getReadColorbufferType() const
302 {
303     // Will require more logic if glReadBuffers is supported
304     return (mColorbuffers[0] ? mColorbuffers[0]->type() : GL_NONE);
305 }
306
307 FramebufferAttachment *Framebuffer::getFirstColorbuffer() const
308 {
309     for (unsigned int colorAttachment = 0; colorAttachment < IMPLEMENTATION_MAX_DRAW_BUFFERS; colorAttachment++)
310     {
311         if (mColorbuffers[colorAttachment])
312         {
313             return mColorbuffers[colorAttachment];
314         }
315     }
316
317     return NULL;
318 }
319
320 FramebufferAttachment *Framebuffer::getAttachment(GLenum attachment) const
321 {
322     if (attachment >= GL_COLOR_ATTACHMENT0 && attachment <= GL_COLOR_ATTACHMENT15)
323     {
324         return getColorbuffer(attachment - GL_COLOR_ATTACHMENT0);
325     }
326     else
327     {
328         switch (attachment)
329         {
330           case GL_DEPTH_ATTACHMENT:
331             return getDepthbuffer();
332           case GL_STENCIL_ATTACHMENT:
333             return getStencilbuffer();
334           case GL_DEPTH_STENCIL_ATTACHMENT:
335             return getDepthStencilBuffer();
336           default:
337             UNREACHABLE();
338             return NULL;
339         }
340     }
341 }
342
343 GLenum Framebuffer::getDrawBufferState(unsigned int colorAttachment) const
344 {
345     return mDrawBufferStates[colorAttachment];
346 }
347
348 void Framebuffer::setDrawBufferState(unsigned int colorAttachment, GLenum drawBuffer)
349 {
350     mDrawBufferStates[colorAttachment] = drawBuffer;
351 }
352
353 bool Framebuffer::isEnabledColorAttachment(unsigned int colorAttachment) const
354 {
355     return (mColorbuffers[colorAttachment] && mDrawBufferStates[colorAttachment] != GL_NONE);
356 }
357
358 bool Framebuffer::hasEnabledColorAttachment() const
359 {
360     for (unsigned int colorAttachment = 0; colorAttachment < gl::IMPLEMENTATION_MAX_DRAW_BUFFERS; colorAttachment++)
361     {
362         if (isEnabledColorAttachment(colorAttachment))
363         {
364             return true;
365         }
366     }
367
368     return false;
369 }
370
371 bool Framebuffer::hasStencil() const
372 {
373     return (mStencilbuffer && mStencilbuffer->getStencilSize() > 0);
374 }
375
376 bool Framebuffer::usingExtendedDrawBuffers() const
377 {
378     for (unsigned int colorAttachment = 1; colorAttachment < IMPLEMENTATION_MAX_DRAW_BUFFERS; colorAttachment++)
379     {
380         if (isEnabledColorAttachment(colorAttachment))
381         {
382             return true;
383         }
384     }
385
386     return false;
387 }
388
389 GLenum Framebuffer::completeness() const
390 {
391     int width = 0;
392     int height = 0;
393     unsigned int colorbufferSize = 0;
394     int samples = -1;
395     bool missingAttachment = true;
396     GLuint clientVersion = mRenderer->getCurrentClientVersion();
397
398     for (unsigned int colorAttachment = 0; colorAttachment < IMPLEMENTATION_MAX_DRAW_BUFFERS; colorAttachment++)
399     {
400         const FramebufferAttachment *colorbuffer = mColorbuffers[colorAttachment];
401
402         if (colorbuffer)
403         {
404             if (colorbuffer->getWidth() == 0 || colorbuffer->getHeight() == 0)
405             {
406                 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
407             }
408
409             GLenum internalformat = colorbuffer->getInternalFormat();
410             // TODO(geofflang): use context's texture caps
411             const TextureCaps &formatCaps = mRenderer->getRendererTextureCaps().get(internalformat);
412             const InternalFormat &formatInfo = GetInternalFormatInfo(internalformat);
413             if (colorbuffer->isTexture())
414             {
415                 if (!formatCaps.renderable)
416                 {
417                     return GL_FRAMEBUFFER_UNSUPPORTED;
418                 }
419
420                 if (formatInfo.depthBits > 0 || formatInfo.stencilBits > 0)
421                 {
422                     return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
423                 }
424             }
425             else
426             {
427                 if (!formatCaps.renderable || formatInfo.depthBits > 0 || formatInfo.stencilBits > 0)
428                 {
429                     return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
430                 }
431             }
432
433             if (!missingAttachment)
434             {
435                 // all color attachments must have the same width and height
436                 if (colorbuffer->getWidth() != width || colorbuffer->getHeight() != height)
437                 {
438                     return GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS;
439                 }
440
441                 // APPLE_framebuffer_multisample, which EXT_draw_buffers refers to, requires that
442                 // all color attachments have the same number of samples for the FBO to be complete.
443                 if (colorbuffer->getSamples() != samples)
444                 {
445                     return GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE_EXT;
446                 }
447
448                 // in GLES 2.0, all color attachments attachments must have the same number of bitplanes
449                 // in GLES 3.0, there is no such restriction
450                 if (clientVersion < 3)
451                 {
452                     if (formatInfo.pixelBytes != colorbufferSize)
453                     {
454                         return GL_FRAMEBUFFER_UNSUPPORTED;
455                     }
456                 }
457
458                 // D3D11 does not allow for overlapping RenderTargetViews, so ensure uniqueness
459                 for (unsigned int previousColorAttachment = 0; previousColorAttachment < colorAttachment; previousColorAttachment++)
460                 {
461                     const FramebufferAttachment *previousAttachment = mColorbuffers[previousColorAttachment];
462
463                     if (previousAttachment &&
464                         (colorbuffer->id() == previousAttachment->id() &&
465                          colorbuffer->type() == previousAttachment->type()))
466                     {
467                         return GL_FRAMEBUFFER_UNSUPPORTED;
468                     }
469                 }
470             }
471             else
472             {
473                 width = colorbuffer->getWidth();
474                 height = colorbuffer->getHeight();
475                 samples = colorbuffer->getSamples();
476                 colorbufferSize = formatInfo.pixelBytes;
477                 missingAttachment = false;
478             }
479         }
480     }
481
482     if (mDepthbuffer)
483     {
484         if (mDepthbuffer->getWidth() == 0 || mDepthbuffer->getHeight() == 0)
485         {
486             return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
487         }
488
489         GLenum internalformat = mDepthbuffer->getInternalFormat();
490         // TODO(geofflang): use context's texture caps
491         const TextureCaps &formatCaps = mRenderer->getRendererTextureCaps().get(internalformat);
492         const InternalFormat &formatInfo = GetInternalFormatInfo(internalformat);
493         if (mDepthbuffer->isTexture())
494         {
495             // depth texture attachments require OES/ANGLE_depth_texture
496             // TODO(geofflang): use context's extensions
497             if (!mRenderer->getRendererExtensions().depthTextures)
498             {
499                 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
500             }
501
502             if (!formatCaps.renderable)
503             {
504                 return GL_FRAMEBUFFER_UNSUPPORTED;
505             }
506
507             if (formatInfo.depthBits == 0)
508             {
509                 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
510             }
511         }
512         else
513         {
514             if (!formatCaps.renderable || formatInfo.depthBits == 0)
515             {
516                 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
517             }
518         }
519
520         if (missingAttachment)
521         {
522             width = mDepthbuffer->getWidth();
523             height = mDepthbuffer->getHeight();
524             samples = mDepthbuffer->getSamples();
525             missingAttachment = false;
526         }
527         else if (width != mDepthbuffer->getWidth() || height != mDepthbuffer->getHeight())
528         {
529             return GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS;
530         }
531         else if (samples != mDepthbuffer->getSamples())
532         {
533             return GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE_ANGLE;
534         }
535     }
536
537     if (mStencilbuffer)
538     {
539         if (mStencilbuffer->getWidth() == 0 || mStencilbuffer->getHeight() == 0)
540         {
541             return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
542         }
543
544         GLenum internalformat = mStencilbuffer->getInternalFormat();
545         // TODO(geofflang): use context's texture caps
546         const TextureCaps &formatCaps = mRenderer->getRendererTextureCaps().get(internalformat);
547         const InternalFormat &formatInfo = GetInternalFormatInfo(internalformat);
548         if (mStencilbuffer->isTexture())
549         {
550             // texture stencil attachments come along as part
551             // of OES_packed_depth_stencil + OES/ANGLE_depth_texture
552             // TODO(geofflang): use context's extensions
553             if (!mRenderer->getRendererExtensions().depthTextures)
554             {
555                 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
556             }
557
558             if (!formatCaps.renderable)
559             {
560                 return GL_FRAMEBUFFER_UNSUPPORTED;
561             }
562
563             if (formatInfo.stencilBits == 0)
564             {
565                 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
566             }
567         }
568         else
569         {
570             if (!formatCaps.renderable || formatInfo.stencilBits == 0)
571             {
572                 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
573             }
574         }
575
576         if (missingAttachment)
577         {
578             width = mStencilbuffer->getWidth();
579             height = mStencilbuffer->getHeight();
580             samples = mStencilbuffer->getSamples();
581             missingAttachment = false;
582         }
583         else if (width != mStencilbuffer->getWidth() || height != mStencilbuffer->getHeight())
584         {
585             return GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS;
586         }
587         else if (samples != mStencilbuffer->getSamples())
588         {
589             return GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE_ANGLE;
590         }
591     }
592
593     // if we have both a depth and stencil buffer, they must refer to the same object
594     // since we only support packed_depth_stencil and not separate depth and stencil
595     if (mDepthbuffer && mStencilbuffer && !hasValidDepthStencil())
596     {
597         return GL_FRAMEBUFFER_UNSUPPORTED;
598     }
599
600     // we need to have at least one attachment to be complete
601     if (missingAttachment)
602     {
603         return GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT;
604     }
605
606     return GL_FRAMEBUFFER_COMPLETE;
607 }
608
609 Error Framebuffer::invalidate(const Caps &caps, GLsizei numAttachments, const GLenum *attachments)
610 {
611     GLuint maxDimension = caps.maxRenderbufferSize;
612     return invalidateSub(numAttachments, attachments, 0, 0, maxDimension, maxDimension);
613 }
614
615 Error Framebuffer::invalidateSub(GLsizei numAttachments, const GLenum *attachments, GLint x, GLint y, GLsizei width, GLsizei height)
616 {
617     ASSERT(completeness() == GL_FRAMEBUFFER_COMPLETE);
618     for (GLsizei attachIndex = 0; attachIndex < numAttachments; ++attachIndex)
619     {
620         GLenum attachmentTarget = attachments[attachIndex];
621
622         FramebufferAttachment *attachment = (attachmentTarget == GL_DEPTH_STENCIL_ATTACHMENT) ? getDepthOrStencilbuffer()
623                                                                                               : getAttachment(attachmentTarget);
624
625         if (attachment)
626         {
627             rx::RenderTarget *renderTarget = NULL;
628             Error error = rx::GetAttachmentRenderTarget(attachment, &renderTarget);
629             if (error.isError())
630             {
631                 return error;
632             }
633
634             renderTarget->invalidate(x, y, width, height);
635         }
636     }
637
638     return Error(GL_NO_ERROR);
639 }
640
641 DefaultFramebuffer::DefaultFramebuffer(rx::Renderer *renderer, Colorbuffer *colorbuffer, DepthStencilbuffer *depthStencil)
642     : Framebuffer(renderer, 0)
643 {
644     Renderbuffer *colorRenderbuffer = new Renderbuffer(0, colorbuffer);
645     mColorbuffers[0] = new RenderbufferAttachment(GL_BACK, colorRenderbuffer);
646
647     GLenum depthStencilActualFormat = depthStencil->getActualFormat();
648     const gl::InternalFormat &depthStencilFormatInfo = GetInternalFormatInfo(depthStencilActualFormat);
649
650     if (depthStencilFormatInfo.depthBits != 0 || depthStencilFormatInfo.stencilBits != 0)
651     {
652         Renderbuffer *depthStencilBuffer = new Renderbuffer(0, depthStencil);
653
654         // Make a new attachment objects to ensure we do not double-delete
655         // See angle issue 686
656         mDepthbuffer = (depthStencilFormatInfo.depthBits != 0 ? new RenderbufferAttachment(GL_DEPTH_ATTACHMENT, depthStencilBuffer) : NULL);
657         mStencilbuffer = (depthStencilFormatInfo.stencilBits != 0 ? new RenderbufferAttachment(GL_STENCIL_ATTACHMENT, depthStencilBuffer) : NULL);
658     }
659     else
660     {
661         // This method transfers ownership, so delete the unused storage if we don't keep it.
662         SafeDelete(depthStencil);
663     }
664
665     mDrawBufferStates[0] = GL_BACK;
666     mReadBufferState = GL_BACK;
667 }
668
669 int Framebuffer::getSamples() const
670 {
671     if (completeness() == GL_FRAMEBUFFER_COMPLETE)
672     {
673         // for a complete framebuffer, all attachments must have the same sample count
674         // in this case return the first nonzero sample size
675         for (unsigned int colorAttachment = 0; colorAttachment < IMPLEMENTATION_MAX_DRAW_BUFFERS; colorAttachment++)
676         {
677             if (mColorbuffers[colorAttachment])
678             {
679                 return mColorbuffers[colorAttachment]->getSamples();
680             }
681         }
682     }
683
684     return 0;
685 }
686
687 bool Framebuffer::hasValidDepthStencil() const
688 {
689     // A valid depth-stencil attachment has the same resource bound to both the
690     // depth and stencil attachment points.
691     return (mDepthbuffer && mStencilbuffer &&
692             mDepthbuffer->type() == mStencilbuffer->type() &&
693             mDepthbuffer->id() == mStencilbuffer->id());
694 }
695
696 ColorbufferInfo Framebuffer::getColorbuffersForRender() const
697 {
698     ColorbufferInfo colorbuffersForRender;
699
700     for (size_t colorAttachment = 0; colorAttachment < IMPLEMENTATION_MAX_DRAW_BUFFERS; ++colorAttachment)
701     {
702         GLenum drawBufferState = mDrawBufferStates[colorAttachment];
703         FramebufferAttachment *colorbuffer = mColorbuffers[colorAttachment];
704
705         if (colorbuffer != NULL && drawBufferState != GL_NONE)
706         {
707             ASSERT(drawBufferState == GL_BACK || drawBufferState == (GL_COLOR_ATTACHMENT0_EXT + colorAttachment));
708             colorbuffersForRender.push_back(colorbuffer);
709         }
710         else if (!mRenderer->getWorkarounds().mrtPerfWorkaround)
711         {
712             colorbuffersForRender.push_back(NULL);
713         }
714     }
715
716     return colorbuffersForRender;
717 }
718
719 GLenum DefaultFramebuffer::completeness() const
720 {
721     // The default framebuffer *must* always be complete, though it may not be
722     // subject to the same rules as application FBOs. ie, it could have 0x0 size.
723     return GL_FRAMEBUFFER_COMPLETE;
724 }
725
726 FramebufferAttachment *DefaultFramebuffer::getAttachment(GLenum attachment) const
727 {
728     switch (attachment)
729     {
730       case GL_COLOR:
731       case GL_BACK:
732         return getColorbuffer(0);
733       case GL_DEPTH:
734         return getDepthbuffer();
735       case GL_STENCIL:
736         return getStencilbuffer();
737       case GL_DEPTH_STENCIL:
738         return getDepthStencilBuffer();
739       default:
740         UNREACHABLE();
741         return NULL;
742     }
743 }
744
745 }