blob: dcd8261ce3a0ee41b2951c30978ee551537c78d8 [file] [log] [blame]
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001//
daniel@transgaming.com911cd6d2012-06-01 01:45:20 +00002// Copyright (c) 2002-2012 The ANGLE Project Authors. All rights reserved.
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00003// 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
daniel@transgaming.combbf56f72010-04-20 18:52:13 +000010#include "libGLESv2/Framebuffer.h"
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000011
daniel@transgaming.combbf56f72010-04-20 18:52:13 +000012#include "libGLESv2/main.h"
13#include "libGLESv2/Renderbuffer.h"
14#include "libGLESv2/Texture.h"
daniel@transgaming.com93a81472010-04-20 18:52:58 +000015#include "libGLESv2/utilities.h"
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000016
17namespace gl
18{
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +000019
apatrick@chromium.orgff8bdfb2010-09-15 17:27:49 +000020Framebuffer::Framebuffer()
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000021{
22 mColorbufferType = GL_NONE;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000023 mDepthbufferType = GL_NONE;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000024 mStencilbufferType = GL_NONE;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000025}
26
27Framebuffer::~Framebuffer()
28{
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +000029 mColorbufferPointer.set(NULL);
30 mDepthbufferPointer.set(NULL);
31 mStencilbufferPointer.set(NULL);
daniel@transgaming.com68145c62012-05-31 01:14:46 +000032 mNullColorbufferPointer.set(NULL);
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +000033}
34
35Renderbuffer *Framebuffer::lookupRenderbuffer(GLenum type, GLuint handle) const
36{
37 gl::Context *context = gl::getContext();
38 Renderbuffer *buffer = NULL;
39
40 if (type == GL_NONE)
41 {
42 buffer = NULL;
43 }
44 else if (type == GL_RENDERBUFFER)
45 {
46 buffer = context->getRenderbuffer(handle);
47 }
apatrick@chromium.org551022e2012-01-23 19:56:54 +000048 else if (IsInternalTextureTarget(type))
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +000049 {
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +000050 buffer = context->getTexture(handle)->getRenderbuffer(type);
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +000051 }
52 else
53 {
54 UNREACHABLE();
55 }
56
57 return buffer;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000058}
59
60void Framebuffer::setColorbuffer(GLenum type, GLuint colorbuffer)
61{
daniel@transgaming.com2fa45512011-10-04 18:43:18 +000062 mColorbufferType = (colorbuffer != 0) ? type : GL_NONE;
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +000063 mColorbufferPointer.set(lookupRenderbuffer(type, colorbuffer));
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000064}
65
66void Framebuffer::setDepthbuffer(GLenum type, GLuint depthbuffer)
67{
daniel@transgaming.com2fa45512011-10-04 18:43:18 +000068 mDepthbufferType = (depthbuffer != 0) ? type : GL_NONE;
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +000069 mDepthbufferPointer.set(lookupRenderbuffer(type, depthbuffer));
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000070}
71
72void Framebuffer::setStencilbuffer(GLenum type, GLuint stencilbuffer)
73{
daniel@transgaming.com2fa45512011-10-04 18:43:18 +000074 mStencilbufferType = (stencilbuffer != 0) ? type : GL_NONE;
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +000075 mStencilbufferPointer.set(lookupRenderbuffer(type, stencilbuffer));
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000076}
77
78void Framebuffer::detachTexture(GLuint texture)
79{
apatrick@chromium.org551022e2012-01-23 19:56:54 +000080 if (mColorbufferPointer.id() == texture && IsInternalTextureTarget(mColorbufferType))
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000081 {
82 mColorbufferType = GL_NONE;
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +000083 mColorbufferPointer.set(NULL);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000084 }
daniel@transgaming.comfbc09532010-04-26 15:33:41 +000085
apatrick@chromium.org551022e2012-01-23 19:56:54 +000086 if (mDepthbufferPointer.id() == texture && IsInternalTextureTarget(mDepthbufferType))
daniel@transgaming.comfbc09532010-04-26 15:33:41 +000087 {
88 mDepthbufferType = GL_NONE;
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +000089 mDepthbufferPointer.set(NULL);
daniel@transgaming.comfbc09532010-04-26 15:33:41 +000090 }
91
apatrick@chromium.org551022e2012-01-23 19:56:54 +000092 if (mStencilbufferPointer.id() == texture && IsInternalTextureTarget(mStencilbufferType))
daniel@transgaming.comfbc09532010-04-26 15:33:41 +000093 {
94 mStencilbufferType = GL_NONE;
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +000095 mStencilbufferPointer.set(NULL);
daniel@transgaming.comfbc09532010-04-26 15:33:41 +000096 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000097}
98
99void Framebuffer::detachRenderbuffer(GLuint renderbuffer)
100{
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000101 if (mColorbufferPointer.id() == renderbuffer && mColorbufferType == GL_RENDERBUFFER)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000102 {
103 mColorbufferType = GL_NONE;
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000104 mColorbufferPointer.set(NULL);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000105 }
106
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000107 if (mDepthbufferPointer.id() == renderbuffer && mDepthbufferType == GL_RENDERBUFFER)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000108 {
109 mDepthbufferType = GL_NONE;
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000110 mDepthbufferPointer.set(NULL);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000111 }
112
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000113 if (mStencilbufferPointer.id() == renderbuffer && mStencilbufferType == GL_RENDERBUFFER)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000114 {
115 mStencilbufferType = GL_NONE;
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000116 mStencilbufferPointer.set(NULL);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000117 }
118}
119
daniel@transgaming.com092bd482010-05-12 03:39:36 +0000120unsigned int Framebuffer::getRenderTargetSerial()
121{
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000122 Renderbuffer *colorbuffer = mColorbufferPointer.get();
daniel@transgaming.com092bd482010-05-12 03:39:36 +0000123
124 if (colorbuffer)
125 {
126 return colorbuffer->getSerial();
127 }
128
129 return 0;
130}
131
daniel@transgaming.com63e6afe2012-05-31 01:14:42 +0000132// Increments refcount on surface.
133// caller must Release() the returned surface
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000134IDirect3DSurface9 *Framebuffer::getRenderTarget()
135{
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000136 Renderbuffer *colorbuffer = mColorbufferPointer.get();
daniel@transgaming.comfab5a1a2010-03-11 19:22:30 +0000137
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000138 if (colorbuffer)
139 {
140 return colorbuffer->getRenderTarget();
141 }
142
143 return NULL;
144}
145
daniel@transgaming.com63e6afe2012-05-31 01:14:42 +0000146// Increments refcount on surface.
147// caller must Release() the returned surface
daniel@transgaming.com4cbc5902010-08-24 19:20:26 +0000148IDirect3DSurface9 *Framebuffer::getDepthStencil()
149{
150 Renderbuffer *depthstencilbuffer = mDepthbufferPointer.get();
151
152 if (!depthstencilbuffer)
153 {
154 depthstencilbuffer = mStencilbufferPointer.get();
155 }
156
157 if (depthstencilbuffer)
158 {
159 return depthstencilbuffer->getDepthStencil();
160 }
161
162 return NULL;
163}
164
daniel@transgaming.com339ae702010-05-12 03:40:20 +0000165unsigned int Framebuffer::getDepthbufferSerial()
166{
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000167 Renderbuffer *depthbuffer = mDepthbufferPointer.get();
daniel@transgaming.com339ae702010-05-12 03:40:20 +0000168
169 if (depthbuffer)
170 {
171 return depthbuffer->getSerial();
172 }
173
174 return 0;
175}
176
daniel@transgaming.com4cbc5902010-08-24 19:20:26 +0000177unsigned int Framebuffer::getStencilbufferSerial()
178{
179 Renderbuffer *stencilbuffer = mStencilbufferPointer.get();
180
181 if (stencilbuffer)
182 {
183 return stencilbuffer->getSerial();
184 }
185
186 return 0;
187}
188
daniel@transgaming.comd14558a2011-11-09 17:46:18 +0000189Renderbuffer *Framebuffer::getColorbuffer()
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000190{
daniel@transgaming.comd14558a2011-11-09 17:46:18 +0000191 return mColorbufferPointer.get();
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000192}
193
daniel@transgaming.comd14558a2011-11-09 17:46:18 +0000194Renderbuffer *Framebuffer::getDepthbuffer()
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000195{
daniel@transgaming.comd14558a2011-11-09 17:46:18 +0000196 return mDepthbufferPointer.get();
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000197}
198
daniel@transgaming.comd14558a2011-11-09 17:46:18 +0000199Renderbuffer *Framebuffer::getStencilbuffer()
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000200{
daniel@transgaming.comd14558a2011-11-09 17:46:18 +0000201 return mStencilbufferPointer.get();
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000202}
203
daniel@transgaming.com68145c62012-05-31 01:14:46 +0000204Renderbuffer *Framebuffer::getNullColorbuffer()
205{
206 Renderbuffer *nullbuffer = mNullColorbufferPointer.get();
207 Renderbuffer *depthbuffer = getDepthbuffer();
208
209 if (!depthbuffer)
210 {
211 ERR("Unexpected null depthbuffer for depth-only FBO.");
212 return NULL;
213 }
214
215 GLsizei width = depthbuffer->getWidth();
216 GLsizei height = depthbuffer->getHeight();
217
218 if (!nullbuffer ||
219 width != nullbuffer->getWidth() || height != nullbuffer->getHeight())
220 {
221 nullbuffer = new Renderbuffer(0, new Colorbuffer(width, height, GL_NONE, 0));
222 mNullColorbufferPointer.set(nullbuffer);
223 }
224
225 return nullbuffer;
226}
227
daniel@transgaming.comc46c9c02010-04-23 18:34:55 +0000228GLenum Framebuffer::getColorbufferType()
229{
230 return mColorbufferType;
231}
232
233GLenum Framebuffer::getDepthbufferType()
234{
235 return mDepthbufferType;
236}
237
238GLenum Framebuffer::getStencilbufferType()
239{
240 return mStencilbufferType;
241}
242
243GLuint Framebuffer::getColorbufferHandle()
244{
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000245 return mColorbufferPointer.id();
daniel@transgaming.comc46c9c02010-04-23 18:34:55 +0000246}
247
248GLuint Framebuffer::getDepthbufferHandle()
249{
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000250 return mDepthbufferPointer.id();
daniel@transgaming.comc46c9c02010-04-23 18:34:55 +0000251}
252
253GLuint Framebuffer::getStencilbufferHandle()
254{
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000255 return mStencilbufferPointer.id();
daniel@transgaming.comc46c9c02010-04-23 18:34:55 +0000256}
257
daniel@transgaming.coma27ff1e2010-08-24 19:20:11 +0000258bool Framebuffer::hasStencil()
259{
260 if (mStencilbufferType != GL_NONE)
261 {
daniel@transgaming.comd14558a2011-11-09 17:46:18 +0000262 Renderbuffer *stencilbufferObject = getStencilbuffer();
daniel@transgaming.coma27ff1e2010-08-24 19:20:11 +0000263
264 if (stencilbufferObject)
265 {
266 return stencilbufferObject->getStencilSize() > 0;
267 }
268 }
269
270 return false;
271}
272
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000273GLenum Framebuffer::completeness()
274{
daniel@transgaming.comd885df02012-05-31 01:14:36 +0000275 gl::Context *context = gl::getContext();
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000276 int width = 0;
277 int height = 0;
daniel@transgaming.com1f135d82010-08-24 19:20:36 +0000278 int samples = -1;
daniel@transgaming.com6b7c84c2012-05-31 01:14:39 +0000279 bool missingAttachment = true;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000280
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000281 if (mColorbufferType != GL_NONE)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000282 {
daniel@transgaming.comd14558a2011-11-09 17:46:18 +0000283 Renderbuffer *colorbuffer = getColorbuffer();
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000284
285 if (!colorbuffer)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000286 {
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000287 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000288 }
289
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000290 if (colorbuffer->getWidth() == 0 || colorbuffer->getHeight() == 0)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000291 {
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000292 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000293 }
294
daniel@transgaming.comedc19182010-10-15 17:57:55 +0000295 if (mColorbufferType == GL_RENDERBUFFER)
296 {
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +0000297 if (!gl::IsColorRenderable(colorbuffer->getInternalFormat()))
daniel@transgaming.comedc19182010-10-15 17:57:55 +0000298 {
299 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
300 }
301 }
apatrick@chromium.org551022e2012-01-23 19:56:54 +0000302 else if (IsInternalTextureTarget(mColorbufferType))
daniel@transgaming.com01868132010-08-24 19:21:17 +0000303 {
daniel@transgaming.comd885df02012-05-31 01:14:36 +0000304 GLenum internalformat = colorbuffer->getInternalFormat();
305 D3DFORMAT d3dformat = colorbuffer->getD3DFormat();
306
307 if (IsCompressed(internalformat) ||
daniel@transgaming.com911cd6d2012-06-01 01:45:20 +0000308 internalformat == GL_ALPHA ||
daniel@transgaming.comd885df02012-05-31 01:14:36 +0000309 internalformat == GL_LUMINANCE ||
310 internalformat == GL_LUMINANCE_ALPHA)
daniel@transgaming.com01868132010-08-24 19:21:17 +0000311 {
312 return GL_FRAMEBUFFER_UNSUPPORTED;
313 }
daniel@transgaming.com1297d922010-09-01 15:47:47 +0000314
daniel@transgaming.comd885df02012-05-31 01:14:36 +0000315 if ((dx2es::IsFloat32Format(d3dformat) && !context->supportsFloat32RenderableTextures()) ||
316 (dx2es::IsFloat16Format(d3dformat) && !context->supportsFloat16RenderableTextures()))
daniel@transgaming.comb6b2e672010-10-15 17:57:47 +0000317 {
318 return GL_FRAMEBUFFER_UNSUPPORTED;
319 }
daniel@transgaming.com6b7c84c2012-05-31 01:14:39 +0000320
321 if (dx2es::IsDepthFormat(d3dformat) || dx2es::IsStencilFormat(d3dformat))
322 {
323 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
324 }
daniel@transgaming.com01868132010-08-24 19:21:17 +0000325 }
daniel@transgaming.comd885df02012-05-31 01:14:36 +0000326 else
327 {
328 UNREACHABLE();
329 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
330 }
daniel@transgaming.com01868132010-08-24 19:21:17 +0000331
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000332 width = colorbuffer->getWidth();
333 height = colorbuffer->getHeight();
daniel@transgaming.com1f135d82010-08-24 19:20:36 +0000334 samples = colorbuffer->getSamples();
daniel@transgaming.com6b7c84c2012-05-31 01:14:39 +0000335 missingAttachment = false;
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000336 }
337
daniel@transgaming.comd14558a2011-11-09 17:46:18 +0000338 Renderbuffer *depthbuffer = NULL;
339 Renderbuffer *stencilbuffer = NULL;
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000340
341 if (mDepthbufferType != GL_NONE)
342 {
343 depthbuffer = getDepthbuffer();
344
345 if (!depthbuffer)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000346 {
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000347 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000348 }
349
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000350 if (depthbuffer->getWidth() == 0 || depthbuffer->getHeight() == 0)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000351 {
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000352 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
353 }
354
daniel@transgaming.com6b7c84c2012-05-31 01:14:39 +0000355 if (mDepthbufferType == GL_RENDERBUFFER)
356 {
357 if (!gl::IsDepthRenderable(depthbuffer->getInternalFormat()))
358 {
359 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
360 }
361 }
362 else if (IsInternalTextureTarget(mDepthbufferType))
363 {
364 D3DFORMAT d3dformat = depthbuffer->getD3DFormat();
365
366 // depth texture attachments require OES/ANGLE_depth_texture
367 if (!context->supportsDepthTextures())
368 {
369 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
370 }
371
372 if (!dx2es::IsDepthFormat(d3dformat))
373 {
374 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
375 }
376 }
377 else
378 {
379 UNREACHABLE();
380 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
381 }
382
383 if (missingAttachment)
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000384 {
385 width = depthbuffer->getWidth();
386 height = depthbuffer->getHeight();
daniel@transgaming.com6b7c84c2012-05-31 01:14:39 +0000387 samples = depthbuffer->getSamples();
388 missingAttachment = false;
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000389 }
390 else if (width != depthbuffer->getWidth() || height != depthbuffer->getHeight())
391 {
392 return GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS;
393 }
daniel@transgaming.com1f135d82010-08-24 19:20:36 +0000394 else if (samples != depthbuffer->getSamples())
395 {
396 return GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE_ANGLE;
397 }
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000398 }
399
400 if (mStencilbufferType != GL_NONE)
401 {
402 stencilbuffer = getStencilbuffer();
403
404 if (!stencilbuffer)
405 {
406 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
407 }
408
409 if (stencilbuffer->getWidth() == 0 || stencilbuffer->getHeight() == 0)
410 {
411 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
412 }
413
daniel@transgaming.com6b7c84c2012-05-31 01:14:39 +0000414 if (mStencilbufferType == GL_RENDERBUFFER)
415 {
416 if (!gl::IsStencilRenderable(stencilbuffer->getInternalFormat()))
417 {
418 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
419 }
420 }
421 else if (IsInternalTextureTarget(mStencilbufferType))
422 {
423 D3DFORMAT d3dformat = stencilbuffer->getD3DFormat();
424
425 // texture stencil attachments come along as part
426 // of OES_packed_depth_stencil + OES/ANGLE_depth_texture
427 if (!context->supportsDepthTextures())
428 {
429 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
430 }
431
432 if (!dx2es::IsStencilFormat(d3dformat))
433 {
434 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
435 }
436 }
437 else
438 {
439 UNREACHABLE();
440 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
441 }
442
443 if (missingAttachment)
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000444 {
445 width = stencilbuffer->getWidth();
446 height = stencilbuffer->getHeight();
daniel@transgaming.com6b7c84c2012-05-31 01:14:39 +0000447 samples = stencilbuffer->getSamples();
448 missingAttachment = false;
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000449 }
450 else if (width != stencilbuffer->getWidth() || height != stencilbuffer->getHeight())
451 {
452 return GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS;
453 }
daniel@transgaming.com1f135d82010-08-24 19:20:36 +0000454 else if (samples != stencilbuffer->getSamples())
455 {
456 return GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE_ANGLE;
457 }
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000458 }
459
daniel@transgaming.com6b7c84c2012-05-31 01:14:39 +0000460 // if we have both a depth and stencil buffer, they must refer to the same object
461 // since we only support packed_depth_stencil and not separate depth and stencil
462 if (depthbuffer && stencilbuffer && (depthbuffer != stencilbuffer))
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000463 {
daniel@transgaming.com6b7c84c2012-05-31 01:14:39 +0000464 return GL_FRAMEBUFFER_UNSUPPORTED;
465 }
466
467 // we need to have at least one attachment to be complete
468 if (missingAttachment)
469 {
470 return GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT;
daniel@transgaming.comcdacc8e2010-07-28 19:20:50 +0000471 }
472
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000473 return GL_FRAMEBUFFER_COMPLETE;
474}
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000475
daniel@transgaming.comd14558a2011-11-09 17:46:18 +0000476DefaultFramebuffer::DefaultFramebuffer(Colorbuffer *colorbuffer, DepthStencilbuffer *depthStencil)
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000477{
daniel@transgaming.comd14558a2011-11-09 17:46:18 +0000478 mColorbufferPointer.set(new Renderbuffer(0, colorbuffer));
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000479
480 Renderbuffer *depthStencilRenderbuffer = new Renderbuffer(0, depthStencil);
481 mDepthbufferPointer.set(depthStencilRenderbuffer);
482 mStencilbufferPointer.set(depthStencilRenderbuffer);
daniel@transgaming.comd14558a2011-11-09 17:46:18 +0000483
484 mColorbufferType = GL_RENDERBUFFER;
485 mDepthbufferType = (depthStencilRenderbuffer->getDepthSize() != 0) ? GL_RENDERBUFFER : GL_NONE;
486 mStencilbufferType = (depthStencilRenderbuffer->getStencilSize() != 0) ? GL_RENDERBUFFER : GL_NONE;
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000487}
488
daniel@transgaming.com1f135d82010-08-24 19:20:36 +0000489int Framebuffer::getSamples()
490{
491 if (completeness() == GL_FRAMEBUFFER_COMPLETE)
492 {
493 return getColorbuffer()->getSamples();
494 }
495 else
496 {
497 return 0;
498 }
499}
500
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000501GLenum DefaultFramebuffer::completeness()
502{
daniel@transgaming.com73a5db62010-10-15 17:58:13 +0000503 // The default framebuffer should always be complete
504 ASSERT(Framebuffer::completeness() == GL_FRAMEBUFFER_COMPLETE);
505
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000506 return GL_FRAMEBUFFER_COMPLETE;
507}
508
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000509}