blob: 6b5c9aa06ab69c179f2226c0e2b3f4aa7421a4eb [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::setDepthbuffer(GLenum type, GLuint depthbuffer)
81{
daniel@transgaming.com2fa45512011-10-04 18:43:18 +000082 mDepthbufferType = (depthbuffer != 0) ? type : GL_NONE;
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +000083 mDepthbufferPointer.set(lookupRenderbuffer(type, depthbuffer));
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000084}
85
86void Framebuffer::setStencilbuffer(GLenum type, GLuint stencilbuffer)
87{
daniel@transgaming.com2fa45512011-10-04 18:43:18 +000088 mStencilbufferType = (stencilbuffer != 0) ? type : GL_NONE;
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +000089 mStencilbufferPointer.set(lookupRenderbuffer(type, stencilbuffer));
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000090}
91
92void Framebuffer::detachTexture(GLuint texture)
93{
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +000094 for (unsigned int colorAttachment = 0; colorAttachment < IMPLEMENTATION_MAX_DRAW_BUFFERS; colorAttachment++)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000095 {
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +000096 if (mColorbufferPointers[colorAttachment].id() == texture && IsInternalTextureTarget(mColorbufferTypes[colorAttachment]))
97 {
98 mColorbufferTypes[colorAttachment] = GL_NONE;
99 mColorbufferPointers[colorAttachment].set(NULL);
100 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000101 }
daniel@transgaming.comfbc09532010-04-26 15:33:41 +0000102
apatrick@chromium.org551022e2012-01-23 19:56:54 +0000103 if (mDepthbufferPointer.id() == texture && IsInternalTextureTarget(mDepthbufferType))
daniel@transgaming.comfbc09532010-04-26 15:33:41 +0000104 {
105 mDepthbufferType = GL_NONE;
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000106 mDepthbufferPointer.set(NULL);
daniel@transgaming.comfbc09532010-04-26 15:33:41 +0000107 }
108
apatrick@chromium.org551022e2012-01-23 19:56:54 +0000109 if (mStencilbufferPointer.id() == texture && IsInternalTextureTarget(mStencilbufferType))
daniel@transgaming.comfbc09532010-04-26 15:33:41 +0000110 {
111 mStencilbufferType = GL_NONE;
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000112 mStencilbufferPointer.set(NULL);
daniel@transgaming.comfbc09532010-04-26 15:33:41 +0000113 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000114}
115
116void Framebuffer::detachRenderbuffer(GLuint renderbuffer)
117{
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000118 for (unsigned int colorAttachment = 0; colorAttachment < IMPLEMENTATION_MAX_DRAW_BUFFERS; colorAttachment++)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000119 {
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000120 if (mColorbufferPointers[colorAttachment].id() == renderbuffer && mColorbufferTypes[colorAttachment] == GL_RENDERBUFFER)
121 {
122 mColorbufferTypes[colorAttachment] = GL_NONE;
123 mColorbufferPointers[colorAttachment].set(NULL);
124 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000125 }
126
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000127 if (mDepthbufferPointer.id() == renderbuffer && mDepthbufferType == GL_RENDERBUFFER)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000128 {
129 mDepthbufferType = GL_NONE;
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000130 mDepthbufferPointer.set(NULL);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000131 }
132
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000133 if (mStencilbufferPointer.id() == renderbuffer && mStencilbufferType == GL_RENDERBUFFER)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000134 {
135 mStencilbufferType = GL_NONE;
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000136 mStencilbufferPointer.set(NULL);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000137 }
138}
139
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000140unsigned int Framebuffer::getRenderTargetSerial(unsigned int colorAttachment) const
daniel@transgaming.com092bd482010-05-12 03:39:36 +0000141{
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000142 ASSERT(colorAttachment < IMPLEMENTATION_MAX_DRAW_BUFFERS);
143
144 Renderbuffer *colorbuffer = mColorbufferPointers[colorAttachment].get();
daniel@transgaming.com092bd482010-05-12 03:39:36 +0000145
146 if (colorbuffer)
147 {
148 return colorbuffer->getSerial();
149 }
150
151 return 0;
152}
153
shannon.woods%transgaming.com@gtempaccount.com3b57b4f2013-04-13 03:28:29 +0000154unsigned int Framebuffer::getDepthbufferSerial() const
daniel@transgaming.com339ae702010-05-12 03:40:20 +0000155{
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000156 Renderbuffer *depthbuffer = mDepthbufferPointer.get();
daniel@transgaming.com339ae702010-05-12 03:40:20 +0000157
158 if (depthbuffer)
159 {
160 return depthbuffer->getSerial();
161 }
162
163 return 0;
164}
165
shannon.woods%transgaming.com@gtempaccount.com3b57b4f2013-04-13 03:28:29 +0000166unsigned int Framebuffer::getStencilbufferSerial() const
daniel@transgaming.com4cbc5902010-08-24 19:20:26 +0000167{
168 Renderbuffer *stencilbuffer = mStencilbufferPointer.get();
169
170 if (stencilbuffer)
171 {
172 return stencilbuffer->getSerial();
173 }
174
175 return 0;
176}
177
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000178Renderbuffer *Framebuffer::getColorbuffer(unsigned int colorAttachment) const
179{
180 ASSERT(colorAttachment < IMPLEMENTATION_MAX_DRAW_BUFFERS);
181 return mColorbufferPointers[colorAttachment].get();
182}
183
shannon.woods%transgaming.com@gtempaccount.com3b57b4f2013-04-13 03:28:29 +0000184Renderbuffer *Framebuffer::getDepthbuffer() const
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000185{
daniel@transgaming.comd14558a2011-11-09 17:46:18 +0000186 return mDepthbufferPointer.get();
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000187}
188
shannon.woods%transgaming.com@gtempaccount.com3b57b4f2013-04-13 03:28:29 +0000189Renderbuffer *Framebuffer::getStencilbuffer() const
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000190{
daniel@transgaming.comd14558a2011-11-09 17:46:18 +0000191 return mStencilbufferPointer.get();
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000192}
193
shannon.woods%transgaming.com@gtempaccount.com3b57b4f2013-04-13 03:28:29 +0000194Renderbuffer *Framebuffer::getDepthOrStencilbuffer() const
daniel@transgaming.comd2b47022012-11-28 19:40:10 +0000195{
196 Renderbuffer *depthstencilbuffer = mDepthbufferPointer.get();
197
198 if (!depthstencilbuffer)
199 {
200 depthstencilbuffer = mStencilbufferPointer.get();
201 }
202
203 return depthstencilbuffer;
204}
205
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000206Renderbuffer *Framebuffer::getReadColorbuffer() const
207{
208 // Will require more logic if glReadBuffers is supported
209 return mColorbufferPointers[0].get();
210}
211
shannon.woods%transgaming.com@gtempaccount.comf6863e02013-04-13 03:34:00 +0000212GLenum Framebuffer::getReadColorbufferType() const
213{
214 // Will require more logic if glReadBuffers is supported
215 return mColorbufferTypes[0];
216}
217
shannon.woods%transgaming.com@gtempaccount.com882434c2013-04-13 03:34:14 +0000218Renderbuffer *Framebuffer::getFirstColorbuffer() const
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000219{
220 for (unsigned int colorAttachment = 0; colorAttachment < IMPLEMENTATION_MAX_DRAW_BUFFERS; colorAttachment++)
221 {
222 if (mColorbufferTypes[colorAttachment] != GL_NONE)
223 {
224 return mColorbufferPointers[colorAttachment].get();
225 }
226 }
227
228 return NULL;
229}
230
231GLenum Framebuffer::getColorbufferType(unsigned int colorAttachment) const
232{
233 ASSERT(colorAttachment < IMPLEMENTATION_MAX_DRAW_BUFFERS);
234 return mColorbufferTypes[colorAttachment];
235}
236
shannon.woods%transgaming.com@gtempaccount.com3b57b4f2013-04-13 03:28:29 +0000237GLenum Framebuffer::getDepthbufferType() const
daniel@transgaming.comc46c9c02010-04-23 18:34:55 +0000238{
239 return mDepthbufferType;
240}
241
shannon.woods%transgaming.com@gtempaccount.com3b57b4f2013-04-13 03:28:29 +0000242GLenum Framebuffer::getStencilbufferType() const
daniel@transgaming.comc46c9c02010-04-23 18:34:55 +0000243{
244 return mStencilbufferType;
245}
246
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000247GLuint Framebuffer::getColorbufferHandle(unsigned int colorAttachment) const
248{
249 ASSERT(colorAttachment < IMPLEMENTATION_MAX_DRAW_BUFFERS);
250 return mColorbufferPointers[colorAttachment].id();
251}
252
shannon.woods%transgaming.com@gtempaccount.com3b57b4f2013-04-13 03:28:29 +0000253GLuint Framebuffer::getDepthbufferHandle() const
daniel@transgaming.comc46c9c02010-04-23 18:34:55 +0000254{
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000255 return mDepthbufferPointer.id();
daniel@transgaming.comc46c9c02010-04-23 18:34:55 +0000256}
257
shannon.woods%transgaming.com@gtempaccount.com3b57b4f2013-04-13 03:28:29 +0000258GLuint Framebuffer::getStencilbufferHandle() const
daniel@transgaming.comc46c9c02010-04-23 18:34:55 +0000259{
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000260 return mStencilbufferPointer.id();
daniel@transgaming.comc46c9c02010-04-23 18:34:55 +0000261}
262
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000263GLenum Framebuffer::getDrawBufferState(unsigned int colorAttachment) const
264{
265 return mDrawBufferStates[colorAttachment];
266}
267
268void Framebuffer::setDrawBufferState(unsigned int colorAttachment, GLenum drawBuffer)
269{
270 mDrawBufferStates[colorAttachment] = drawBuffer;
271}
272
shannon.woods%transgaming.com@gtempaccount.comdae24092013-04-13 03:31:31 +0000273bool Framebuffer::isEnabledColorAttachment(unsigned int colorAttachment) const
274{
275 return (mColorbufferTypes[colorAttachment] != GL_NONE && mDrawBufferStates[colorAttachment] != GL_NONE);
276}
277
278bool Framebuffer::hasEnabledColorAttachment() const
279{
280 for (unsigned int colorAttachment = 0; colorAttachment < gl::IMPLEMENTATION_MAX_DRAW_BUFFERS; colorAttachment++)
281 {
282 if (isEnabledColorAttachment(colorAttachment))
283 {
284 return true;
285 }
286 }
287
288 return false;
289}
290
shannon.woods%transgaming.com@gtempaccount.com3b57b4f2013-04-13 03:28:29 +0000291bool Framebuffer::hasStencil() const
daniel@transgaming.coma27ff1e2010-08-24 19:20:11 +0000292{
293 if (mStencilbufferType != GL_NONE)
294 {
shannon.woods%transgaming.com@gtempaccount.com3b57b4f2013-04-13 03:28:29 +0000295 const Renderbuffer *stencilbufferObject = getStencilbuffer();
daniel@transgaming.coma27ff1e2010-08-24 19:20:11 +0000296
297 if (stencilbufferObject)
298 {
299 return stencilbufferObject->getStencilSize() > 0;
300 }
301 }
302
303 return false;
304}
305
shannonwoods@chromium.org24ac8502013-05-30 00:01:37 +0000306bool Framebuffer::usingExtendedDrawBuffers() const
307{
308 for (unsigned int colorAttachment = 1; colorAttachment < IMPLEMENTATION_MAX_DRAW_BUFFERS; colorAttachment++)
309 {
310 if (isEnabledColorAttachment(colorAttachment))
311 {
312 return true;
313 }
314 }
315
316 return false;
317}
318
shannon.woods%transgaming.com@gtempaccount.com3b57b4f2013-04-13 03:28:29 +0000319GLenum Framebuffer::completeness() const
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000320{
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000321 int width = 0;
322 int height = 0;
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000323 int colorbufferSize = 0;
daniel@transgaming.com1f135d82010-08-24 19:20:36 +0000324 int samples = -1;
daniel@transgaming.com6b7c84c2012-05-31 01:14:39 +0000325 bool missingAttachment = true;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000326
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000327 for (unsigned int colorAttachment = 0; colorAttachment < IMPLEMENTATION_MAX_DRAW_BUFFERS; colorAttachment++)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000328 {
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000329 if (mColorbufferTypes[colorAttachment] != GL_NONE)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000330 {
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000331 const Renderbuffer *colorbuffer = getColorbuffer(colorAttachment);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000332
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000333 if (!colorbuffer)
daniel@transgaming.comedc19182010-10-15 17:57:55 +0000334 {
335 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
336 }
daniel@transgaming.comd885df02012-05-31 01:14:36 +0000337
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000338 if (colorbuffer->getWidth() == 0 || colorbuffer->getHeight() == 0)
daniel@transgaming.com6b7c84c2012-05-31 01:14:39 +0000339 {
340 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
341 }
daniel@transgaming.com01868132010-08-24 19:21:17 +0000342
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000343 if (mColorbufferTypes[colorAttachment] == GL_RENDERBUFFER)
344 {
345 if (!gl::IsColorRenderable(colorbuffer->getInternalFormat()))
346 {
347 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
348 }
349 }
350 else if (IsInternalTextureTarget(mColorbufferTypes[colorAttachment]))
351 {
352 GLint internalformat = colorbuffer->getInternalFormat();
353 GLenum format = gl::ExtractFormat(internalformat);
354
355 if (IsCompressed(format) ||
356 format == GL_ALPHA ||
357 format == GL_LUMINANCE ||
358 format == GL_LUMINANCE_ALPHA)
359 {
360 return GL_FRAMEBUFFER_UNSUPPORTED;
361 }
362
363 bool filtering, renderable;
364
365 if ((gl::IsFloat32Format(internalformat) && !mRenderer->getFloat32TextureSupport(&filtering, &renderable)) ||
366 (gl::IsFloat16Format(internalformat) && !mRenderer->getFloat16TextureSupport(&filtering, &renderable)))
367 {
368 return GL_FRAMEBUFFER_UNSUPPORTED;
369 }
370
371 if (gl::IsDepthTexture(internalformat) || gl::IsStencilTexture(internalformat))
372 {
373 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
374 }
375 }
376 else
377 {
378 UNREACHABLE();
379 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
380 }
381
382 if (!missingAttachment)
383 {
384 // all color attachments must have the same width and height
385 if (colorbuffer->getWidth() != width || colorbuffer->getHeight() != height)
386 {
387 return GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS;
388 }
389
390 // APPLE_framebuffer_multisample, which EXT_draw_buffers refers to, requires that
391 // all color attachments have the same number of samples for the FBO to be complete.
392 if (colorbuffer->getSamples() != samples)
393 {
394 return GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE_EXT;
395 }
396
shannon.woods%transgaming.com@gtempaccount.comc3471522013-04-13 03:34:52 +0000397 // in GLES 2.0, all color attachments attachments must have the same number of bitplanes
398 // in GLES 3.0, there is no such restriction
399 if (mRenderer->getCurrentClientVersion() < 3)
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000400 {
shannon.woods%transgaming.com@gtempaccount.comc3471522013-04-13 03:34:52 +0000401 if (ComputePixelSize(colorbuffer->getInternalFormat()) != colorbufferSize)
402 {
403 return GL_FRAMEBUFFER_UNSUPPORTED;
404 }
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000405 }
406
407 // D3D11 does not allow for overlapping RenderTargetViews, so ensure uniqueness
408 for (unsigned int previousColorAttachment = 0; previousColorAttachment < colorAttachment; previousColorAttachment++)
409 {
410 if (mColorbufferPointers[colorAttachment].get() == mColorbufferPointers[previousColorAttachment].get())
411 {
412 return GL_FRAMEBUFFER_UNSUPPORTED;
413 }
414 }
415 }
416 else
417 {
418 width = colorbuffer->getWidth();
419 height = colorbuffer->getHeight();
420 samples = colorbuffer->getSamples();
421 colorbufferSize = gl::ComputePixelSize(colorbuffer->getInternalFormat());
422 missingAttachment = false;
423 }
424 }
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000425 }
426
shannon.woods%transgaming.com@gtempaccount.com3b57b4f2013-04-13 03:28:29 +0000427 const Renderbuffer *depthbuffer = NULL;
428 const Renderbuffer *stencilbuffer = NULL;
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000429
430 if (mDepthbufferType != GL_NONE)
431 {
432 depthbuffer = getDepthbuffer();
433
434 if (!depthbuffer)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000435 {
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000436 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000437 }
438
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000439 if (depthbuffer->getWidth() == 0 || depthbuffer->getHeight() == 0)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000440 {
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000441 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
442 }
443
daniel@transgaming.com6b7c84c2012-05-31 01:14:39 +0000444 if (mDepthbufferType == GL_RENDERBUFFER)
445 {
446 if (!gl::IsDepthRenderable(depthbuffer->getInternalFormat()))
447 {
448 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
449 }
450 }
451 else if (IsInternalTextureTarget(mDepthbufferType))
452 {
daniel@transgaming.com8e91d252012-10-17 18:22:44 +0000453 GLint internalformat = depthbuffer->getInternalFormat();
daniel@transgaming.com6b7c84c2012-05-31 01:14:39 +0000454
455 // depth texture attachments require OES/ANGLE_depth_texture
daniel@transgaming.comea32d482012-11-28 19:33:18 +0000456 if (!mRenderer->getDepthTextureSupport())
daniel@transgaming.com6b7c84c2012-05-31 01:14:39 +0000457 {
458 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
459 }
460
daniel@transgaming.com8e91d252012-10-17 18:22:44 +0000461 if (!gl::IsDepthTexture(internalformat))
daniel@transgaming.com6b7c84c2012-05-31 01:14:39 +0000462 {
463 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
464 }
465 }
466 else
467 {
468 UNREACHABLE();
469 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
470 }
471
472 if (missingAttachment)
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000473 {
474 width = depthbuffer->getWidth();
475 height = depthbuffer->getHeight();
daniel@transgaming.com6b7c84c2012-05-31 01:14:39 +0000476 samples = depthbuffer->getSamples();
477 missingAttachment = false;
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000478 }
479 else if (width != depthbuffer->getWidth() || height != depthbuffer->getHeight())
480 {
481 return GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS;
482 }
daniel@transgaming.com1f135d82010-08-24 19:20:36 +0000483 else if (samples != depthbuffer->getSamples())
484 {
485 return GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE_ANGLE;
486 }
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000487 }
488
489 if (mStencilbufferType != GL_NONE)
490 {
491 stencilbuffer = getStencilbuffer();
492
493 if (!stencilbuffer)
494 {
495 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
496 }
497
498 if (stencilbuffer->getWidth() == 0 || stencilbuffer->getHeight() == 0)
499 {
500 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
501 }
502
daniel@transgaming.com6b7c84c2012-05-31 01:14:39 +0000503 if (mStencilbufferType == GL_RENDERBUFFER)
504 {
505 if (!gl::IsStencilRenderable(stencilbuffer->getInternalFormat()))
506 {
507 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
508 }
509 }
510 else if (IsInternalTextureTarget(mStencilbufferType))
511 {
daniel@transgaming.com8e91d252012-10-17 18:22:44 +0000512 GLint internalformat = stencilbuffer->getInternalFormat();
daniel@transgaming.com6b7c84c2012-05-31 01:14:39 +0000513
514 // texture stencil attachments come along as part
515 // of OES_packed_depth_stencil + OES/ANGLE_depth_texture
daniel@transgaming.comea32d482012-11-28 19:33:18 +0000516 if (!mRenderer->getDepthTextureSupport())
daniel@transgaming.com6b7c84c2012-05-31 01:14:39 +0000517 {
518 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
519 }
520
daniel@transgaming.com8e91d252012-10-17 18:22:44 +0000521 if (!gl::IsStencilTexture(internalformat))
daniel@transgaming.com6b7c84c2012-05-31 01:14:39 +0000522 {
523 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
524 }
525 }
526 else
527 {
528 UNREACHABLE();
529 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
530 }
531
532 if (missingAttachment)
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000533 {
534 width = stencilbuffer->getWidth();
535 height = stencilbuffer->getHeight();
daniel@transgaming.com6b7c84c2012-05-31 01:14:39 +0000536 samples = stencilbuffer->getSamples();
537 missingAttachment = false;
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000538 }
539 else if (width != stencilbuffer->getWidth() || height != stencilbuffer->getHeight())
540 {
541 return GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS;
542 }
daniel@transgaming.com1f135d82010-08-24 19:20:36 +0000543 else if (samples != stencilbuffer->getSamples())
544 {
545 return GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE_ANGLE;
546 }
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000547 }
548
daniel@transgaming.com6b7c84c2012-05-31 01:14:39 +0000549 // if we have both a depth and stencil buffer, they must refer to the same object
550 // since we only support packed_depth_stencil and not separate depth and stencil
551 if (depthbuffer && stencilbuffer && (depthbuffer != stencilbuffer))
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000552 {
daniel@transgaming.com6b7c84c2012-05-31 01:14:39 +0000553 return GL_FRAMEBUFFER_UNSUPPORTED;
554 }
555
556 // we need to have at least one attachment to be complete
557 if (missingAttachment)
558 {
559 return GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT;
daniel@transgaming.comcdacc8e2010-07-28 19:20:50 +0000560 }
561
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000562 return GL_FRAMEBUFFER_COMPLETE;
563}
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000564
daniel@transgaming.com16418b12012-11-28 19:32:22 +0000565DefaultFramebuffer::DefaultFramebuffer(rx::Renderer *renderer, Colorbuffer *colorbuffer, DepthStencilbuffer *depthStencil)
566 : Framebuffer(renderer)
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000567{
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000568 mColorbufferPointers[0].set(new Renderbuffer(mRenderer, 0, colorbuffer));
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000569
daniel@transgaming.com70062c92012-11-28 19:32:30 +0000570 Renderbuffer *depthStencilRenderbuffer = new Renderbuffer(mRenderer, 0, depthStencil);
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000571 mDepthbufferPointer.set(depthStencilRenderbuffer);
572 mStencilbufferPointer.set(depthStencilRenderbuffer);
daniel@transgaming.comd14558a2011-11-09 17:46:18 +0000573
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000574 mColorbufferTypes[0] = GL_RENDERBUFFER;
daniel@transgaming.comd14558a2011-11-09 17:46:18 +0000575 mDepthbufferType = (depthStencilRenderbuffer->getDepthSize() != 0) ? GL_RENDERBUFFER : GL_NONE;
576 mStencilbufferType = (depthStencilRenderbuffer->getStencilSize() != 0) ? GL_RENDERBUFFER : GL_NONE;
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000577
578 mDrawBufferStates[0] = GL_BACK;
579 mReadBufferState = GL_BACK;
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000580}
581
shannon.woods%transgaming.com@gtempaccount.com3b57b4f2013-04-13 03:28:29 +0000582int Framebuffer::getSamples() const
daniel@transgaming.com1f135d82010-08-24 19:20:36 +0000583{
584 if (completeness() == GL_FRAMEBUFFER_COMPLETE)
585 {
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000586 // for a complete framebuffer, all attachments must have the same sample count
587 // in this case return the first nonzero sample size
588 for (unsigned int colorAttachment = 0; colorAttachment < IMPLEMENTATION_MAX_DRAW_BUFFERS; colorAttachment++)
589 {
590 if (mColorbufferTypes[colorAttachment] != GL_NONE)
591 {
592 return getColorbuffer(colorAttachment)->getSamples();
593 }
594 }
daniel@transgaming.com1f135d82010-08-24 19:20:36 +0000595 }
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000596
597 return 0;
daniel@transgaming.com1f135d82010-08-24 19:20:36 +0000598}
599
shannon.woods%transgaming.com@gtempaccount.com3b57b4f2013-04-13 03:28:29 +0000600GLenum DefaultFramebuffer::completeness() const
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000601{
shannon.woods@transgaming.com3e3da582013-02-28 23:09:03 +0000602 // The default framebuffer *must* always be complete, though it may not be
603 // subject to the same rules as application FBOs. ie, it could have 0x0 size.
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000604 return GL_FRAMEBUFFER_COMPLETE;
605}
606
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000607}