blob: 4d0653c4952325b4c631ce62b4b534b35853b311 [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
daniel@transgaming.com16418b12012-11-28 19:32:22 +000020Framebuffer::Framebuffer(rx::Renderer *renderer)
21 : mRenderer(renderer)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000022{
23 mColorbufferType = GL_NONE;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000024 mDepthbufferType = GL_NONE;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000025 mStencilbufferType = GL_NONE;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000026}
27
28Framebuffer::~Framebuffer()
29{
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +000030 mColorbufferPointer.set(NULL);
31 mDepthbufferPointer.set(NULL);
32 mStencilbufferPointer.set(NULL);
daniel@transgaming.com68145c62012-05-31 01:14:46 +000033 mNullColorbufferPointer.set(NULL);
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +000034}
35
36Renderbuffer *Framebuffer::lookupRenderbuffer(GLenum type, GLuint handle) const
37{
38 gl::Context *context = gl::getContext();
39 Renderbuffer *buffer = NULL;
40
41 if (type == GL_NONE)
42 {
43 buffer = NULL;
44 }
45 else if (type == GL_RENDERBUFFER)
46 {
47 buffer = context->getRenderbuffer(handle);
48 }
apatrick@chromium.org551022e2012-01-23 19:56:54 +000049 else if (IsInternalTextureTarget(type))
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +000050 {
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +000051 buffer = context->getTexture(handle)->getRenderbuffer(type);
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +000052 }
53 else
54 {
55 UNREACHABLE();
56 }
57
58 return buffer;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000059}
60
61void Framebuffer::setColorbuffer(GLenum type, GLuint colorbuffer)
62{
daniel@transgaming.com2fa45512011-10-04 18:43:18 +000063 mColorbufferType = (colorbuffer != 0) ? type : GL_NONE;
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +000064 mColorbufferPointer.set(lookupRenderbuffer(type, colorbuffer));
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000065}
66
67void Framebuffer::setDepthbuffer(GLenum type, GLuint depthbuffer)
68{
daniel@transgaming.com2fa45512011-10-04 18:43:18 +000069 mDepthbufferType = (depthbuffer != 0) ? type : GL_NONE;
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +000070 mDepthbufferPointer.set(lookupRenderbuffer(type, depthbuffer));
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000071}
72
73void Framebuffer::setStencilbuffer(GLenum type, GLuint stencilbuffer)
74{
daniel@transgaming.com2fa45512011-10-04 18:43:18 +000075 mStencilbufferType = (stencilbuffer != 0) ? type : GL_NONE;
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +000076 mStencilbufferPointer.set(lookupRenderbuffer(type, stencilbuffer));
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000077}
78
79void Framebuffer::detachTexture(GLuint texture)
80{
apatrick@chromium.org551022e2012-01-23 19:56:54 +000081 if (mColorbufferPointer.id() == texture && IsInternalTextureTarget(mColorbufferType))
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000082 {
83 mColorbufferType = GL_NONE;
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +000084 mColorbufferPointer.set(NULL);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000085 }
daniel@transgaming.comfbc09532010-04-26 15:33:41 +000086
apatrick@chromium.org551022e2012-01-23 19:56:54 +000087 if (mDepthbufferPointer.id() == texture && IsInternalTextureTarget(mDepthbufferType))
daniel@transgaming.comfbc09532010-04-26 15:33:41 +000088 {
89 mDepthbufferType = GL_NONE;
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +000090 mDepthbufferPointer.set(NULL);
daniel@transgaming.comfbc09532010-04-26 15:33:41 +000091 }
92
apatrick@chromium.org551022e2012-01-23 19:56:54 +000093 if (mStencilbufferPointer.id() == texture && IsInternalTextureTarget(mStencilbufferType))
daniel@transgaming.comfbc09532010-04-26 15:33:41 +000094 {
95 mStencilbufferType = GL_NONE;
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +000096 mStencilbufferPointer.set(NULL);
daniel@transgaming.comfbc09532010-04-26 15:33:41 +000097 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000098}
99
100void Framebuffer::detachRenderbuffer(GLuint renderbuffer)
101{
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000102 if (mColorbufferPointer.id() == renderbuffer && mColorbufferType == GL_RENDERBUFFER)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000103 {
104 mColorbufferType = GL_NONE;
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000105 mColorbufferPointer.set(NULL);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000106 }
107
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000108 if (mDepthbufferPointer.id() == renderbuffer && mDepthbufferType == GL_RENDERBUFFER)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000109 {
110 mDepthbufferType = GL_NONE;
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000111 mDepthbufferPointer.set(NULL);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000112 }
113
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000114 if (mStencilbufferPointer.id() == renderbuffer && mStencilbufferType == GL_RENDERBUFFER)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000115 {
116 mStencilbufferType = GL_NONE;
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000117 mStencilbufferPointer.set(NULL);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000118 }
119}
120
daniel@transgaming.com092bd482010-05-12 03:39:36 +0000121unsigned int Framebuffer::getRenderTargetSerial()
122{
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000123 Renderbuffer *colorbuffer = mColorbufferPointer.get();
daniel@transgaming.com092bd482010-05-12 03:39:36 +0000124
125 if (colorbuffer)
126 {
127 return colorbuffer->getSerial();
128 }
129
130 return 0;
131}
132
daniel@transgaming.com63e6afe2012-05-31 01:14:42 +0000133// Increments refcount on surface.
134// caller must Release() the returned surface
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000135IDirect3DSurface9 *Framebuffer::getRenderTarget()
136{
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000137 Renderbuffer *colorbuffer = mColorbufferPointer.get();
daniel@transgaming.comfab5a1a2010-03-11 19:22:30 +0000138
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000139 if (colorbuffer)
140 {
141 return colorbuffer->getRenderTarget();
142 }
143
144 return NULL;
145}
146
daniel@transgaming.com63e6afe2012-05-31 01:14:42 +0000147// Increments refcount on surface.
148// caller must Release() the returned surface
daniel@transgaming.com4cbc5902010-08-24 19:20:26 +0000149IDirect3DSurface9 *Framebuffer::getDepthStencil()
150{
151 Renderbuffer *depthstencilbuffer = mDepthbufferPointer.get();
152
153 if (!depthstencilbuffer)
154 {
155 depthstencilbuffer = mStencilbufferPointer.get();
156 }
157
158 if (depthstencilbuffer)
159 {
160 return depthstencilbuffer->getDepthStencil();
161 }
162
163 return NULL;
164}
165
daniel@transgaming.com339ae702010-05-12 03:40:20 +0000166unsigned int Framebuffer::getDepthbufferSerial()
167{
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000168 Renderbuffer *depthbuffer = mDepthbufferPointer.get();
daniel@transgaming.com339ae702010-05-12 03:40:20 +0000169
170 if (depthbuffer)
171 {
172 return depthbuffer->getSerial();
173 }
174
175 return 0;
176}
177
daniel@transgaming.com4cbc5902010-08-24 19:20:26 +0000178unsigned int Framebuffer::getStencilbufferSerial()
179{
180 Renderbuffer *stencilbuffer = mStencilbufferPointer.get();
181
182 if (stencilbuffer)
183 {
184 return stencilbuffer->getSerial();
185 }
186
187 return 0;
188}
189
daniel@transgaming.comd14558a2011-11-09 17:46:18 +0000190Renderbuffer *Framebuffer::getColorbuffer()
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000191{
daniel@transgaming.comd14558a2011-11-09 17:46:18 +0000192 return mColorbufferPointer.get();
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000193}
194
daniel@transgaming.comd14558a2011-11-09 17:46:18 +0000195Renderbuffer *Framebuffer::getDepthbuffer()
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000196{
daniel@transgaming.comd14558a2011-11-09 17:46:18 +0000197 return mDepthbufferPointer.get();
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000198}
199
daniel@transgaming.comd14558a2011-11-09 17:46:18 +0000200Renderbuffer *Framebuffer::getStencilbuffer()
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000201{
daniel@transgaming.comd14558a2011-11-09 17:46:18 +0000202 return mStencilbufferPointer.get();
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000203}
204
daniel@transgaming.comd2b47022012-11-28 19:40:10 +0000205Renderbuffer *Framebuffer::getDepthOrStencilbuffer()
206{
207 Renderbuffer *depthstencilbuffer = mDepthbufferPointer.get();
208
209 if (!depthstencilbuffer)
210 {
211 depthstencilbuffer = mStencilbufferPointer.get();
212 }
213
214 return depthstencilbuffer;
215}
216
daniel@transgaming.com68145c62012-05-31 01:14:46 +0000217Renderbuffer *Framebuffer::getNullColorbuffer()
218{
219 Renderbuffer *nullbuffer = mNullColorbufferPointer.get();
220 Renderbuffer *depthbuffer = getDepthbuffer();
221
222 if (!depthbuffer)
223 {
224 ERR("Unexpected null depthbuffer for depth-only FBO.");
225 return NULL;
226 }
227
228 GLsizei width = depthbuffer->getWidth();
229 GLsizei height = depthbuffer->getHeight();
230
231 if (!nullbuffer ||
232 width != nullbuffer->getWidth() || height != nullbuffer->getHeight())
233 {
daniel@transgaming.com70062c92012-11-28 19:32:30 +0000234 nullbuffer = new Renderbuffer(mRenderer, 0, new Colorbuffer(mRenderer, width, height, GL_NONE, 0));
daniel@transgaming.com68145c62012-05-31 01:14:46 +0000235 mNullColorbufferPointer.set(nullbuffer);
236 }
237
238 return nullbuffer;
239}
240
daniel@transgaming.comc46c9c02010-04-23 18:34:55 +0000241GLenum Framebuffer::getColorbufferType()
242{
243 return mColorbufferType;
244}
245
246GLenum Framebuffer::getDepthbufferType()
247{
248 return mDepthbufferType;
249}
250
251GLenum Framebuffer::getStencilbufferType()
252{
253 return mStencilbufferType;
254}
255
256GLuint Framebuffer::getColorbufferHandle()
257{
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000258 return mColorbufferPointer.id();
daniel@transgaming.comc46c9c02010-04-23 18:34:55 +0000259}
260
261GLuint Framebuffer::getDepthbufferHandle()
262{
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000263 return mDepthbufferPointer.id();
daniel@transgaming.comc46c9c02010-04-23 18:34:55 +0000264}
265
266GLuint Framebuffer::getStencilbufferHandle()
267{
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000268 return mStencilbufferPointer.id();
daniel@transgaming.comc46c9c02010-04-23 18:34:55 +0000269}
270
daniel@transgaming.coma27ff1e2010-08-24 19:20:11 +0000271bool Framebuffer::hasStencil()
272{
273 if (mStencilbufferType != GL_NONE)
274 {
daniel@transgaming.comd14558a2011-11-09 17:46:18 +0000275 Renderbuffer *stencilbufferObject = getStencilbuffer();
daniel@transgaming.coma27ff1e2010-08-24 19:20:11 +0000276
277 if (stencilbufferObject)
278 {
279 return stencilbufferObject->getStencilSize() > 0;
280 }
281 }
282
283 return false;
284}
285
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000286GLenum Framebuffer::completeness()
287{
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000288 int width = 0;
289 int height = 0;
daniel@transgaming.com1f135d82010-08-24 19:20:36 +0000290 int samples = -1;
daniel@transgaming.com6b7c84c2012-05-31 01:14:39 +0000291 bool missingAttachment = true;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000292
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000293 if (mColorbufferType != GL_NONE)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000294 {
daniel@transgaming.comd14558a2011-11-09 17:46:18 +0000295 Renderbuffer *colorbuffer = getColorbuffer();
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000296
297 if (!colorbuffer)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000298 {
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000299 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000300 }
301
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000302 if (colorbuffer->getWidth() == 0 || colorbuffer->getHeight() == 0)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000303 {
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000304 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000305 }
306
daniel@transgaming.comedc19182010-10-15 17:57:55 +0000307 if (mColorbufferType == GL_RENDERBUFFER)
308 {
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +0000309 if (!gl::IsColorRenderable(colorbuffer->getInternalFormat()))
daniel@transgaming.comedc19182010-10-15 17:57:55 +0000310 {
311 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
312 }
313 }
apatrick@chromium.org551022e2012-01-23 19:56:54 +0000314 else if (IsInternalTextureTarget(mColorbufferType))
daniel@transgaming.com01868132010-08-24 19:21:17 +0000315 {
daniel@transgaming.com6452adf2012-10-17 18:22:35 +0000316 GLint internalformat = colorbuffer->getInternalFormat();
317 GLenum format = gl::ExtractFormat(internalformat);
daniel@transgaming.comd885df02012-05-31 01:14:36 +0000318
daniel@transgaming.com6452adf2012-10-17 18:22:35 +0000319 if (IsCompressed(format) ||
320 format == GL_ALPHA ||
321 format == GL_LUMINANCE ||
322 format == GL_LUMINANCE_ALPHA)
daniel@transgaming.com01868132010-08-24 19:21:17 +0000323 {
324 return GL_FRAMEBUFFER_UNSUPPORTED;
325 }
daniel@transgaming.com1297d922010-09-01 15:47:47 +0000326
daniel@transgaming.comea32d482012-11-28 19:33:18 +0000327 bool filtering, renderable;
328
329 if ((gl::IsFloat32Format(internalformat) && !mRenderer->getFloat32TextureSupport(&filtering, &renderable)) ||
330 (gl::IsFloat16Format(internalformat) && !mRenderer->getFloat16TextureSupport(&filtering, &renderable)))
daniel@transgaming.comb6b2e672010-10-15 17:57:47 +0000331 {
332 return GL_FRAMEBUFFER_UNSUPPORTED;
333 }
daniel@transgaming.com6b7c84c2012-05-31 01:14:39 +0000334
daniel@transgaming.com8e91d252012-10-17 18:22:44 +0000335 if (gl::IsDepthTexture(internalformat) || gl::IsStencilTexture(internalformat))
daniel@transgaming.com6b7c84c2012-05-31 01:14:39 +0000336 {
337 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
338 }
daniel@transgaming.com01868132010-08-24 19:21:17 +0000339 }
daniel@transgaming.comd885df02012-05-31 01:14:36 +0000340 else
341 {
342 UNREACHABLE();
343 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
344 }
daniel@transgaming.com01868132010-08-24 19:21:17 +0000345
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000346 width = colorbuffer->getWidth();
347 height = colorbuffer->getHeight();
daniel@transgaming.com1f135d82010-08-24 19:20:36 +0000348 samples = colorbuffer->getSamples();
daniel@transgaming.com6b7c84c2012-05-31 01:14:39 +0000349 missingAttachment = false;
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000350 }
351
daniel@transgaming.comd14558a2011-11-09 17:46:18 +0000352 Renderbuffer *depthbuffer = NULL;
353 Renderbuffer *stencilbuffer = NULL;
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000354
355 if (mDepthbufferType != GL_NONE)
356 {
357 depthbuffer = getDepthbuffer();
358
359 if (!depthbuffer)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000360 {
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000361 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000362 }
363
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000364 if (depthbuffer->getWidth() == 0 || depthbuffer->getHeight() == 0)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000365 {
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000366 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
367 }
368
daniel@transgaming.com6b7c84c2012-05-31 01:14:39 +0000369 if (mDepthbufferType == GL_RENDERBUFFER)
370 {
371 if (!gl::IsDepthRenderable(depthbuffer->getInternalFormat()))
372 {
373 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
374 }
375 }
376 else if (IsInternalTextureTarget(mDepthbufferType))
377 {
daniel@transgaming.com8e91d252012-10-17 18:22:44 +0000378 GLint internalformat = depthbuffer->getInternalFormat();
daniel@transgaming.com6b7c84c2012-05-31 01:14:39 +0000379
380 // depth texture attachments require OES/ANGLE_depth_texture
daniel@transgaming.comea32d482012-11-28 19:33:18 +0000381 if (!mRenderer->getDepthTextureSupport())
daniel@transgaming.com6b7c84c2012-05-31 01:14:39 +0000382 {
383 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
384 }
385
daniel@transgaming.com8e91d252012-10-17 18:22:44 +0000386 if (!gl::IsDepthTexture(internalformat))
daniel@transgaming.com6b7c84c2012-05-31 01:14:39 +0000387 {
388 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
389 }
390 }
391 else
392 {
393 UNREACHABLE();
394 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
395 }
396
397 if (missingAttachment)
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000398 {
399 width = depthbuffer->getWidth();
400 height = depthbuffer->getHeight();
daniel@transgaming.com6b7c84c2012-05-31 01:14:39 +0000401 samples = depthbuffer->getSamples();
402 missingAttachment = false;
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000403 }
404 else if (width != depthbuffer->getWidth() || height != depthbuffer->getHeight())
405 {
406 return GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS;
407 }
daniel@transgaming.com1f135d82010-08-24 19:20:36 +0000408 else if (samples != depthbuffer->getSamples())
409 {
410 return GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE_ANGLE;
411 }
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000412 }
413
414 if (mStencilbufferType != GL_NONE)
415 {
416 stencilbuffer = getStencilbuffer();
417
418 if (!stencilbuffer)
419 {
420 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
421 }
422
423 if (stencilbuffer->getWidth() == 0 || stencilbuffer->getHeight() == 0)
424 {
425 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
426 }
427
daniel@transgaming.com6b7c84c2012-05-31 01:14:39 +0000428 if (mStencilbufferType == GL_RENDERBUFFER)
429 {
430 if (!gl::IsStencilRenderable(stencilbuffer->getInternalFormat()))
431 {
432 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
433 }
434 }
435 else if (IsInternalTextureTarget(mStencilbufferType))
436 {
daniel@transgaming.com8e91d252012-10-17 18:22:44 +0000437 GLint internalformat = stencilbuffer->getInternalFormat();
daniel@transgaming.com6b7c84c2012-05-31 01:14:39 +0000438
439 // texture stencil attachments come along as part
440 // of OES_packed_depth_stencil + OES/ANGLE_depth_texture
daniel@transgaming.comea32d482012-11-28 19:33:18 +0000441 if (!mRenderer->getDepthTextureSupport())
daniel@transgaming.com6b7c84c2012-05-31 01:14:39 +0000442 {
443 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
444 }
445
daniel@transgaming.com8e91d252012-10-17 18:22:44 +0000446 if (!gl::IsStencilTexture(internalformat))
daniel@transgaming.com6b7c84c2012-05-31 01:14:39 +0000447 {
448 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
449 }
450 }
451 else
452 {
453 UNREACHABLE();
454 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
455 }
456
457 if (missingAttachment)
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000458 {
459 width = stencilbuffer->getWidth();
460 height = stencilbuffer->getHeight();
daniel@transgaming.com6b7c84c2012-05-31 01:14:39 +0000461 samples = stencilbuffer->getSamples();
462 missingAttachment = false;
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000463 }
464 else if (width != stencilbuffer->getWidth() || height != stencilbuffer->getHeight())
465 {
466 return GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS;
467 }
daniel@transgaming.com1f135d82010-08-24 19:20:36 +0000468 else if (samples != stencilbuffer->getSamples())
469 {
470 return GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE_ANGLE;
471 }
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000472 }
473
daniel@transgaming.com6b7c84c2012-05-31 01:14:39 +0000474 // if we have both a depth and stencil buffer, they must refer to the same object
475 // since we only support packed_depth_stencil and not separate depth and stencil
476 if (depthbuffer && stencilbuffer && (depthbuffer != stencilbuffer))
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000477 {
daniel@transgaming.com6b7c84c2012-05-31 01:14:39 +0000478 return GL_FRAMEBUFFER_UNSUPPORTED;
479 }
480
481 // we need to have at least one attachment to be complete
482 if (missingAttachment)
483 {
484 return GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT;
daniel@transgaming.comcdacc8e2010-07-28 19:20:50 +0000485 }
486
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000487 return GL_FRAMEBUFFER_COMPLETE;
488}
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000489
daniel@transgaming.com16418b12012-11-28 19:32:22 +0000490DefaultFramebuffer::DefaultFramebuffer(rx::Renderer *renderer, Colorbuffer *colorbuffer, DepthStencilbuffer *depthStencil)
491 : Framebuffer(renderer)
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000492{
daniel@transgaming.com70062c92012-11-28 19:32:30 +0000493 mColorbufferPointer.set(new Renderbuffer(mRenderer, 0, colorbuffer));
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000494
daniel@transgaming.com70062c92012-11-28 19:32:30 +0000495 Renderbuffer *depthStencilRenderbuffer = new Renderbuffer(mRenderer, 0, depthStencil);
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000496 mDepthbufferPointer.set(depthStencilRenderbuffer);
497 mStencilbufferPointer.set(depthStencilRenderbuffer);
daniel@transgaming.comd14558a2011-11-09 17:46:18 +0000498
499 mColorbufferType = GL_RENDERBUFFER;
500 mDepthbufferType = (depthStencilRenderbuffer->getDepthSize() != 0) ? GL_RENDERBUFFER : GL_NONE;
501 mStencilbufferType = (depthStencilRenderbuffer->getStencilSize() != 0) ? GL_RENDERBUFFER : GL_NONE;
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000502}
503
daniel@transgaming.com1f135d82010-08-24 19:20:36 +0000504int Framebuffer::getSamples()
505{
506 if (completeness() == GL_FRAMEBUFFER_COMPLETE)
507 {
508 return getColorbuffer()->getSamples();
509 }
510 else
511 {
512 return 0;
513 }
514}
515
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000516GLenum DefaultFramebuffer::completeness()
517{
daniel@transgaming.com73a5db62010-10-15 17:58:13 +0000518 // The default framebuffer should always be complete
519 ASSERT(Framebuffer::completeness() == GL_FRAMEBUFFER_COMPLETE);
520
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000521 return GL_FRAMEBUFFER_COMPLETE;
522}
523
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000524}