blob: 2f8d3742ae30ba892a954dd809caba896fa20e20 [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"
shannonwoods@chromium.orga2ecfcc2013-05-30 00:11:59 +000014#include "common/utilities.h"
shannonwoods@chromium.orgf6fb9592013-05-30 00:09:40 +000015#include "libGLESv2/formatutils.h"
shannon.woods@transgaming.com486d9e92013-02-28 23:15:41 +000016#include "libGLESv2/Texture.h"
17#include "libGLESv2/Context.h"
18#include "libGLESv2/renderer/Renderer.h"
19#include "libGLESv2/Renderbuffer.h"
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000020
21namespace gl
22{
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +000023
daniel@transgaming.com16418b12012-11-28 19:32:22 +000024Framebuffer::Framebuffer(rx::Renderer *renderer)
25 : mRenderer(renderer)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000026{
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +000027 for (unsigned int colorAttachment = 0; colorAttachment < IMPLEMENTATION_MAX_DRAW_BUFFERS; colorAttachment++)
28 {
29 mColorbufferTypes[colorAttachment] = GL_NONE;
30 mDrawBufferStates[colorAttachment] = GL_NONE;
31 }
32 mDrawBufferStates[0] = GL_COLOR_ATTACHMENT0_EXT;
33 mReadBufferState = GL_COLOR_ATTACHMENT0_EXT;
34
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000035 mDepthbufferType = GL_NONE;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000036 mStencilbufferType = GL_NONE;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000037}
38
39Framebuffer::~Framebuffer()
40{
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +000041 for (unsigned int colorAttachment = 0; colorAttachment < IMPLEMENTATION_MAX_DRAW_BUFFERS; colorAttachment++)
42 {
43 mColorbufferPointers[colorAttachment].set(NULL);
44 }
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +000045 mDepthbufferPointer.set(NULL);
46 mStencilbufferPointer.set(NULL);
47}
48
49Renderbuffer *Framebuffer::lookupRenderbuffer(GLenum type, GLuint handle) const
50{
51 gl::Context *context = gl::getContext();
52 Renderbuffer *buffer = NULL;
53
54 if (type == GL_NONE)
55 {
56 buffer = NULL;
57 }
58 else if (type == GL_RENDERBUFFER)
59 {
60 buffer = context->getRenderbuffer(handle);
61 }
apatrick@chromium.org551022e2012-01-23 19:56:54 +000062 else if (IsInternalTextureTarget(type))
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +000063 {
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +000064 buffer = context->getTexture(handle)->getRenderbuffer(type);
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +000065 }
66 else
67 {
68 UNREACHABLE();
69 }
70
71 return buffer;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000072}
73
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +000074void Framebuffer::setColorbuffer(unsigned int colorAttachment, GLenum type, GLuint colorbuffer)
75{
76 ASSERT(colorAttachment < IMPLEMENTATION_MAX_DRAW_BUFFERS);
77 mColorbufferTypes[colorAttachment] = (colorbuffer != 0) ? type : GL_NONE;
78 mColorbufferPointers[colorAttachment].set(lookupRenderbuffer(type, colorbuffer));
79}
80
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000081void Framebuffer::setDepthbuffer(GLenum type, GLuint depthbuffer)
82{
daniel@transgaming.com2fa45512011-10-04 18:43:18 +000083 mDepthbufferType = (depthbuffer != 0) ? type : GL_NONE;
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +000084 mDepthbufferPointer.set(lookupRenderbuffer(type, depthbuffer));
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000085}
86
87void Framebuffer::setStencilbuffer(GLenum type, GLuint stencilbuffer)
88{
daniel@transgaming.com2fa45512011-10-04 18:43:18 +000089 mStencilbufferType = (stencilbuffer != 0) ? type : GL_NONE;
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +000090 mStencilbufferPointer.set(lookupRenderbuffer(type, stencilbuffer));
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000091}
92
93void Framebuffer::detachTexture(GLuint texture)
94{
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +000095 for (unsigned int colorAttachment = 0; colorAttachment < IMPLEMENTATION_MAX_DRAW_BUFFERS; colorAttachment++)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000096 {
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +000097 if (mColorbufferPointers[colorAttachment].id() == texture && IsInternalTextureTarget(mColorbufferTypes[colorAttachment]))
98 {
99 mColorbufferTypes[colorAttachment] = GL_NONE;
100 mColorbufferPointers[colorAttachment].set(NULL);
101 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000102 }
daniel@transgaming.comfbc09532010-04-26 15:33:41 +0000103
apatrick@chromium.org551022e2012-01-23 19:56:54 +0000104 if (mDepthbufferPointer.id() == texture && IsInternalTextureTarget(mDepthbufferType))
daniel@transgaming.comfbc09532010-04-26 15:33:41 +0000105 {
106 mDepthbufferType = GL_NONE;
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000107 mDepthbufferPointer.set(NULL);
daniel@transgaming.comfbc09532010-04-26 15:33:41 +0000108 }
109
apatrick@chromium.org551022e2012-01-23 19:56:54 +0000110 if (mStencilbufferPointer.id() == texture && IsInternalTextureTarget(mStencilbufferType))
daniel@transgaming.comfbc09532010-04-26 15:33:41 +0000111 {
112 mStencilbufferType = GL_NONE;
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000113 mStencilbufferPointer.set(NULL);
daniel@transgaming.comfbc09532010-04-26 15:33:41 +0000114 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000115}
116
117void Framebuffer::detachRenderbuffer(GLuint renderbuffer)
118{
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000119 for (unsigned int colorAttachment = 0; colorAttachment < IMPLEMENTATION_MAX_DRAW_BUFFERS; colorAttachment++)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000120 {
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000121 if (mColorbufferPointers[colorAttachment].id() == renderbuffer && mColorbufferTypes[colorAttachment] == GL_RENDERBUFFER)
122 {
123 mColorbufferTypes[colorAttachment] = GL_NONE;
124 mColorbufferPointers[colorAttachment].set(NULL);
125 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000126 }
127
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000128 if (mDepthbufferPointer.id() == renderbuffer && mDepthbufferType == GL_RENDERBUFFER)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000129 {
130 mDepthbufferType = GL_NONE;
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000131 mDepthbufferPointer.set(NULL);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000132 }
133
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000134 if (mStencilbufferPointer.id() == renderbuffer && mStencilbufferType == GL_RENDERBUFFER)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000135 {
136 mStencilbufferType = GL_NONE;
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000137 mStencilbufferPointer.set(NULL);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000138 }
139}
140
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000141unsigned int Framebuffer::getRenderTargetSerial(unsigned int colorAttachment) const
daniel@transgaming.com092bd482010-05-12 03:39:36 +0000142{
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000143 ASSERT(colorAttachment < IMPLEMENTATION_MAX_DRAW_BUFFERS);
144
145 Renderbuffer *colorbuffer = mColorbufferPointers[colorAttachment].get();
daniel@transgaming.com092bd482010-05-12 03:39:36 +0000146
147 if (colorbuffer)
148 {
149 return colorbuffer->getSerial();
150 }
151
152 return 0;
153}
154
shannon.woods%transgaming.com@gtempaccount.com3b57b4f2013-04-13 03:28:29 +0000155unsigned int Framebuffer::getDepthbufferSerial() const
daniel@transgaming.com339ae702010-05-12 03:40:20 +0000156{
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000157 Renderbuffer *depthbuffer = mDepthbufferPointer.get();
daniel@transgaming.com339ae702010-05-12 03:40:20 +0000158
159 if (depthbuffer)
160 {
161 return depthbuffer->getSerial();
162 }
163
164 return 0;
165}
166
shannon.woods%transgaming.com@gtempaccount.com3b57b4f2013-04-13 03:28:29 +0000167unsigned int Framebuffer::getStencilbufferSerial() const
daniel@transgaming.com4cbc5902010-08-24 19:20:26 +0000168{
169 Renderbuffer *stencilbuffer = mStencilbufferPointer.get();
170
171 if (stencilbuffer)
172 {
173 return stencilbuffer->getSerial();
174 }
175
176 return 0;
177}
178
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000179Renderbuffer *Framebuffer::getColorbuffer(unsigned int colorAttachment) const
180{
181 ASSERT(colorAttachment < IMPLEMENTATION_MAX_DRAW_BUFFERS);
182 return mColorbufferPointers[colorAttachment].get();
183}
184
shannon.woods%transgaming.com@gtempaccount.com3b57b4f2013-04-13 03:28:29 +0000185Renderbuffer *Framebuffer::getDepthbuffer() const
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000186{
daniel@transgaming.comd14558a2011-11-09 17:46:18 +0000187 return mDepthbufferPointer.get();
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000188}
189
shannon.woods%transgaming.com@gtempaccount.com3b57b4f2013-04-13 03:28:29 +0000190Renderbuffer *Framebuffer::getStencilbuffer() const
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000191{
daniel@transgaming.comd14558a2011-11-09 17:46:18 +0000192 return mStencilbufferPointer.get();
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000193}
194
shannon.woods%transgaming.com@gtempaccount.com3b57b4f2013-04-13 03:28:29 +0000195Renderbuffer *Framebuffer::getDepthOrStencilbuffer() const
daniel@transgaming.comd2b47022012-11-28 19:40:10 +0000196{
197 Renderbuffer *depthstencilbuffer = mDepthbufferPointer.get();
198
199 if (!depthstencilbuffer)
200 {
201 depthstencilbuffer = mStencilbufferPointer.get();
202 }
203
204 return depthstencilbuffer;
205}
206
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000207Renderbuffer *Framebuffer::getReadColorbuffer() const
208{
209 // Will require more logic if glReadBuffers is supported
210 return mColorbufferPointers[0].get();
211}
212
shannon.woods%transgaming.com@gtempaccount.comf6863e02013-04-13 03:34:00 +0000213GLenum Framebuffer::getReadColorbufferType() const
214{
215 // Will require more logic if glReadBuffers is supported
216 return mColorbufferTypes[0];
217}
218
shannon.woods%transgaming.com@gtempaccount.com882434c2013-04-13 03:34:14 +0000219Renderbuffer *Framebuffer::getFirstColorbuffer() const
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000220{
221 for (unsigned int colorAttachment = 0; colorAttachment < IMPLEMENTATION_MAX_DRAW_BUFFERS; colorAttachment++)
222 {
223 if (mColorbufferTypes[colorAttachment] != GL_NONE)
224 {
225 return mColorbufferPointers[colorAttachment].get();
226 }
227 }
228
229 return NULL;
230}
231
232GLenum Framebuffer::getColorbufferType(unsigned int colorAttachment) const
233{
234 ASSERT(colorAttachment < IMPLEMENTATION_MAX_DRAW_BUFFERS);
235 return mColorbufferTypes[colorAttachment];
236}
237
shannon.woods%transgaming.com@gtempaccount.com3b57b4f2013-04-13 03:28:29 +0000238GLenum Framebuffer::getDepthbufferType() const
daniel@transgaming.comc46c9c02010-04-23 18:34:55 +0000239{
240 return mDepthbufferType;
241}
242
shannon.woods%transgaming.com@gtempaccount.com3b57b4f2013-04-13 03:28:29 +0000243GLenum Framebuffer::getStencilbufferType() const
daniel@transgaming.comc46c9c02010-04-23 18:34:55 +0000244{
245 return mStencilbufferType;
246}
247
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000248GLuint Framebuffer::getColorbufferHandle(unsigned int colorAttachment) const
249{
250 ASSERT(colorAttachment < IMPLEMENTATION_MAX_DRAW_BUFFERS);
251 return mColorbufferPointers[colorAttachment].id();
252}
253
shannon.woods%transgaming.com@gtempaccount.com3b57b4f2013-04-13 03:28:29 +0000254GLuint Framebuffer::getDepthbufferHandle() const
daniel@transgaming.comc46c9c02010-04-23 18:34:55 +0000255{
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000256 return mDepthbufferPointer.id();
daniel@transgaming.comc46c9c02010-04-23 18:34:55 +0000257}
258
shannon.woods%transgaming.com@gtempaccount.com3b57b4f2013-04-13 03:28:29 +0000259GLuint Framebuffer::getStencilbufferHandle() const
daniel@transgaming.comc46c9c02010-04-23 18:34:55 +0000260{
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000261 return mStencilbufferPointer.id();
daniel@transgaming.comc46c9c02010-04-23 18:34:55 +0000262}
263
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000264GLenum Framebuffer::getDrawBufferState(unsigned int colorAttachment) const
265{
266 return mDrawBufferStates[colorAttachment];
267}
268
269void Framebuffer::setDrawBufferState(unsigned int colorAttachment, GLenum drawBuffer)
270{
271 mDrawBufferStates[colorAttachment] = drawBuffer;
272}
273
shannon.woods%transgaming.com@gtempaccount.comdae24092013-04-13 03:31:31 +0000274bool Framebuffer::isEnabledColorAttachment(unsigned int colorAttachment) const
275{
276 return (mColorbufferTypes[colorAttachment] != GL_NONE && mDrawBufferStates[colorAttachment] != GL_NONE);
277}
278
279bool Framebuffer::hasEnabledColorAttachment() const
280{
281 for (unsigned int colorAttachment = 0; colorAttachment < gl::IMPLEMENTATION_MAX_DRAW_BUFFERS; colorAttachment++)
282 {
283 if (isEnabledColorAttachment(colorAttachment))
284 {
285 return true;
286 }
287 }
288
289 return false;
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
shannonwoods@chromium.org24ac8502013-05-30 00:01:37 +0000307bool Framebuffer::usingExtendedDrawBuffers() const
308{
309 for (unsigned int colorAttachment = 1; colorAttachment < IMPLEMENTATION_MAX_DRAW_BUFFERS; colorAttachment++)
310 {
311 if (isEnabledColorAttachment(colorAttachment))
312 {
313 return true;
314 }
315 }
316
317 return false;
318}
319
shannon.woods%transgaming.com@gtempaccount.com3b57b4f2013-04-13 03:28:29 +0000320GLenum Framebuffer::completeness() const
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000321{
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000322 int width = 0;
323 int height = 0;
shannonwoods@chromium.orgf6fb9592013-05-30 00:09:40 +0000324 unsigned int colorbufferSize = 0;
daniel@transgaming.com1f135d82010-08-24 19:20:36 +0000325 int samples = -1;
daniel@transgaming.com6b7c84c2012-05-31 01:14:39 +0000326 bool missingAttachment = true;
shannonwoods@chromium.orgf6fb9592013-05-30 00:09:40 +0000327 GLuint clientVersion = mRenderer->getCurrentClientVersion();
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000328
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000329 for (unsigned int colorAttachment = 0; colorAttachment < IMPLEMENTATION_MAX_DRAW_BUFFERS; colorAttachment++)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000330 {
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000331 if (mColorbufferTypes[colorAttachment] != GL_NONE)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000332 {
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000333 const Renderbuffer *colorbuffer = getColorbuffer(colorAttachment);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000334
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000335 if (!colorbuffer)
daniel@transgaming.comedc19182010-10-15 17:57:55 +0000336 {
337 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
338 }
daniel@transgaming.comd885df02012-05-31 01:14:36 +0000339
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000340 if (colorbuffer->getWidth() == 0 || colorbuffer->getHeight() == 0)
daniel@transgaming.com6b7c84c2012-05-31 01:14:39 +0000341 {
342 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
343 }
daniel@transgaming.com01868132010-08-24 19:21:17 +0000344
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000345 if (mColorbufferTypes[colorAttachment] == GL_RENDERBUFFER)
346 {
shannonwoods@chromium.orgf6fb9592013-05-30 00:09:40 +0000347 if (!gl::IsColorRenderingSupported(colorbuffer->getInternalFormat(), mRenderer))
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000348 {
349 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
350 }
351 }
352 else if (IsInternalTextureTarget(mColorbufferTypes[colorAttachment]))
353 {
354 GLint internalformat = colorbuffer->getInternalFormat();
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000355
shannonwoods@chromium.orgf6fb9592013-05-30 00:09:40 +0000356 if (!gl::IsColorRenderingSupported(internalformat, mRenderer))
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000357 {
358 return GL_FRAMEBUFFER_UNSUPPORTED;
359 }
360
shannonwoods@chromium.orgf6fb9592013-05-30 00:09:40 +0000361 if (gl::GetDepthBits(internalformat, clientVersion) > 0 ||
362 gl::GetStencilBits(internalformat, clientVersion) > 0)
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000363 {
364 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
365 }
366 }
367 else
368 {
369 UNREACHABLE();
370 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
371 }
372
373 if (!missingAttachment)
374 {
375 // all color attachments must have the same width and height
376 if (colorbuffer->getWidth() != width || colorbuffer->getHeight() != height)
377 {
378 return GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS;
379 }
380
381 // APPLE_framebuffer_multisample, which EXT_draw_buffers refers to, requires that
382 // all color attachments have the same number of samples for the FBO to be complete.
383 if (colorbuffer->getSamples() != samples)
384 {
385 return GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE_EXT;
386 }
387
shannon.woods%transgaming.com@gtempaccount.comc3471522013-04-13 03:34:52 +0000388 // in GLES 2.0, all color attachments attachments must have the same number of bitplanes
389 // in GLES 3.0, there is no such restriction
shannonwoods@chromium.orgf6fb9592013-05-30 00:09:40 +0000390 if (clientVersion < 3)
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000391 {
shannonwoods@chromium.orgf6fb9592013-05-30 00:09:40 +0000392 if (gl::GetPixelBytes(colorbuffer->getInternalFormat(), clientVersion) != colorbufferSize)
shannon.woods%transgaming.com@gtempaccount.comc3471522013-04-13 03:34:52 +0000393 {
394 return GL_FRAMEBUFFER_UNSUPPORTED;
395 }
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000396 }
397
398 // D3D11 does not allow for overlapping RenderTargetViews, so ensure uniqueness
399 for (unsigned int previousColorAttachment = 0; previousColorAttachment < colorAttachment; previousColorAttachment++)
400 {
401 if (mColorbufferPointers[colorAttachment].get() == mColorbufferPointers[previousColorAttachment].get())
402 {
403 return GL_FRAMEBUFFER_UNSUPPORTED;
404 }
405 }
406 }
407 else
408 {
409 width = colorbuffer->getWidth();
410 height = colorbuffer->getHeight();
411 samples = colorbuffer->getSamples();
shannonwoods@chromium.orgf6fb9592013-05-30 00:09:40 +0000412 colorbufferSize = gl::GetPixelBytes(colorbuffer->getInternalFormat(), clientVersion);
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000413 missingAttachment = false;
414 }
415 }
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000416 }
417
shannon.woods%transgaming.com@gtempaccount.com3b57b4f2013-04-13 03:28:29 +0000418 const Renderbuffer *depthbuffer = NULL;
419 const Renderbuffer *stencilbuffer = NULL;
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000420
421 if (mDepthbufferType != GL_NONE)
422 {
423 depthbuffer = getDepthbuffer();
424
425 if (!depthbuffer)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000426 {
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000427 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000428 }
429
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000430 if (depthbuffer->getWidth() == 0 || depthbuffer->getHeight() == 0)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000431 {
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000432 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
433 }
434
daniel@transgaming.com6b7c84c2012-05-31 01:14:39 +0000435 if (mDepthbufferType == GL_RENDERBUFFER)
436 {
shannonwoods@chromium.orgf6fb9592013-05-30 00:09:40 +0000437 if (!gl::IsDepthRenderingSupported(depthbuffer->getInternalFormat(), mRenderer))
daniel@transgaming.com6b7c84c2012-05-31 01:14:39 +0000438 {
439 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
440 }
441 }
442 else if (IsInternalTextureTarget(mDepthbufferType))
443 {
daniel@transgaming.com8e91d252012-10-17 18:22:44 +0000444 GLint internalformat = depthbuffer->getInternalFormat();
daniel@transgaming.com6b7c84c2012-05-31 01:14:39 +0000445
446 // depth texture attachments require OES/ANGLE_depth_texture
daniel@transgaming.comea32d482012-11-28 19:33:18 +0000447 if (!mRenderer->getDepthTextureSupport())
daniel@transgaming.com6b7c84c2012-05-31 01:14:39 +0000448 {
449 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
450 }
451
shannonwoods@chromium.orgf6fb9592013-05-30 00:09:40 +0000452 if (gl::GetDepthBits(internalformat, clientVersion) == 0)
daniel@transgaming.com6b7c84c2012-05-31 01:14:39 +0000453 {
454 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
455 }
456 }
457 else
458 {
459 UNREACHABLE();
460 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
461 }
462
463 if (missingAttachment)
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000464 {
465 width = depthbuffer->getWidth();
466 height = depthbuffer->getHeight();
daniel@transgaming.com6b7c84c2012-05-31 01:14:39 +0000467 samples = depthbuffer->getSamples();
468 missingAttachment = false;
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000469 }
470 else if (width != depthbuffer->getWidth() || height != depthbuffer->getHeight())
471 {
472 return GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS;
473 }
daniel@transgaming.com1f135d82010-08-24 19:20:36 +0000474 else if (samples != depthbuffer->getSamples())
475 {
476 return GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE_ANGLE;
477 }
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000478 }
479
480 if (mStencilbufferType != GL_NONE)
481 {
482 stencilbuffer = getStencilbuffer();
483
484 if (!stencilbuffer)
485 {
486 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
487 }
488
489 if (stencilbuffer->getWidth() == 0 || stencilbuffer->getHeight() == 0)
490 {
491 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
492 }
493
daniel@transgaming.com6b7c84c2012-05-31 01:14:39 +0000494 if (mStencilbufferType == GL_RENDERBUFFER)
495 {
shannonwoods@chromium.orgf6fb9592013-05-30 00:09:40 +0000496 if (!gl::IsStencilRenderingSupported(stencilbuffer->getInternalFormat(), mRenderer))
daniel@transgaming.com6b7c84c2012-05-31 01:14:39 +0000497 {
498 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
499 }
500 }
501 else if (IsInternalTextureTarget(mStencilbufferType))
502 {
daniel@transgaming.com8e91d252012-10-17 18:22:44 +0000503 GLint internalformat = stencilbuffer->getInternalFormat();
daniel@transgaming.com6b7c84c2012-05-31 01:14:39 +0000504
505 // texture stencil attachments come along as part
506 // of OES_packed_depth_stencil + OES/ANGLE_depth_texture
daniel@transgaming.comea32d482012-11-28 19:33:18 +0000507 if (!mRenderer->getDepthTextureSupport())
daniel@transgaming.com6b7c84c2012-05-31 01:14:39 +0000508 {
509 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
510 }
511
shannonwoods@chromium.orgf6fb9592013-05-30 00:09:40 +0000512 if (gl::GetStencilBits(internalformat, clientVersion) == 0)
daniel@transgaming.com6b7c84c2012-05-31 01:14:39 +0000513 {
514 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
515 }
516 }
517 else
518 {
519 UNREACHABLE();
520 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
521 }
522
523 if (missingAttachment)
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000524 {
525 width = stencilbuffer->getWidth();
526 height = stencilbuffer->getHeight();
daniel@transgaming.com6b7c84c2012-05-31 01:14:39 +0000527 samples = stencilbuffer->getSamples();
528 missingAttachment = false;
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000529 }
530 else if (width != stencilbuffer->getWidth() || height != stencilbuffer->getHeight())
531 {
532 return GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS;
533 }
daniel@transgaming.com1f135d82010-08-24 19:20:36 +0000534 else if (samples != stencilbuffer->getSamples())
535 {
536 return GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE_ANGLE;
537 }
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000538 }
539
daniel@transgaming.com6b7c84c2012-05-31 01:14:39 +0000540 // if we have both a depth and stencil buffer, they must refer to the same object
541 // since we only support packed_depth_stencil and not separate depth and stencil
542 if (depthbuffer && stencilbuffer && (depthbuffer != stencilbuffer))
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000543 {
daniel@transgaming.com6b7c84c2012-05-31 01:14:39 +0000544 return GL_FRAMEBUFFER_UNSUPPORTED;
545 }
546
547 // we need to have at least one attachment to be complete
548 if (missingAttachment)
549 {
550 return GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT;
daniel@transgaming.comcdacc8e2010-07-28 19:20:50 +0000551 }
552
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000553 return GL_FRAMEBUFFER_COMPLETE;
554}
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000555
daniel@transgaming.com16418b12012-11-28 19:32:22 +0000556DefaultFramebuffer::DefaultFramebuffer(rx::Renderer *renderer, Colorbuffer *colorbuffer, DepthStencilbuffer *depthStencil)
557 : Framebuffer(renderer)
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000558{
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000559 mColorbufferPointers[0].set(new Renderbuffer(mRenderer, 0, colorbuffer));
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000560
daniel@transgaming.com70062c92012-11-28 19:32:30 +0000561 Renderbuffer *depthStencilRenderbuffer = new Renderbuffer(mRenderer, 0, depthStencil);
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000562 mDepthbufferPointer.set(depthStencilRenderbuffer);
563 mStencilbufferPointer.set(depthStencilRenderbuffer);
daniel@transgaming.comd14558a2011-11-09 17:46:18 +0000564
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000565 mColorbufferTypes[0] = GL_RENDERBUFFER;
daniel@transgaming.comd14558a2011-11-09 17:46:18 +0000566 mDepthbufferType = (depthStencilRenderbuffer->getDepthSize() != 0) ? GL_RENDERBUFFER : GL_NONE;
567 mStencilbufferType = (depthStencilRenderbuffer->getStencilSize() != 0) ? GL_RENDERBUFFER : GL_NONE;
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000568
569 mDrawBufferStates[0] = GL_BACK;
570 mReadBufferState = GL_BACK;
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000571}
572
shannon.woods%transgaming.com@gtempaccount.com3b57b4f2013-04-13 03:28:29 +0000573int Framebuffer::getSamples() const
daniel@transgaming.com1f135d82010-08-24 19:20:36 +0000574{
575 if (completeness() == GL_FRAMEBUFFER_COMPLETE)
576 {
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000577 // for a complete framebuffer, all attachments must have the same sample count
578 // in this case return the first nonzero sample size
579 for (unsigned int colorAttachment = 0; colorAttachment < IMPLEMENTATION_MAX_DRAW_BUFFERS; colorAttachment++)
580 {
581 if (mColorbufferTypes[colorAttachment] != GL_NONE)
582 {
583 return getColorbuffer(colorAttachment)->getSamples();
584 }
585 }
daniel@transgaming.com1f135d82010-08-24 19:20:36 +0000586 }
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000587
588 return 0;
daniel@transgaming.com1f135d82010-08-24 19:20:36 +0000589}
590
shannon.woods%transgaming.com@gtempaccount.com3b57b4f2013-04-13 03:28:29 +0000591GLenum DefaultFramebuffer::completeness() const
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000592{
shannon.woods@transgaming.com3e3da582013-02-28 23:09:03 +0000593 // The default framebuffer *must* always be complete, though it may not be
594 // subject to the same rules as application FBOs. ie, it could have 0x0 size.
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000595 return GL_FRAMEBUFFER_COMPLETE;
596}
597
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000598}