blob: 1d83ded50bfcb9ee183787636756b276f9325ed2 [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
Geoff Lang55ba29c2013-07-11 16:57:53 -040093void Framebuffer::setDepthStencilBuffer(GLenum type, GLuint depthStencilBuffer)
94{
95 Renderbuffer *renderBuffer = lookupRenderbuffer(type, depthStencilBuffer);
96 if (renderBuffer && renderBuffer->getDepthSize() > 0 && renderBuffer->getStencilSize() > 0)
97 {
98 mDepthbufferType = type;
99 mDepthbufferPointer.set(renderBuffer);
100
101 mStencilbufferType = type;
102 mStencilbufferPointer.set(renderBuffer);
103 }
104 else
105 {
106 mDepthbufferType = GL_NONE;
107 mStencilbufferType = GL_NONE;
108 }
109}
110
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000111void Framebuffer::detachTexture(GLuint texture)
112{
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000113 for (unsigned int colorAttachment = 0; colorAttachment < IMPLEMENTATION_MAX_DRAW_BUFFERS; colorAttachment++)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000114 {
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000115 if (mColorbufferPointers[colorAttachment].id() == texture && IsInternalTextureTarget(mColorbufferTypes[colorAttachment]))
116 {
117 mColorbufferTypes[colorAttachment] = GL_NONE;
118 mColorbufferPointers[colorAttachment].set(NULL);
119 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000120 }
daniel@transgaming.comfbc09532010-04-26 15:33:41 +0000121
apatrick@chromium.org551022e2012-01-23 19:56:54 +0000122 if (mDepthbufferPointer.id() == texture && IsInternalTextureTarget(mDepthbufferType))
daniel@transgaming.comfbc09532010-04-26 15:33:41 +0000123 {
124 mDepthbufferType = GL_NONE;
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000125 mDepthbufferPointer.set(NULL);
daniel@transgaming.comfbc09532010-04-26 15:33:41 +0000126 }
127
apatrick@chromium.org551022e2012-01-23 19:56:54 +0000128 if (mStencilbufferPointer.id() == texture && IsInternalTextureTarget(mStencilbufferType))
daniel@transgaming.comfbc09532010-04-26 15:33:41 +0000129 {
130 mStencilbufferType = GL_NONE;
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000131 mStencilbufferPointer.set(NULL);
daniel@transgaming.comfbc09532010-04-26 15:33:41 +0000132 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000133}
134
135void Framebuffer::detachRenderbuffer(GLuint renderbuffer)
136{
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000137 for (unsigned int colorAttachment = 0; colorAttachment < IMPLEMENTATION_MAX_DRAW_BUFFERS; colorAttachment++)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000138 {
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000139 if (mColorbufferPointers[colorAttachment].id() == renderbuffer && mColorbufferTypes[colorAttachment] == GL_RENDERBUFFER)
140 {
141 mColorbufferTypes[colorAttachment] = GL_NONE;
142 mColorbufferPointers[colorAttachment].set(NULL);
143 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000144 }
145
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000146 if (mDepthbufferPointer.id() == renderbuffer && mDepthbufferType == GL_RENDERBUFFER)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000147 {
148 mDepthbufferType = GL_NONE;
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000149 mDepthbufferPointer.set(NULL);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000150 }
151
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000152 if (mStencilbufferPointer.id() == renderbuffer && mStencilbufferType == GL_RENDERBUFFER)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000153 {
154 mStencilbufferType = GL_NONE;
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000155 mStencilbufferPointer.set(NULL);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000156 }
157}
158
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000159unsigned int Framebuffer::getRenderTargetSerial(unsigned int colorAttachment) const
daniel@transgaming.com092bd482010-05-12 03:39:36 +0000160{
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000161 ASSERT(colorAttachment < IMPLEMENTATION_MAX_DRAW_BUFFERS);
162
163 Renderbuffer *colorbuffer = mColorbufferPointers[colorAttachment].get();
daniel@transgaming.com092bd482010-05-12 03:39:36 +0000164
165 if (colorbuffer)
166 {
167 return colorbuffer->getSerial();
168 }
169
170 return 0;
171}
172
shannon.woods%transgaming.com@gtempaccount.com3b57b4f2013-04-13 03:28:29 +0000173unsigned int Framebuffer::getDepthbufferSerial() const
daniel@transgaming.com339ae702010-05-12 03:40:20 +0000174{
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000175 Renderbuffer *depthbuffer = mDepthbufferPointer.get();
daniel@transgaming.com339ae702010-05-12 03:40:20 +0000176
177 if (depthbuffer)
178 {
179 return depthbuffer->getSerial();
180 }
181
182 return 0;
183}
184
shannon.woods%transgaming.com@gtempaccount.com3b57b4f2013-04-13 03:28:29 +0000185unsigned int Framebuffer::getStencilbufferSerial() const
daniel@transgaming.com4cbc5902010-08-24 19:20:26 +0000186{
187 Renderbuffer *stencilbuffer = mStencilbufferPointer.get();
188
189 if (stencilbuffer)
190 {
191 return stencilbuffer->getSerial();
192 }
193
194 return 0;
195}
196
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000197Renderbuffer *Framebuffer::getColorbuffer(unsigned int colorAttachment) const
198{
199 ASSERT(colorAttachment < IMPLEMENTATION_MAX_DRAW_BUFFERS);
200 return mColorbufferPointers[colorAttachment].get();
201}
202
shannon.woods%transgaming.com@gtempaccount.com3b57b4f2013-04-13 03:28:29 +0000203Renderbuffer *Framebuffer::getDepthbuffer() const
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000204{
daniel@transgaming.comd14558a2011-11-09 17:46:18 +0000205 return mDepthbufferPointer.get();
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000206}
207
shannon.woods%transgaming.com@gtempaccount.com3b57b4f2013-04-13 03:28:29 +0000208Renderbuffer *Framebuffer::getStencilbuffer() const
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000209{
daniel@transgaming.comd14558a2011-11-09 17:46:18 +0000210 return mStencilbufferPointer.get();
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000211}
212
shannon.woods%transgaming.com@gtempaccount.com3b57b4f2013-04-13 03:28:29 +0000213Renderbuffer *Framebuffer::getDepthOrStencilbuffer() const
daniel@transgaming.comd2b47022012-11-28 19:40:10 +0000214{
215 Renderbuffer *depthstencilbuffer = mDepthbufferPointer.get();
216
217 if (!depthstencilbuffer)
218 {
219 depthstencilbuffer = mStencilbufferPointer.get();
220 }
221
222 return depthstencilbuffer;
223}
224
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000225Renderbuffer *Framebuffer::getReadColorbuffer() const
226{
227 // Will require more logic if glReadBuffers is supported
228 return mColorbufferPointers[0].get();
229}
230
shannon.woods%transgaming.com@gtempaccount.comf6863e02013-04-13 03:34:00 +0000231GLenum Framebuffer::getReadColorbufferType() const
232{
233 // Will require more logic if glReadBuffers is supported
234 return mColorbufferTypes[0];
235}
236
shannon.woods%transgaming.com@gtempaccount.com882434c2013-04-13 03:34:14 +0000237Renderbuffer *Framebuffer::getFirstColorbuffer() const
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000238{
239 for (unsigned int colorAttachment = 0; colorAttachment < IMPLEMENTATION_MAX_DRAW_BUFFERS; colorAttachment++)
240 {
241 if (mColorbufferTypes[colorAttachment] != GL_NONE)
242 {
243 return mColorbufferPointers[colorAttachment].get();
244 }
245 }
246
247 return NULL;
248}
249
250GLenum Framebuffer::getColorbufferType(unsigned int colorAttachment) const
251{
252 ASSERT(colorAttachment < IMPLEMENTATION_MAX_DRAW_BUFFERS);
253 return mColorbufferTypes[colorAttachment];
254}
255
shannon.woods%transgaming.com@gtempaccount.com3b57b4f2013-04-13 03:28:29 +0000256GLenum Framebuffer::getDepthbufferType() const
daniel@transgaming.comc46c9c02010-04-23 18:34:55 +0000257{
258 return mDepthbufferType;
259}
260
shannon.woods%transgaming.com@gtempaccount.com3b57b4f2013-04-13 03:28:29 +0000261GLenum Framebuffer::getStencilbufferType() const
daniel@transgaming.comc46c9c02010-04-23 18:34:55 +0000262{
263 return mStencilbufferType;
264}
265
Geoff Lang55ba29c2013-07-11 16:57:53 -0400266GLenum Framebuffer::getDepthStencilbufferType() const
267{
268 return (mDepthbufferPointer.id() == mStencilbufferPointer.id()) ? mDepthbufferType : GL_NONE;
269}
270
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000271GLuint Framebuffer::getColorbufferHandle(unsigned int colorAttachment) const
272{
273 ASSERT(colorAttachment < IMPLEMENTATION_MAX_DRAW_BUFFERS);
274 return mColorbufferPointers[colorAttachment].id();
275}
276
shannon.woods%transgaming.com@gtempaccount.com3b57b4f2013-04-13 03:28:29 +0000277GLuint Framebuffer::getDepthbufferHandle() const
daniel@transgaming.comc46c9c02010-04-23 18:34:55 +0000278{
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000279 return mDepthbufferPointer.id();
daniel@transgaming.comc46c9c02010-04-23 18:34:55 +0000280}
281
shannon.woods%transgaming.com@gtempaccount.com3b57b4f2013-04-13 03:28:29 +0000282GLuint Framebuffer::getStencilbufferHandle() const
daniel@transgaming.comc46c9c02010-04-23 18:34:55 +0000283{
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000284 return mStencilbufferPointer.id();
daniel@transgaming.comc46c9c02010-04-23 18:34:55 +0000285}
286
Geoff Lang55ba29c2013-07-11 16:57:53 -0400287GLenum Framebuffer::getDepthStencilbufferHandle() const
288{
289 return (mDepthbufferPointer.id() == mStencilbufferPointer.id()) ? mDepthbufferPointer.id() : 0;
290}
291
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000292GLenum Framebuffer::getDrawBufferState(unsigned int colorAttachment) const
293{
294 return mDrawBufferStates[colorAttachment];
295}
296
297void Framebuffer::setDrawBufferState(unsigned int colorAttachment, GLenum drawBuffer)
298{
299 mDrawBufferStates[colorAttachment] = drawBuffer;
300}
301
shannon.woods%transgaming.com@gtempaccount.comdae24092013-04-13 03:31:31 +0000302bool Framebuffer::isEnabledColorAttachment(unsigned int colorAttachment) const
303{
304 return (mColorbufferTypes[colorAttachment] != GL_NONE && mDrawBufferStates[colorAttachment] != GL_NONE);
305}
306
307bool Framebuffer::hasEnabledColorAttachment() const
308{
309 for (unsigned int colorAttachment = 0; colorAttachment < gl::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 +0000320bool Framebuffer::hasStencil() const
daniel@transgaming.coma27ff1e2010-08-24 19:20:11 +0000321{
322 if (mStencilbufferType != GL_NONE)
323 {
shannon.woods%transgaming.com@gtempaccount.com3b57b4f2013-04-13 03:28:29 +0000324 const Renderbuffer *stencilbufferObject = getStencilbuffer();
daniel@transgaming.coma27ff1e2010-08-24 19:20:11 +0000325
326 if (stencilbufferObject)
327 {
328 return stencilbufferObject->getStencilSize() > 0;
329 }
330 }
331
332 return false;
333}
334
shannonwoods@chromium.org24ac8502013-05-30 00:01:37 +0000335bool Framebuffer::usingExtendedDrawBuffers() const
336{
337 for (unsigned int colorAttachment = 1; colorAttachment < IMPLEMENTATION_MAX_DRAW_BUFFERS; colorAttachment++)
338 {
339 if (isEnabledColorAttachment(colorAttachment))
340 {
341 return true;
342 }
343 }
344
345 return false;
346}
347
shannon.woods%transgaming.com@gtempaccount.com3b57b4f2013-04-13 03:28:29 +0000348GLenum Framebuffer::completeness() const
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000349{
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000350 int width = 0;
351 int height = 0;
shannonwoods@chromium.orgf6fb9592013-05-30 00:09:40 +0000352 unsigned int colorbufferSize = 0;
daniel@transgaming.com1f135d82010-08-24 19:20:36 +0000353 int samples = -1;
daniel@transgaming.com6b7c84c2012-05-31 01:14:39 +0000354 bool missingAttachment = true;
shannonwoods@chromium.orgf6fb9592013-05-30 00:09:40 +0000355 GLuint clientVersion = mRenderer->getCurrentClientVersion();
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000356
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000357 for (unsigned int colorAttachment = 0; colorAttachment < IMPLEMENTATION_MAX_DRAW_BUFFERS; colorAttachment++)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000358 {
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000359 if (mColorbufferTypes[colorAttachment] != GL_NONE)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000360 {
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000361 const Renderbuffer *colorbuffer = getColorbuffer(colorAttachment);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000362
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000363 if (!colorbuffer)
daniel@transgaming.comedc19182010-10-15 17:57:55 +0000364 {
365 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
366 }
daniel@transgaming.comd885df02012-05-31 01:14:36 +0000367
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000368 if (colorbuffer->getWidth() == 0 || colorbuffer->getHeight() == 0)
daniel@transgaming.com6b7c84c2012-05-31 01:14:39 +0000369 {
370 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
371 }
daniel@transgaming.com01868132010-08-24 19:21:17 +0000372
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000373 if (mColorbufferTypes[colorAttachment] == GL_RENDERBUFFER)
374 {
shannonwoods@chromium.orgf6fb9592013-05-30 00:09:40 +0000375 if (!gl::IsColorRenderingSupported(colorbuffer->getInternalFormat(), mRenderer))
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000376 {
377 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
378 }
379 }
380 else if (IsInternalTextureTarget(mColorbufferTypes[colorAttachment]))
381 {
382 GLint internalformat = colorbuffer->getInternalFormat();
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000383
shannonwoods@chromium.orgf6fb9592013-05-30 00:09:40 +0000384 if (!gl::IsColorRenderingSupported(internalformat, mRenderer))
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000385 {
386 return GL_FRAMEBUFFER_UNSUPPORTED;
387 }
388
shannonwoods@chromium.orgf6fb9592013-05-30 00:09:40 +0000389 if (gl::GetDepthBits(internalformat, clientVersion) > 0 ||
390 gl::GetStencilBits(internalformat, clientVersion) > 0)
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000391 {
392 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
393 }
394 }
395 else
396 {
397 UNREACHABLE();
398 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
399 }
400
401 if (!missingAttachment)
402 {
403 // all color attachments must have the same width and height
404 if (colorbuffer->getWidth() != width || colorbuffer->getHeight() != height)
405 {
406 return GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS;
407 }
408
409 // APPLE_framebuffer_multisample, which EXT_draw_buffers refers to, requires that
410 // all color attachments have the same number of samples for the FBO to be complete.
411 if (colorbuffer->getSamples() != samples)
412 {
413 return GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE_EXT;
414 }
415
shannon.woods%transgaming.com@gtempaccount.comc3471522013-04-13 03:34:52 +0000416 // in GLES 2.0, all color attachments attachments must have the same number of bitplanes
417 // in GLES 3.0, there is no such restriction
shannonwoods@chromium.orgf6fb9592013-05-30 00:09:40 +0000418 if (clientVersion < 3)
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000419 {
shannonwoods@chromium.orgf6fb9592013-05-30 00:09:40 +0000420 if (gl::GetPixelBytes(colorbuffer->getInternalFormat(), clientVersion) != colorbufferSize)
shannon.woods%transgaming.com@gtempaccount.comc3471522013-04-13 03:34:52 +0000421 {
422 return GL_FRAMEBUFFER_UNSUPPORTED;
423 }
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000424 }
425
426 // D3D11 does not allow for overlapping RenderTargetViews, so ensure uniqueness
427 for (unsigned int previousColorAttachment = 0; previousColorAttachment < colorAttachment; previousColorAttachment++)
428 {
429 if (mColorbufferPointers[colorAttachment].get() == mColorbufferPointers[previousColorAttachment].get())
430 {
431 return GL_FRAMEBUFFER_UNSUPPORTED;
432 }
433 }
434 }
435 else
436 {
437 width = colorbuffer->getWidth();
438 height = colorbuffer->getHeight();
439 samples = colorbuffer->getSamples();
shannonwoods@chromium.orgf6fb9592013-05-30 00:09:40 +0000440 colorbufferSize = gl::GetPixelBytes(colorbuffer->getInternalFormat(), clientVersion);
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000441 missingAttachment = false;
442 }
443 }
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000444 }
445
shannon.woods%transgaming.com@gtempaccount.com3b57b4f2013-04-13 03:28:29 +0000446 const Renderbuffer *depthbuffer = NULL;
447 const Renderbuffer *stencilbuffer = NULL;
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000448
449 if (mDepthbufferType != GL_NONE)
450 {
451 depthbuffer = getDepthbuffer();
452
453 if (!depthbuffer)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000454 {
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000455 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000456 }
457
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000458 if (depthbuffer->getWidth() == 0 || depthbuffer->getHeight() == 0)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000459 {
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000460 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
461 }
462
daniel@transgaming.com6b7c84c2012-05-31 01:14:39 +0000463 if (mDepthbufferType == GL_RENDERBUFFER)
464 {
shannonwoods@chromium.orgf6fb9592013-05-30 00:09:40 +0000465 if (!gl::IsDepthRenderingSupported(depthbuffer->getInternalFormat(), mRenderer))
daniel@transgaming.com6b7c84c2012-05-31 01:14:39 +0000466 {
467 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
468 }
469 }
470 else if (IsInternalTextureTarget(mDepthbufferType))
471 {
daniel@transgaming.com8e91d252012-10-17 18:22:44 +0000472 GLint internalformat = depthbuffer->getInternalFormat();
daniel@transgaming.com6b7c84c2012-05-31 01:14:39 +0000473
474 // depth texture attachments require OES/ANGLE_depth_texture
daniel@transgaming.comea32d482012-11-28 19:33:18 +0000475 if (!mRenderer->getDepthTextureSupport())
daniel@transgaming.com6b7c84c2012-05-31 01:14:39 +0000476 {
477 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
478 }
479
shannonwoods@chromium.orgf6fb9592013-05-30 00:09:40 +0000480 if (gl::GetDepthBits(internalformat, clientVersion) == 0)
daniel@transgaming.com6b7c84c2012-05-31 01:14:39 +0000481 {
482 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
483 }
484 }
485 else
486 {
487 UNREACHABLE();
488 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
489 }
490
491 if (missingAttachment)
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000492 {
493 width = depthbuffer->getWidth();
494 height = depthbuffer->getHeight();
daniel@transgaming.com6b7c84c2012-05-31 01:14:39 +0000495 samples = depthbuffer->getSamples();
496 missingAttachment = false;
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000497 }
498 else if (width != depthbuffer->getWidth() || height != depthbuffer->getHeight())
499 {
500 return GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS;
501 }
daniel@transgaming.com1f135d82010-08-24 19:20:36 +0000502 else if (samples != depthbuffer->getSamples())
503 {
504 return GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE_ANGLE;
505 }
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000506 }
507
508 if (mStencilbufferType != GL_NONE)
509 {
510 stencilbuffer = getStencilbuffer();
511
512 if (!stencilbuffer)
513 {
514 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
515 }
516
517 if (stencilbuffer->getWidth() == 0 || stencilbuffer->getHeight() == 0)
518 {
519 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
520 }
521
daniel@transgaming.com6b7c84c2012-05-31 01:14:39 +0000522 if (mStencilbufferType == GL_RENDERBUFFER)
523 {
shannonwoods@chromium.orgf6fb9592013-05-30 00:09:40 +0000524 if (!gl::IsStencilRenderingSupported(stencilbuffer->getInternalFormat(), mRenderer))
daniel@transgaming.com6b7c84c2012-05-31 01:14:39 +0000525 {
526 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
527 }
528 }
529 else if (IsInternalTextureTarget(mStencilbufferType))
530 {
daniel@transgaming.com8e91d252012-10-17 18:22:44 +0000531 GLint internalformat = stencilbuffer->getInternalFormat();
daniel@transgaming.com6b7c84c2012-05-31 01:14:39 +0000532
533 // texture stencil attachments come along as part
534 // of OES_packed_depth_stencil + OES/ANGLE_depth_texture
daniel@transgaming.comea32d482012-11-28 19:33:18 +0000535 if (!mRenderer->getDepthTextureSupport())
daniel@transgaming.com6b7c84c2012-05-31 01:14:39 +0000536 {
537 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
538 }
539
shannonwoods@chromium.orgf6fb9592013-05-30 00:09:40 +0000540 if (gl::GetStencilBits(internalformat, clientVersion) == 0)
daniel@transgaming.com6b7c84c2012-05-31 01:14:39 +0000541 {
542 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
543 }
544 }
545 else
546 {
547 UNREACHABLE();
548 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
549 }
550
551 if (missingAttachment)
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000552 {
553 width = stencilbuffer->getWidth();
554 height = stencilbuffer->getHeight();
daniel@transgaming.com6b7c84c2012-05-31 01:14:39 +0000555 samples = stencilbuffer->getSamples();
556 missingAttachment = false;
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000557 }
558 else if (width != stencilbuffer->getWidth() || height != stencilbuffer->getHeight())
559 {
560 return GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS;
561 }
daniel@transgaming.com1f135d82010-08-24 19:20:36 +0000562 else if (samples != stencilbuffer->getSamples())
563 {
564 return GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE_ANGLE;
565 }
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000566 }
567
daniel@transgaming.com6b7c84c2012-05-31 01:14:39 +0000568 // if we have both a depth and stencil buffer, they must refer to the same object
569 // since we only support packed_depth_stencil and not separate depth and stencil
570 if (depthbuffer && stencilbuffer && (depthbuffer != stencilbuffer))
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000571 {
daniel@transgaming.com6b7c84c2012-05-31 01:14:39 +0000572 return GL_FRAMEBUFFER_UNSUPPORTED;
573 }
574
575 // we need to have at least one attachment to be complete
576 if (missingAttachment)
577 {
578 return GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT;
daniel@transgaming.comcdacc8e2010-07-28 19:20:50 +0000579 }
580
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000581 return GL_FRAMEBUFFER_COMPLETE;
582}
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000583
daniel@transgaming.com16418b12012-11-28 19:32:22 +0000584DefaultFramebuffer::DefaultFramebuffer(rx::Renderer *renderer, Colorbuffer *colorbuffer, DepthStencilbuffer *depthStencil)
585 : Framebuffer(renderer)
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000586{
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000587 mColorbufferPointers[0].set(new Renderbuffer(mRenderer, 0, colorbuffer));
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000588
daniel@transgaming.com70062c92012-11-28 19:32:30 +0000589 Renderbuffer *depthStencilRenderbuffer = new Renderbuffer(mRenderer, 0, depthStencil);
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000590 mDepthbufferPointer.set(depthStencilRenderbuffer);
591 mStencilbufferPointer.set(depthStencilRenderbuffer);
daniel@transgaming.comd14558a2011-11-09 17:46:18 +0000592
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000593 mColorbufferTypes[0] = GL_RENDERBUFFER;
daniel@transgaming.comd14558a2011-11-09 17:46:18 +0000594 mDepthbufferType = (depthStencilRenderbuffer->getDepthSize() != 0) ? GL_RENDERBUFFER : GL_NONE;
595 mStencilbufferType = (depthStencilRenderbuffer->getStencilSize() != 0) ? GL_RENDERBUFFER : GL_NONE;
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000596
597 mDrawBufferStates[0] = GL_BACK;
598 mReadBufferState = GL_BACK;
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000599}
600
shannon.woods%transgaming.com@gtempaccount.com3b57b4f2013-04-13 03:28:29 +0000601int Framebuffer::getSamples() const
daniel@transgaming.com1f135d82010-08-24 19:20:36 +0000602{
603 if (completeness() == GL_FRAMEBUFFER_COMPLETE)
604 {
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000605 // for a complete framebuffer, all attachments must have the same sample count
606 // in this case return the first nonzero sample size
607 for (unsigned int colorAttachment = 0; colorAttachment < IMPLEMENTATION_MAX_DRAW_BUFFERS; colorAttachment++)
608 {
609 if (mColorbufferTypes[colorAttachment] != GL_NONE)
610 {
611 return getColorbuffer(colorAttachment)->getSamples();
612 }
613 }
daniel@transgaming.com1f135d82010-08-24 19:20:36 +0000614 }
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000615
616 return 0;
daniel@transgaming.com1f135d82010-08-24 19:20:36 +0000617}
618
shannon.woods%transgaming.com@gtempaccount.com3b57b4f2013-04-13 03:28:29 +0000619GLenum DefaultFramebuffer::completeness() const
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000620{
shannon.woods@transgaming.com3e3da582013-02-28 23:09:03 +0000621 // The default framebuffer *must* always be complete, though it may not be
622 // subject to the same rules as application FBOs. ie, it could have 0x0 size.
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000623 return GL_FRAMEBUFFER_COMPLETE;
624}
625
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000626}