blob: 947269bcccaa20e20604f596a2576305b41e9430 [file] [log] [blame]
shannon.woods@transgaming.combdf2d802013-02-28 23:16:20 +00001#include "precompiled.h"
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002//
shannon.woods%transgaming.com@gtempaccount.com3b57b4f2013-04-13 03:28:29 +00003// Copyright (c) 2002-2013 The ANGLE Project Authors. All rights reserved.
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00004// 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
daniel@transgaming.combbf56f72010-04-20 18:52:13 +000011#include "libGLESv2/Framebuffer.h"
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000012
daniel@transgaming.combbf56f72010-04-20 18:52:13 +000013#include "libGLESv2/main.h"
daniel@transgaming.com93a81472010-04-20 18:52:58 +000014#include "libGLESv2/utilities.h"
shannon.woods@transgaming.com486d9e92013-02-28 23:15:41 +000015#include "libGLESv2/Texture.h"
16#include "libGLESv2/Context.h"
17#include "libGLESv2/renderer/Renderer.h"
18#include "libGLESv2/Renderbuffer.h"
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000019
20namespace gl
21{
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +000022
daniel@transgaming.com16418b12012-11-28 19:32:22 +000023Framebuffer::Framebuffer(rx::Renderer *renderer)
24 : mRenderer(renderer)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000025{
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +000026 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
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000034 mDepthbufferType = GL_NONE;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000035 mStencilbufferType = GL_NONE;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000036}
37
38Framebuffer::~Framebuffer()
39{
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +000040 for (unsigned int colorAttachment = 0; colorAttachment < IMPLEMENTATION_MAX_DRAW_BUFFERS; colorAttachment++)
41 {
42 mColorbufferPointers[colorAttachment].set(NULL);
43 }
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +000044 mDepthbufferPointer.set(NULL);
45 mStencilbufferPointer.set(NULL);
46}
47
48Renderbuffer *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 }
apatrick@chromium.org551022e2012-01-23 19:56:54 +000061 else if (IsInternalTextureTarget(type))
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +000062 {
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +000063 buffer = context->getTexture(handle)->getRenderbuffer(type);
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +000064 }
65 else
66 {
67 UNREACHABLE();
68 }
69
70 return buffer;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000071}
72
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +000073void 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
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000080void Framebuffer::setColorbuffer(GLenum type, GLuint colorbuffer)
81{
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +000082 setColorbuffer(0, type, colorbuffer);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000083}
84
85void Framebuffer::setDepthbuffer(GLenum type, GLuint depthbuffer)
86{
daniel@transgaming.com2fa45512011-10-04 18:43:18 +000087 mDepthbufferType = (depthbuffer != 0) ? type : GL_NONE;
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +000088 mDepthbufferPointer.set(lookupRenderbuffer(type, depthbuffer));
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000089}
90
91void Framebuffer::setStencilbuffer(GLenum type, GLuint stencilbuffer)
92{
daniel@transgaming.com2fa45512011-10-04 18:43:18 +000093 mStencilbufferType = (stencilbuffer != 0) ? type : GL_NONE;
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +000094 mStencilbufferPointer.set(lookupRenderbuffer(type, stencilbuffer));
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000095}
96
97void Framebuffer::detachTexture(GLuint texture)
98{
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +000099 for (unsigned int colorAttachment = 0; colorAttachment < IMPLEMENTATION_MAX_DRAW_BUFFERS; colorAttachment++)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000100 {
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000101 if (mColorbufferPointers[colorAttachment].id() == texture && IsInternalTextureTarget(mColorbufferTypes[colorAttachment]))
102 {
103 mColorbufferTypes[colorAttachment] = GL_NONE;
104 mColorbufferPointers[colorAttachment].set(NULL);
105 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000106 }
daniel@transgaming.comfbc09532010-04-26 15:33:41 +0000107
apatrick@chromium.org551022e2012-01-23 19:56:54 +0000108 if (mDepthbufferPointer.id() == texture && IsInternalTextureTarget(mDepthbufferType))
daniel@transgaming.comfbc09532010-04-26 15:33:41 +0000109 {
110 mDepthbufferType = GL_NONE;
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000111 mDepthbufferPointer.set(NULL);
daniel@transgaming.comfbc09532010-04-26 15:33:41 +0000112 }
113
apatrick@chromium.org551022e2012-01-23 19:56:54 +0000114 if (mStencilbufferPointer.id() == texture && IsInternalTextureTarget(mStencilbufferType))
daniel@transgaming.comfbc09532010-04-26 15:33:41 +0000115 {
116 mStencilbufferType = GL_NONE;
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000117 mStencilbufferPointer.set(NULL);
daniel@transgaming.comfbc09532010-04-26 15:33:41 +0000118 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000119}
120
121void Framebuffer::detachRenderbuffer(GLuint renderbuffer)
122{
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000123 for (unsigned int colorAttachment = 0; colorAttachment < IMPLEMENTATION_MAX_DRAW_BUFFERS; colorAttachment++)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000124 {
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000125 if (mColorbufferPointers[colorAttachment].id() == renderbuffer && mColorbufferTypes[colorAttachment] == GL_RENDERBUFFER)
126 {
127 mColorbufferTypes[colorAttachment] = GL_NONE;
128 mColorbufferPointers[colorAttachment].set(NULL);
129 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000130 }
131
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000132 if (mDepthbufferPointer.id() == renderbuffer && mDepthbufferType == GL_RENDERBUFFER)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000133 {
134 mDepthbufferType = GL_NONE;
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000135 mDepthbufferPointer.set(NULL);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000136 }
137
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000138 if (mStencilbufferPointer.id() == renderbuffer && mStencilbufferType == GL_RENDERBUFFER)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000139 {
140 mStencilbufferType = GL_NONE;
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000141 mStencilbufferPointer.set(NULL);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000142 }
143}
144
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000145unsigned int Framebuffer::getRenderTargetSerial(unsigned int colorAttachment) const
daniel@transgaming.com092bd482010-05-12 03:39:36 +0000146{
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000147 ASSERT(colorAttachment < IMPLEMENTATION_MAX_DRAW_BUFFERS);
148
149 Renderbuffer *colorbuffer = mColorbufferPointers[colorAttachment].get();
daniel@transgaming.com092bd482010-05-12 03:39:36 +0000150
151 if (colorbuffer)
152 {
153 return colorbuffer->getSerial();
154 }
155
156 return 0;
157}
158
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000159unsigned int Framebuffer::getRenderTargetSerial() const
160{
161 return getRenderTargetSerial(0);
162}
163
shannon.woods%transgaming.com@gtempaccount.com3b57b4f2013-04-13 03:28:29 +0000164unsigned int Framebuffer::getDepthbufferSerial() const
daniel@transgaming.com339ae702010-05-12 03:40:20 +0000165{
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000166 Renderbuffer *depthbuffer = mDepthbufferPointer.get();
daniel@transgaming.com339ae702010-05-12 03:40:20 +0000167
168 if (depthbuffer)
169 {
170 return depthbuffer->getSerial();
171 }
172
173 return 0;
174}
175
shannon.woods%transgaming.com@gtempaccount.com3b57b4f2013-04-13 03:28:29 +0000176unsigned int Framebuffer::getStencilbufferSerial() const
daniel@transgaming.com4cbc5902010-08-24 19:20:26 +0000177{
178 Renderbuffer *stencilbuffer = mStencilbufferPointer.get();
179
180 if (stencilbuffer)
181 {
182 return stencilbuffer->getSerial();
183 }
184
185 return 0;
186}
187
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000188Renderbuffer *Framebuffer::getColorbuffer(unsigned int colorAttachment) const
189{
190 ASSERT(colorAttachment < IMPLEMENTATION_MAX_DRAW_BUFFERS);
191 return mColorbufferPointers[colorAttachment].get();
192}
193
shannon.woods%transgaming.com@gtempaccount.com3b57b4f2013-04-13 03:28:29 +0000194Renderbuffer *Framebuffer::getColorbuffer() const
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000195{
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000196 return getColorbuffer(0);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000197}
198
shannon.woods%transgaming.com@gtempaccount.com3b57b4f2013-04-13 03:28:29 +0000199Renderbuffer *Framebuffer::getDepthbuffer() const
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000200{
daniel@transgaming.comd14558a2011-11-09 17:46:18 +0000201 return mDepthbufferPointer.get();
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000202}
203
shannon.woods%transgaming.com@gtempaccount.com3b57b4f2013-04-13 03:28:29 +0000204Renderbuffer *Framebuffer::getStencilbuffer() const
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000205{
daniel@transgaming.comd14558a2011-11-09 17:46:18 +0000206 return mStencilbufferPointer.get();
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000207}
208
shannon.woods%transgaming.com@gtempaccount.com3b57b4f2013-04-13 03:28:29 +0000209Renderbuffer *Framebuffer::getDepthOrStencilbuffer() const
daniel@transgaming.comd2b47022012-11-28 19:40:10 +0000210{
211 Renderbuffer *depthstencilbuffer = mDepthbufferPointer.get();
212
213 if (!depthstencilbuffer)
214 {
215 depthstencilbuffer = mStencilbufferPointer.get();
216 }
217
218 return depthstencilbuffer;
219}
220
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000221Renderbuffer *Framebuffer::getReadColorbuffer() const
222{
223 // Will require more logic if glReadBuffers is supported
224 return mColorbufferPointers[0].get();
225}
226
227Renderbuffer *Framebuffer::getFirstColorBuffer() const
228{
229 for (unsigned int colorAttachment = 0; colorAttachment < IMPLEMENTATION_MAX_DRAW_BUFFERS; colorAttachment++)
230 {
231 if (mColorbufferTypes[colorAttachment] != GL_NONE)
232 {
233 return mColorbufferPointers[colorAttachment].get();
234 }
235 }
236
237 return NULL;
238}
239
240GLenum Framebuffer::getColorbufferType(unsigned int colorAttachment) const
241{
242 ASSERT(colorAttachment < IMPLEMENTATION_MAX_DRAW_BUFFERS);
243 return mColorbufferTypes[colorAttachment];
244}
245
shannon.woods%transgaming.com@gtempaccount.com3b57b4f2013-04-13 03:28:29 +0000246GLenum Framebuffer::getColorbufferType() const
daniel@transgaming.comc46c9c02010-04-23 18:34:55 +0000247{
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000248 return getColorbufferType(0);
daniel@transgaming.comc46c9c02010-04-23 18:34:55 +0000249}
250
shannon.woods%transgaming.com@gtempaccount.com3b57b4f2013-04-13 03:28:29 +0000251GLenum Framebuffer::getDepthbufferType() const
daniel@transgaming.comc46c9c02010-04-23 18:34:55 +0000252{
253 return mDepthbufferType;
254}
255
shannon.woods%transgaming.com@gtempaccount.com3b57b4f2013-04-13 03:28:29 +0000256GLenum Framebuffer::getStencilbufferType() const
daniel@transgaming.comc46c9c02010-04-23 18:34:55 +0000257{
258 return mStencilbufferType;
259}
260
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000261GLuint Framebuffer::getColorbufferHandle(unsigned int colorAttachment) const
262{
263 ASSERT(colorAttachment < IMPLEMENTATION_MAX_DRAW_BUFFERS);
264 return mColorbufferPointers[colorAttachment].id();
265}
266
shannon.woods%transgaming.com@gtempaccount.com3b57b4f2013-04-13 03:28:29 +0000267GLuint Framebuffer::getColorbufferHandle() const
daniel@transgaming.comc46c9c02010-04-23 18:34:55 +0000268{
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000269 return getColorbufferHandle(0);
daniel@transgaming.comc46c9c02010-04-23 18:34:55 +0000270}
271
shannon.woods%transgaming.com@gtempaccount.com3b57b4f2013-04-13 03:28:29 +0000272GLuint Framebuffer::getDepthbufferHandle() const
daniel@transgaming.comc46c9c02010-04-23 18:34:55 +0000273{
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000274 return mDepthbufferPointer.id();
daniel@transgaming.comc46c9c02010-04-23 18:34:55 +0000275}
276
shannon.woods%transgaming.com@gtempaccount.com3b57b4f2013-04-13 03:28:29 +0000277GLuint Framebuffer::getStencilbufferHandle() const
daniel@transgaming.comc46c9c02010-04-23 18:34:55 +0000278{
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000279 return mStencilbufferPointer.id();
daniel@transgaming.comc46c9c02010-04-23 18:34:55 +0000280}
281
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000282GLenum Framebuffer::getDrawBufferState(unsigned int colorAttachment) const
283{
284 return mDrawBufferStates[colorAttachment];
285}
286
287void Framebuffer::setDrawBufferState(unsigned int colorAttachment, GLenum drawBuffer)
288{
289 mDrawBufferStates[colorAttachment] = drawBuffer;
290}
291
shannon.woods%transgaming.com@gtempaccount.com3b57b4f2013-04-13 03:28:29 +0000292bool Framebuffer::hasStencil() const
daniel@transgaming.coma27ff1e2010-08-24 19:20:11 +0000293{
294 if (mStencilbufferType != GL_NONE)
295 {
shannon.woods%transgaming.com@gtempaccount.com3b57b4f2013-04-13 03:28:29 +0000296 const Renderbuffer *stencilbufferObject = getStencilbuffer();
daniel@transgaming.coma27ff1e2010-08-24 19:20:11 +0000297
298 if (stencilbufferObject)
299 {
300 return stencilbufferObject->getStencilSize() > 0;
301 }
302 }
303
304 return false;
305}
306
shannon.woods%transgaming.com@gtempaccount.com3b57b4f2013-04-13 03:28:29 +0000307GLenum Framebuffer::completeness() const
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000308{
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000309 int width = 0;
310 int height = 0;
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000311 int colorbufferSize = 0;
daniel@transgaming.com1f135d82010-08-24 19:20:36 +0000312 int samples = -1;
daniel@transgaming.com6b7c84c2012-05-31 01:14:39 +0000313 bool missingAttachment = true;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000314
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000315 for (unsigned int colorAttachment = 0; colorAttachment < IMPLEMENTATION_MAX_DRAW_BUFFERS; colorAttachment++)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000316 {
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000317 if (mColorbufferTypes[colorAttachment] != GL_NONE)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000318 {
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000319 const Renderbuffer *colorbuffer = getColorbuffer(colorAttachment);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000320
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000321 if (!colorbuffer)
daniel@transgaming.comedc19182010-10-15 17:57:55 +0000322 {
323 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
324 }
daniel@transgaming.comd885df02012-05-31 01:14:36 +0000325
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000326 if (colorbuffer->getWidth() == 0 || colorbuffer->getHeight() == 0)
daniel@transgaming.com6b7c84c2012-05-31 01:14:39 +0000327 {
328 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
329 }
daniel@transgaming.com01868132010-08-24 19:21:17 +0000330
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000331 if (mColorbufferTypes[colorAttachment] == GL_RENDERBUFFER)
332 {
333 if (!gl::IsColorRenderable(colorbuffer->getInternalFormat()))
334 {
335 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
336 }
337 }
338 else if (IsInternalTextureTarget(mColorbufferTypes[colorAttachment]))
339 {
340 GLint internalformat = colorbuffer->getInternalFormat();
341 GLenum format = gl::ExtractFormat(internalformat);
342
343 if (IsCompressed(format) ||
344 format == GL_ALPHA ||
345 format == GL_LUMINANCE ||
346 format == GL_LUMINANCE_ALPHA)
347 {
348 return GL_FRAMEBUFFER_UNSUPPORTED;
349 }
350
351 bool filtering, renderable;
352
353 if ((gl::IsFloat32Format(internalformat) && !mRenderer->getFloat32TextureSupport(&filtering, &renderable)) ||
354 (gl::IsFloat16Format(internalformat) && !mRenderer->getFloat16TextureSupport(&filtering, &renderable)))
355 {
356 return GL_FRAMEBUFFER_UNSUPPORTED;
357 }
358
359 if (gl::IsDepthTexture(internalformat) || gl::IsStencilTexture(internalformat))
360 {
361 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
362 }
363 }
364 else
365 {
366 UNREACHABLE();
367 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
368 }
369
370 if (!missingAttachment)
371 {
372 // all color attachments must have the same width and height
373 if (colorbuffer->getWidth() != width || colorbuffer->getHeight() != height)
374 {
375 return GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS;
376 }
377
378 // APPLE_framebuffer_multisample, which EXT_draw_buffers refers to, requires that
379 // all color attachments have the same number of samples for the FBO to be complete.
380 if (colorbuffer->getSamples() != samples)
381 {
382 return GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE_EXT;
383 }
384
385 // all color attachments attachments must have the same number of bitplanes
386 if (gl::ComputePixelSize(colorbuffer->getInternalFormat()) != colorbufferSize)
387 {
388 return GL_FRAMEBUFFER_UNSUPPORTED;
389 }
390
391 // D3D11 does not allow for overlapping RenderTargetViews, so ensure uniqueness
392 for (unsigned int previousColorAttachment = 0; previousColorAttachment < colorAttachment; previousColorAttachment++)
393 {
394 if (mColorbufferPointers[colorAttachment].get() == mColorbufferPointers[previousColorAttachment].get())
395 {
396 return GL_FRAMEBUFFER_UNSUPPORTED;
397 }
398 }
399 }
400 else
401 {
402 width = colorbuffer->getWidth();
403 height = colorbuffer->getHeight();
404 samples = colorbuffer->getSamples();
405 colorbufferSize = gl::ComputePixelSize(colorbuffer->getInternalFormat());
406 missingAttachment = false;
407 }
408 }
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000409 }
410
shannon.woods%transgaming.com@gtempaccount.com3b57b4f2013-04-13 03:28:29 +0000411 const Renderbuffer *depthbuffer = NULL;
412 const Renderbuffer *stencilbuffer = NULL;
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000413
414 if (mDepthbufferType != GL_NONE)
415 {
416 depthbuffer = getDepthbuffer();
417
418 if (!depthbuffer)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000419 {
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000420 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000421 }
422
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000423 if (depthbuffer->getWidth() == 0 || depthbuffer->getHeight() == 0)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000424 {
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000425 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
426 }
427
daniel@transgaming.com6b7c84c2012-05-31 01:14:39 +0000428 if (mDepthbufferType == GL_RENDERBUFFER)
429 {
430 if (!gl::IsDepthRenderable(depthbuffer->getInternalFormat()))
431 {
432 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
433 }
434 }
435 else if (IsInternalTextureTarget(mDepthbufferType))
436 {
daniel@transgaming.com8e91d252012-10-17 18:22:44 +0000437 GLint internalformat = depthbuffer->getInternalFormat();
daniel@transgaming.com6b7c84c2012-05-31 01:14:39 +0000438
439 // depth texture attachments require OES/ANGLE_depth_texture
daniel@transgaming.comea32d482012-11-28 19:33:18 +0000440 if (!mRenderer->getDepthTextureSupport())
daniel@transgaming.com6b7c84c2012-05-31 01:14:39 +0000441 {
442 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
443 }
444
daniel@transgaming.com8e91d252012-10-17 18:22:44 +0000445 if (!gl::IsDepthTexture(internalformat))
daniel@transgaming.com6b7c84c2012-05-31 01:14:39 +0000446 {
447 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
448 }
449 }
450 else
451 {
452 UNREACHABLE();
453 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
454 }
455
456 if (missingAttachment)
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000457 {
458 width = depthbuffer->getWidth();
459 height = depthbuffer->getHeight();
daniel@transgaming.com6b7c84c2012-05-31 01:14:39 +0000460 samples = depthbuffer->getSamples();
461 missingAttachment = false;
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000462 }
463 else if (width != depthbuffer->getWidth() || height != depthbuffer->getHeight())
464 {
465 return GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS;
466 }
daniel@transgaming.com1f135d82010-08-24 19:20:36 +0000467 else if (samples != depthbuffer->getSamples())
468 {
469 return GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE_ANGLE;
470 }
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000471 }
472
473 if (mStencilbufferType != GL_NONE)
474 {
475 stencilbuffer = getStencilbuffer();
476
477 if (!stencilbuffer)
478 {
479 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
480 }
481
482 if (stencilbuffer->getWidth() == 0 || stencilbuffer->getHeight() == 0)
483 {
484 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
485 }
486
daniel@transgaming.com6b7c84c2012-05-31 01:14:39 +0000487 if (mStencilbufferType == GL_RENDERBUFFER)
488 {
489 if (!gl::IsStencilRenderable(stencilbuffer->getInternalFormat()))
490 {
491 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
492 }
493 }
494 else if (IsInternalTextureTarget(mStencilbufferType))
495 {
daniel@transgaming.com8e91d252012-10-17 18:22:44 +0000496 GLint internalformat = stencilbuffer->getInternalFormat();
daniel@transgaming.com6b7c84c2012-05-31 01:14:39 +0000497
498 // texture stencil attachments come along as part
499 // of OES_packed_depth_stencil + OES/ANGLE_depth_texture
daniel@transgaming.comea32d482012-11-28 19:33:18 +0000500 if (!mRenderer->getDepthTextureSupport())
daniel@transgaming.com6b7c84c2012-05-31 01:14:39 +0000501 {
502 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
503 }
504
daniel@transgaming.com8e91d252012-10-17 18:22:44 +0000505 if (!gl::IsStencilTexture(internalformat))
daniel@transgaming.com6b7c84c2012-05-31 01:14:39 +0000506 {
507 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
508 }
509 }
510 else
511 {
512 UNREACHABLE();
513 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
514 }
515
516 if (missingAttachment)
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000517 {
518 width = stencilbuffer->getWidth();
519 height = stencilbuffer->getHeight();
daniel@transgaming.com6b7c84c2012-05-31 01:14:39 +0000520 samples = stencilbuffer->getSamples();
521 missingAttachment = false;
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000522 }
523 else if (width != stencilbuffer->getWidth() || height != stencilbuffer->getHeight())
524 {
525 return GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS;
526 }
daniel@transgaming.com1f135d82010-08-24 19:20:36 +0000527 else if (samples != stencilbuffer->getSamples())
528 {
529 return GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE_ANGLE;
530 }
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000531 }
532
daniel@transgaming.com6b7c84c2012-05-31 01:14:39 +0000533 // if we have both a depth and stencil buffer, they must refer to the same object
534 // since we only support packed_depth_stencil and not separate depth and stencil
535 if (depthbuffer && stencilbuffer && (depthbuffer != stencilbuffer))
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000536 {
daniel@transgaming.com6b7c84c2012-05-31 01:14:39 +0000537 return GL_FRAMEBUFFER_UNSUPPORTED;
538 }
539
540 // we need to have at least one attachment to be complete
541 if (missingAttachment)
542 {
543 return GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT;
daniel@transgaming.comcdacc8e2010-07-28 19:20:50 +0000544 }
545
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000546 return GL_FRAMEBUFFER_COMPLETE;
547}
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000548
daniel@transgaming.com16418b12012-11-28 19:32:22 +0000549DefaultFramebuffer::DefaultFramebuffer(rx::Renderer *renderer, Colorbuffer *colorbuffer, DepthStencilbuffer *depthStencil)
550 : Framebuffer(renderer)
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000551{
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000552 mColorbufferPointers[0].set(new Renderbuffer(mRenderer, 0, colorbuffer));
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000553
daniel@transgaming.com70062c92012-11-28 19:32:30 +0000554 Renderbuffer *depthStencilRenderbuffer = new Renderbuffer(mRenderer, 0, depthStencil);
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000555 mDepthbufferPointer.set(depthStencilRenderbuffer);
556 mStencilbufferPointer.set(depthStencilRenderbuffer);
daniel@transgaming.comd14558a2011-11-09 17:46:18 +0000557
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000558 mColorbufferTypes[0] = GL_RENDERBUFFER;
daniel@transgaming.comd14558a2011-11-09 17:46:18 +0000559 mDepthbufferType = (depthStencilRenderbuffer->getDepthSize() != 0) ? GL_RENDERBUFFER : GL_NONE;
560 mStencilbufferType = (depthStencilRenderbuffer->getStencilSize() != 0) ? GL_RENDERBUFFER : GL_NONE;
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000561
562 mDrawBufferStates[0] = GL_BACK;
563 mReadBufferState = GL_BACK;
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000564}
565
shannon.woods%transgaming.com@gtempaccount.com3b57b4f2013-04-13 03:28:29 +0000566int Framebuffer::getSamples() const
daniel@transgaming.com1f135d82010-08-24 19:20:36 +0000567{
568 if (completeness() == GL_FRAMEBUFFER_COMPLETE)
569 {
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000570 // for a complete framebuffer, all attachments must have the same sample count
571 // in this case return the first nonzero sample size
572 for (unsigned int colorAttachment = 0; colorAttachment < IMPLEMENTATION_MAX_DRAW_BUFFERS; colorAttachment++)
573 {
574 if (mColorbufferTypes[colorAttachment] != GL_NONE)
575 {
576 return getColorbuffer(colorAttachment)->getSamples();
577 }
578 }
daniel@transgaming.com1f135d82010-08-24 19:20:36 +0000579 }
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000580
581 return 0;
daniel@transgaming.com1f135d82010-08-24 19:20:36 +0000582}
583
shannon.woods%transgaming.com@gtempaccount.com3b57b4f2013-04-13 03:28:29 +0000584GLenum DefaultFramebuffer::completeness() const
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000585{
shannon.woods@transgaming.com3e3da582013-02-28 23:09:03 +0000586 // The default framebuffer *must* always be complete, though it may not be
587 // subject to the same rules as application FBOs. ie, it could have 0x0 size.
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000588 return GL_FRAMEBUFFER_COMPLETE;
589}
590
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000591}