blob: d89e0620ac19db46e46ecfa6d2ebb1eab28f3def [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 {
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +000029 mDrawBufferStates[colorAttachment] = GL_NONE;
30 }
31 mDrawBufferStates[0] = GL_COLOR_ATTACHMENT0_EXT;
32 mReadBufferState = GL_COLOR_ATTACHMENT0_EXT;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000033}
34
35Framebuffer::~Framebuffer()
36{
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +000037 for (unsigned int colorAttachment = 0; colorAttachment < IMPLEMENTATION_MAX_DRAW_BUFFERS; colorAttachment++)
38 {
Geoff Langc90d73a2013-07-22 16:39:23 -040039 mColorbuffers[colorAttachment].set(NULL, GL_NONE, 0, 0);
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +000040 }
Geoff Langc90d73a2013-07-22 16:39:23 -040041 mDepthbuffer.set(NULL, GL_NONE, 0, 0);
42 mStencilbuffer.set(NULL, GL_NONE, 0, 0);
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +000043}
44
45Renderbuffer *Framebuffer::lookupRenderbuffer(GLenum type, GLuint handle) const
46{
47 gl::Context *context = gl::getContext();
48 Renderbuffer *buffer = NULL;
49
50 if (type == GL_NONE)
51 {
52 buffer = NULL;
53 }
54 else if (type == GL_RENDERBUFFER)
55 {
56 buffer = context->getRenderbuffer(handle);
57 }
apatrick@chromium.org551022e2012-01-23 19:56:54 +000058 else if (IsInternalTextureTarget(type))
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +000059 {
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +000060 buffer = context->getTexture(handle)->getRenderbuffer(type);
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +000061 }
62 else
63 {
64 UNREACHABLE();
65 }
66
67 return buffer;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000068}
69
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +000070void Framebuffer::setColorbuffer(unsigned int colorAttachment, GLenum type, GLuint colorbuffer)
71{
72 ASSERT(colorAttachment < IMPLEMENTATION_MAX_DRAW_BUFFERS);
Geoff Langc90d73a2013-07-22 16:39:23 -040073 Renderbuffer *renderBuffer = lookupRenderbuffer(type, colorbuffer);
74 if (renderBuffer)
75 {
76 mColorbuffers[colorAttachment].set(renderBuffer, type, 0, 0);
77 }
78 else
79 {
80 mColorbuffers[colorAttachment].set(NULL, GL_NONE, 0, 0);
81 }
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +000082}
83
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000084void Framebuffer::setDepthbuffer(GLenum type, GLuint depthbuffer)
85{
Geoff Langc90d73a2013-07-22 16:39:23 -040086 Renderbuffer *renderBuffer = lookupRenderbuffer(type, depthbuffer);
87 if (renderBuffer)
88 {
89 mDepthbuffer.set(renderBuffer, type, 0, 0);
90 }
91 else
92 {
93 mDepthbuffer.set(NULL, GL_NONE, 0, 0);
94 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000095}
96
97void Framebuffer::setStencilbuffer(GLenum type, GLuint stencilbuffer)
98{
Geoff Langc90d73a2013-07-22 16:39:23 -040099 Renderbuffer *renderBuffer = lookupRenderbuffer(type, stencilbuffer);
100 if (renderBuffer)
101 {
102 mStencilbuffer.set(renderBuffer, type, 0, 0);
103 }
104 else
105 {
106 mStencilbuffer.set(NULL, GL_NONE, 0, 0);
107 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000108}
109
Geoff Lang55ba29c2013-07-11 16:57:53 -0400110void Framebuffer::setDepthStencilBuffer(GLenum type, GLuint depthStencilBuffer)
111{
112 Renderbuffer *renderBuffer = lookupRenderbuffer(type, depthStencilBuffer);
113 if (renderBuffer && renderBuffer->getDepthSize() > 0 && renderBuffer->getStencilSize() > 0)
114 {
Geoff Langc90d73a2013-07-22 16:39:23 -0400115 mDepthbuffer.set(renderBuffer, type, 0, 0);
116 mStencilbuffer.set(renderBuffer, type, 0, 0);
Geoff Lang55ba29c2013-07-11 16:57:53 -0400117 }
118 else
119 {
Geoff Langc90d73a2013-07-22 16:39:23 -0400120 mDepthbuffer.set(NULL, GL_NONE, 0, 0);
121 mStencilbuffer.set(NULL, GL_NONE, 0, 0);
Geoff Lang55ba29c2013-07-11 16:57:53 -0400122 }
123}
124
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000125void Framebuffer::detachTexture(GLuint texture)
126{
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000127 for (unsigned int colorAttachment = 0; colorAttachment < IMPLEMENTATION_MAX_DRAW_BUFFERS; colorAttachment++)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000128 {
Geoff Langc90d73a2013-07-22 16:39:23 -0400129 if (mColorbuffers[colorAttachment].id() == texture && IsInternalTextureTarget(mColorbuffers[colorAttachment].type()))
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000130 {
Geoff Langc90d73a2013-07-22 16:39:23 -0400131 mColorbuffers[colorAttachment].set(NULL, GL_NONE, 0, 0);
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000132 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000133 }
daniel@transgaming.comfbc09532010-04-26 15:33:41 +0000134
Geoff Langc90d73a2013-07-22 16:39:23 -0400135 if (mDepthbuffer.id() == texture && IsInternalTextureTarget(mDepthbuffer.type()))
daniel@transgaming.comfbc09532010-04-26 15:33:41 +0000136 {
Geoff Langc90d73a2013-07-22 16:39:23 -0400137 mDepthbuffer.set(NULL, GL_NONE, 0, 0);
daniel@transgaming.comfbc09532010-04-26 15:33:41 +0000138 }
139
Geoff Langc90d73a2013-07-22 16:39:23 -0400140 if (mStencilbuffer.id() == texture && IsInternalTextureTarget(mStencilbuffer.type()))
daniel@transgaming.comfbc09532010-04-26 15:33:41 +0000141 {
Geoff Langc90d73a2013-07-22 16:39:23 -0400142 mStencilbuffer.set(NULL, GL_NONE, 0, 0);
daniel@transgaming.comfbc09532010-04-26 15:33:41 +0000143 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000144}
145
146void Framebuffer::detachRenderbuffer(GLuint renderbuffer)
147{
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000148 for (unsigned int colorAttachment = 0; colorAttachment < IMPLEMENTATION_MAX_DRAW_BUFFERS; colorAttachment++)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000149 {
Geoff Langc90d73a2013-07-22 16:39:23 -0400150 if (mColorbuffers[colorAttachment].id() == renderbuffer && mColorbuffers[colorAttachment].type() == GL_RENDERBUFFER)
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000151 {
Geoff Langc90d73a2013-07-22 16:39:23 -0400152 mColorbuffers[colorAttachment].set(NULL, GL_NONE, 0, 0);
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000153 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000154 }
155
Geoff Langc90d73a2013-07-22 16:39:23 -0400156 if (mDepthbuffer.id() == renderbuffer && mDepthbuffer.type() == GL_RENDERBUFFER)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000157 {
Geoff Langc90d73a2013-07-22 16:39:23 -0400158 mDepthbuffer.set(NULL, GL_NONE, 0, 0);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000159 }
160
Geoff Langc90d73a2013-07-22 16:39:23 -0400161 if (mStencilbuffer.id() == renderbuffer && mStencilbuffer.type() == GL_RENDERBUFFER)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000162 {
Geoff Langc90d73a2013-07-22 16:39:23 -0400163 mStencilbuffer.set(NULL, GL_NONE, 0, 0);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000164 }
165}
166
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000167unsigned int Framebuffer::getRenderTargetSerial(unsigned int colorAttachment) const
daniel@transgaming.com092bd482010-05-12 03:39:36 +0000168{
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000169 ASSERT(colorAttachment < IMPLEMENTATION_MAX_DRAW_BUFFERS);
170
Geoff Langc90d73a2013-07-22 16:39:23 -0400171 Renderbuffer *colorbuffer = mColorbuffers[colorAttachment].get();
daniel@transgaming.com092bd482010-05-12 03:39:36 +0000172
173 if (colorbuffer)
174 {
175 return colorbuffer->getSerial();
176 }
177
178 return 0;
179}
180
shannon.woods%transgaming.com@gtempaccount.com3b57b4f2013-04-13 03:28:29 +0000181unsigned int Framebuffer::getDepthbufferSerial() const
daniel@transgaming.com339ae702010-05-12 03:40:20 +0000182{
Geoff Langc90d73a2013-07-22 16:39:23 -0400183 Renderbuffer *depthbuffer = mDepthbuffer.get();
daniel@transgaming.com339ae702010-05-12 03:40:20 +0000184
185 if (depthbuffer)
186 {
187 return depthbuffer->getSerial();
188 }
189
190 return 0;
191}
192
shannon.woods%transgaming.com@gtempaccount.com3b57b4f2013-04-13 03:28:29 +0000193unsigned int Framebuffer::getStencilbufferSerial() const
daniel@transgaming.com4cbc5902010-08-24 19:20:26 +0000194{
Geoff Langc90d73a2013-07-22 16:39:23 -0400195 Renderbuffer *stencilbuffer = mStencilbuffer.get();
daniel@transgaming.com4cbc5902010-08-24 19:20:26 +0000196
197 if (stencilbuffer)
198 {
199 return stencilbuffer->getSerial();
200 }
201
202 return 0;
203}
204
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000205Renderbuffer *Framebuffer::getColorbuffer(unsigned int colorAttachment) const
206{
207 ASSERT(colorAttachment < IMPLEMENTATION_MAX_DRAW_BUFFERS);
Geoff Langc90d73a2013-07-22 16:39:23 -0400208 return mColorbuffers[colorAttachment].get();
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000209}
210
shannon.woods%transgaming.com@gtempaccount.com3b57b4f2013-04-13 03:28:29 +0000211Renderbuffer *Framebuffer::getDepthbuffer() const
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000212{
Geoff Langc90d73a2013-07-22 16:39:23 -0400213 return mDepthbuffer.get();
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000214}
215
shannon.woods%transgaming.com@gtempaccount.com3b57b4f2013-04-13 03:28:29 +0000216Renderbuffer *Framebuffer::getStencilbuffer() const
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000217{
Geoff Langc90d73a2013-07-22 16:39:23 -0400218 return mStencilbuffer.get();
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000219}
220
shannon.woods%transgaming.com@gtempaccount.com3b57b4f2013-04-13 03:28:29 +0000221Renderbuffer *Framebuffer::getDepthOrStencilbuffer() const
daniel@transgaming.comd2b47022012-11-28 19:40:10 +0000222{
Geoff Langc90d73a2013-07-22 16:39:23 -0400223 Renderbuffer *depthstencilbuffer = mDepthbuffer.get();
daniel@transgaming.comd2b47022012-11-28 19:40:10 +0000224
225 if (!depthstencilbuffer)
226 {
Geoff Langc90d73a2013-07-22 16:39:23 -0400227 depthstencilbuffer = mStencilbuffer.get();
daniel@transgaming.comd2b47022012-11-28 19:40:10 +0000228 }
229
230 return depthstencilbuffer;
231}
232
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000233Renderbuffer *Framebuffer::getReadColorbuffer() const
234{
235 // Will require more logic if glReadBuffers is supported
Geoff Langc90d73a2013-07-22 16:39:23 -0400236 return mColorbuffers[0].get();
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000237}
238
shannon.woods%transgaming.com@gtempaccount.comf6863e02013-04-13 03:34:00 +0000239GLenum Framebuffer::getReadColorbufferType() const
240{
241 // Will require more logic if glReadBuffers is supported
Geoff Langc90d73a2013-07-22 16:39:23 -0400242 return mColorbuffers[0].type();
shannon.woods%transgaming.com@gtempaccount.comf6863e02013-04-13 03:34:00 +0000243}
244
shannon.woods%transgaming.com@gtempaccount.com882434c2013-04-13 03:34:14 +0000245Renderbuffer *Framebuffer::getFirstColorbuffer() const
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000246{
247 for (unsigned int colorAttachment = 0; colorAttachment < IMPLEMENTATION_MAX_DRAW_BUFFERS; colorAttachment++)
248 {
Geoff Langc90d73a2013-07-22 16:39:23 -0400249 if (mColorbuffers[colorAttachment].type() != GL_NONE)
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000250 {
Geoff Langc90d73a2013-07-22 16:39:23 -0400251 return mColorbuffers[colorAttachment].get();
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000252 }
253 }
254
255 return NULL;
256}
257
258GLenum Framebuffer::getColorbufferType(unsigned int colorAttachment) const
259{
260 ASSERT(colorAttachment < IMPLEMENTATION_MAX_DRAW_BUFFERS);
Geoff Langc90d73a2013-07-22 16:39:23 -0400261 return mColorbuffers[colorAttachment].type();
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000262}
263
shannon.woods%transgaming.com@gtempaccount.com3b57b4f2013-04-13 03:28:29 +0000264GLenum Framebuffer::getDepthbufferType() const
daniel@transgaming.comc46c9c02010-04-23 18:34:55 +0000265{
Geoff Langc90d73a2013-07-22 16:39:23 -0400266 return mDepthbuffer.type();
daniel@transgaming.comc46c9c02010-04-23 18:34:55 +0000267}
268
shannon.woods%transgaming.com@gtempaccount.com3b57b4f2013-04-13 03:28:29 +0000269GLenum Framebuffer::getStencilbufferType() const
daniel@transgaming.comc46c9c02010-04-23 18:34:55 +0000270{
Geoff Langc90d73a2013-07-22 16:39:23 -0400271 return mStencilbuffer.type();
daniel@transgaming.comc46c9c02010-04-23 18:34:55 +0000272}
273
Geoff Lang55ba29c2013-07-11 16:57:53 -0400274GLenum Framebuffer::getDepthStencilbufferType() const
275{
Geoff Langc90d73a2013-07-22 16:39:23 -0400276 return (mDepthbuffer.id() == mStencilbuffer.id()) ? mDepthbuffer.type() : GL_NONE;
Geoff Lang55ba29c2013-07-11 16:57:53 -0400277}
278
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000279GLuint Framebuffer::getColorbufferHandle(unsigned int colorAttachment) const
280{
281 ASSERT(colorAttachment < IMPLEMENTATION_MAX_DRAW_BUFFERS);
Geoff Langc90d73a2013-07-22 16:39:23 -0400282 return mColorbuffers[colorAttachment].id();
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000283}
284
shannon.woods%transgaming.com@gtempaccount.com3b57b4f2013-04-13 03:28:29 +0000285GLuint Framebuffer::getDepthbufferHandle() const
daniel@transgaming.comc46c9c02010-04-23 18:34:55 +0000286{
Geoff Langc90d73a2013-07-22 16:39:23 -0400287 return mDepthbuffer.id();
daniel@transgaming.comc46c9c02010-04-23 18:34:55 +0000288}
289
shannon.woods%transgaming.com@gtempaccount.com3b57b4f2013-04-13 03:28:29 +0000290GLuint Framebuffer::getStencilbufferHandle() const
daniel@transgaming.comc46c9c02010-04-23 18:34:55 +0000291{
Geoff Langc90d73a2013-07-22 16:39:23 -0400292 return mStencilbuffer.id();
daniel@transgaming.comc46c9c02010-04-23 18:34:55 +0000293}
294
Geoff Lang55ba29c2013-07-11 16:57:53 -0400295GLenum Framebuffer::getDepthStencilbufferHandle() const
296{
Geoff Langc90d73a2013-07-22 16:39:23 -0400297 return (mDepthbuffer.id() == mStencilbuffer.id()) ? mDepthbuffer.id() : 0;
298}
299
300GLenum Framebuffer::getColorbufferMipLevel(unsigned int colorAttachment) const
301{
302 ASSERT(colorAttachment < IMPLEMENTATION_MAX_DRAW_BUFFERS);
303 return mColorbuffers[colorAttachment].mipLevel();
304}
305
306GLenum Framebuffer::getDepthbufferMipLevel() const
307{
308 return mDepthbuffer.mipLevel();
309}
310
311GLenum Framebuffer::getStencilbufferMipLevel() const
312{
313 return mStencilbuffer.mipLevel();
314}
315
316GLenum Framebuffer::getDepthStencilbufferMipLevel() const
317{
318 return (mDepthbuffer.id() == mStencilbuffer.id()) ? mDepthbuffer.mipLevel() : 0;
319}
320
321GLenum Framebuffer::getColorbufferLayer(unsigned int colorAttachment) const
322{
323 ASSERT(colorAttachment < IMPLEMENTATION_MAX_DRAW_BUFFERS);
324 return mColorbuffers[colorAttachment].layer();
325}
326
327GLenum Framebuffer::getDepthbufferLayer() const
328{
329 return mDepthbuffer.layer();
330}
331
332GLenum Framebuffer::getStencilbufferLayer() const
333{
334 return mStencilbuffer.layer();
335}
336
337GLenum Framebuffer::getDepthStencilbufferLayer() const
338{
339 return (mDepthbuffer.id() == mStencilbuffer.id()) ? mDepthbuffer.layer() : 0;
Geoff Lang55ba29c2013-07-11 16:57:53 -0400340}
341
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000342GLenum Framebuffer::getDrawBufferState(unsigned int colorAttachment) const
343{
344 return mDrawBufferStates[colorAttachment];
345}
346
347void Framebuffer::setDrawBufferState(unsigned int colorAttachment, GLenum drawBuffer)
348{
349 mDrawBufferStates[colorAttachment] = drawBuffer;
350}
351
shannon.woods%transgaming.com@gtempaccount.comdae24092013-04-13 03:31:31 +0000352bool Framebuffer::isEnabledColorAttachment(unsigned int colorAttachment) const
353{
Geoff Langc90d73a2013-07-22 16:39:23 -0400354 return (mColorbuffers[colorAttachment].type() != GL_NONE && mDrawBufferStates[colorAttachment] != GL_NONE);
shannon.woods%transgaming.com@gtempaccount.comdae24092013-04-13 03:31:31 +0000355}
356
357bool Framebuffer::hasEnabledColorAttachment() const
358{
359 for (unsigned int colorAttachment = 0; colorAttachment < gl::IMPLEMENTATION_MAX_DRAW_BUFFERS; colorAttachment++)
360 {
361 if (isEnabledColorAttachment(colorAttachment))
362 {
363 return true;
364 }
365 }
366
367 return false;
368}
369
shannon.woods%transgaming.com@gtempaccount.com3b57b4f2013-04-13 03:28:29 +0000370bool Framebuffer::hasStencil() const
daniel@transgaming.coma27ff1e2010-08-24 19:20:11 +0000371{
Geoff Langc90d73a2013-07-22 16:39:23 -0400372 if (mStencilbuffer.type() != GL_NONE)
daniel@transgaming.coma27ff1e2010-08-24 19:20:11 +0000373 {
shannon.woods%transgaming.com@gtempaccount.com3b57b4f2013-04-13 03:28:29 +0000374 const Renderbuffer *stencilbufferObject = getStencilbuffer();
daniel@transgaming.coma27ff1e2010-08-24 19:20:11 +0000375
376 if (stencilbufferObject)
377 {
378 return stencilbufferObject->getStencilSize() > 0;
379 }
380 }
381
382 return false;
383}
384
shannonwoods@chromium.org24ac8502013-05-30 00:01:37 +0000385bool Framebuffer::usingExtendedDrawBuffers() const
386{
387 for (unsigned int colorAttachment = 1; colorAttachment < IMPLEMENTATION_MAX_DRAW_BUFFERS; colorAttachment++)
388 {
389 if (isEnabledColorAttachment(colorAttachment))
390 {
391 return true;
392 }
393 }
394
395 return false;
396}
397
shannon.woods%transgaming.com@gtempaccount.com3b57b4f2013-04-13 03:28:29 +0000398GLenum Framebuffer::completeness() const
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000399{
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000400 int width = 0;
401 int height = 0;
shannonwoods@chromium.orgf6fb9592013-05-30 00:09:40 +0000402 unsigned int colorbufferSize = 0;
daniel@transgaming.com1f135d82010-08-24 19:20:36 +0000403 int samples = -1;
daniel@transgaming.com6b7c84c2012-05-31 01:14:39 +0000404 bool missingAttachment = true;
shannonwoods@chromium.orgf6fb9592013-05-30 00:09:40 +0000405 GLuint clientVersion = mRenderer->getCurrentClientVersion();
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000406
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000407 for (unsigned int colorAttachment = 0; colorAttachment < IMPLEMENTATION_MAX_DRAW_BUFFERS; colorAttachment++)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000408 {
Geoff Langc90d73a2013-07-22 16:39:23 -0400409 if (mColorbuffers[colorAttachment].type() != GL_NONE)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000410 {
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000411 const Renderbuffer *colorbuffer = getColorbuffer(colorAttachment);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000412
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000413 if (!colorbuffer)
daniel@transgaming.comedc19182010-10-15 17:57:55 +0000414 {
415 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
416 }
daniel@transgaming.comd885df02012-05-31 01:14:36 +0000417
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000418 if (colorbuffer->getWidth() == 0 || colorbuffer->getHeight() == 0)
daniel@transgaming.com6b7c84c2012-05-31 01:14:39 +0000419 {
420 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
421 }
daniel@transgaming.com01868132010-08-24 19:21:17 +0000422
Geoff Langc90d73a2013-07-22 16:39:23 -0400423 if (mColorbuffers[colorAttachment].type() == GL_RENDERBUFFER)
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000424 {
shannonwoods@chromium.orgf6fb9592013-05-30 00:09:40 +0000425 if (!gl::IsColorRenderingSupported(colorbuffer->getInternalFormat(), mRenderer))
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000426 {
427 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
428 }
429 }
Geoff Langc90d73a2013-07-22 16:39:23 -0400430 else if (IsInternalTextureTarget(mColorbuffers[colorAttachment].type()))
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000431 {
432 GLint internalformat = colorbuffer->getInternalFormat();
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000433
shannonwoods@chromium.orgf6fb9592013-05-30 00:09:40 +0000434 if (!gl::IsColorRenderingSupported(internalformat, mRenderer))
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000435 {
436 return GL_FRAMEBUFFER_UNSUPPORTED;
437 }
438
shannonwoods@chromium.orgf6fb9592013-05-30 00:09:40 +0000439 if (gl::GetDepthBits(internalformat, clientVersion) > 0 ||
440 gl::GetStencilBits(internalformat, clientVersion) > 0)
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000441 {
442 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
443 }
444 }
445 else
446 {
447 UNREACHABLE();
448 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
449 }
450
451 if (!missingAttachment)
452 {
453 // all color attachments must have the same width and height
454 if (colorbuffer->getWidth() != width || colorbuffer->getHeight() != height)
455 {
456 return GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS;
457 }
458
459 // APPLE_framebuffer_multisample, which EXT_draw_buffers refers to, requires that
460 // all color attachments have the same number of samples for the FBO to be complete.
461 if (colorbuffer->getSamples() != samples)
462 {
463 return GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE_EXT;
464 }
465
shannon.woods%transgaming.com@gtempaccount.comc3471522013-04-13 03:34:52 +0000466 // in GLES 2.0, all color attachments attachments must have the same number of bitplanes
467 // in GLES 3.0, there is no such restriction
shannonwoods@chromium.orgf6fb9592013-05-30 00:09:40 +0000468 if (clientVersion < 3)
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000469 {
shannonwoods@chromium.orgf6fb9592013-05-30 00:09:40 +0000470 if (gl::GetPixelBytes(colorbuffer->getInternalFormat(), clientVersion) != colorbufferSize)
shannon.woods%transgaming.com@gtempaccount.comc3471522013-04-13 03:34:52 +0000471 {
472 return GL_FRAMEBUFFER_UNSUPPORTED;
473 }
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000474 }
475
476 // D3D11 does not allow for overlapping RenderTargetViews, so ensure uniqueness
477 for (unsigned int previousColorAttachment = 0; previousColorAttachment < colorAttachment; previousColorAttachment++)
478 {
Geoff Langc90d73a2013-07-22 16:39:23 -0400479 if (mColorbuffers[colorAttachment].get() == mColorbuffers[previousColorAttachment].get())
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000480 {
481 return GL_FRAMEBUFFER_UNSUPPORTED;
482 }
483 }
484 }
485 else
486 {
487 width = colorbuffer->getWidth();
488 height = colorbuffer->getHeight();
489 samples = colorbuffer->getSamples();
shannonwoods@chromium.orgf6fb9592013-05-30 00:09:40 +0000490 colorbufferSize = gl::GetPixelBytes(colorbuffer->getInternalFormat(), clientVersion);
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000491 missingAttachment = false;
492 }
493 }
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000494 }
495
shannon.woods%transgaming.com@gtempaccount.com3b57b4f2013-04-13 03:28:29 +0000496 const Renderbuffer *depthbuffer = NULL;
497 const Renderbuffer *stencilbuffer = NULL;
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000498
Geoff Langc90d73a2013-07-22 16:39:23 -0400499 if (mDepthbuffer.type() != GL_NONE)
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000500 {
501 depthbuffer = getDepthbuffer();
502
503 if (!depthbuffer)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000504 {
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000505 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000506 }
507
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000508 if (depthbuffer->getWidth() == 0 || depthbuffer->getHeight() == 0)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000509 {
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000510 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
511 }
512
Geoff Langc90d73a2013-07-22 16:39:23 -0400513 if (mDepthbuffer.type() == GL_RENDERBUFFER)
daniel@transgaming.com6b7c84c2012-05-31 01:14:39 +0000514 {
shannonwoods@chromium.orgf6fb9592013-05-30 00:09:40 +0000515 if (!gl::IsDepthRenderingSupported(depthbuffer->getInternalFormat(), mRenderer))
daniel@transgaming.com6b7c84c2012-05-31 01:14:39 +0000516 {
517 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
518 }
519 }
Geoff Langc90d73a2013-07-22 16:39:23 -0400520 else if (IsInternalTextureTarget(mDepthbuffer.type()))
daniel@transgaming.com6b7c84c2012-05-31 01:14:39 +0000521 {
daniel@transgaming.com8e91d252012-10-17 18:22:44 +0000522 GLint internalformat = depthbuffer->getInternalFormat();
daniel@transgaming.com6b7c84c2012-05-31 01:14:39 +0000523
524 // depth texture attachments require OES/ANGLE_depth_texture
daniel@transgaming.comea32d482012-11-28 19:33:18 +0000525 if (!mRenderer->getDepthTextureSupport())
daniel@transgaming.com6b7c84c2012-05-31 01:14:39 +0000526 {
527 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
528 }
529
shannonwoods@chromium.orgf6fb9592013-05-30 00:09:40 +0000530 if (gl::GetDepthBits(internalformat, clientVersion) == 0)
daniel@transgaming.com6b7c84c2012-05-31 01:14:39 +0000531 {
532 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
533 }
534 }
535 else
536 {
537 UNREACHABLE();
538 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
539 }
540
541 if (missingAttachment)
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000542 {
543 width = depthbuffer->getWidth();
544 height = depthbuffer->getHeight();
daniel@transgaming.com6b7c84c2012-05-31 01:14:39 +0000545 samples = depthbuffer->getSamples();
546 missingAttachment = false;
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000547 }
548 else if (width != depthbuffer->getWidth() || height != depthbuffer->getHeight())
549 {
550 return GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS;
551 }
daniel@transgaming.com1f135d82010-08-24 19:20:36 +0000552 else if (samples != depthbuffer->getSamples())
553 {
554 return GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE_ANGLE;
555 }
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000556 }
557
Geoff Langc90d73a2013-07-22 16:39:23 -0400558 if (mStencilbuffer.type() != GL_NONE)
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000559 {
560 stencilbuffer = getStencilbuffer();
561
562 if (!stencilbuffer)
563 {
564 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
565 }
566
567 if (stencilbuffer->getWidth() == 0 || stencilbuffer->getHeight() == 0)
568 {
569 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
570 }
571
Geoff Langc90d73a2013-07-22 16:39:23 -0400572 if (mStencilbuffer.type() == GL_RENDERBUFFER)
daniel@transgaming.com6b7c84c2012-05-31 01:14:39 +0000573 {
shannonwoods@chromium.orgf6fb9592013-05-30 00:09:40 +0000574 if (!gl::IsStencilRenderingSupported(stencilbuffer->getInternalFormat(), mRenderer))
daniel@transgaming.com6b7c84c2012-05-31 01:14:39 +0000575 {
576 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
577 }
578 }
Geoff Langc90d73a2013-07-22 16:39:23 -0400579 else if (IsInternalTextureTarget(mStencilbuffer.type()))
daniel@transgaming.com6b7c84c2012-05-31 01:14:39 +0000580 {
daniel@transgaming.com8e91d252012-10-17 18:22:44 +0000581 GLint internalformat = stencilbuffer->getInternalFormat();
daniel@transgaming.com6b7c84c2012-05-31 01:14:39 +0000582
583 // texture stencil attachments come along as part
584 // of OES_packed_depth_stencil + OES/ANGLE_depth_texture
daniel@transgaming.comea32d482012-11-28 19:33:18 +0000585 if (!mRenderer->getDepthTextureSupport())
daniel@transgaming.com6b7c84c2012-05-31 01:14:39 +0000586 {
587 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
588 }
589
shannonwoods@chromium.orgf6fb9592013-05-30 00:09:40 +0000590 if (gl::GetStencilBits(internalformat, clientVersion) == 0)
daniel@transgaming.com6b7c84c2012-05-31 01:14:39 +0000591 {
592 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
593 }
594 }
595 else
596 {
597 UNREACHABLE();
598 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
599 }
600
601 if (missingAttachment)
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000602 {
603 width = stencilbuffer->getWidth();
604 height = stencilbuffer->getHeight();
daniel@transgaming.com6b7c84c2012-05-31 01:14:39 +0000605 samples = stencilbuffer->getSamples();
606 missingAttachment = false;
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000607 }
608 else if (width != stencilbuffer->getWidth() || height != stencilbuffer->getHeight())
609 {
610 return GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS;
611 }
daniel@transgaming.com1f135d82010-08-24 19:20:36 +0000612 else if (samples != stencilbuffer->getSamples())
613 {
614 return GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE_ANGLE;
615 }
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000616 }
617
daniel@transgaming.com6b7c84c2012-05-31 01:14:39 +0000618 // if we have both a depth and stencil buffer, they must refer to the same object
619 // since we only support packed_depth_stencil and not separate depth and stencil
620 if (depthbuffer && stencilbuffer && (depthbuffer != stencilbuffer))
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000621 {
daniel@transgaming.com6b7c84c2012-05-31 01:14:39 +0000622 return GL_FRAMEBUFFER_UNSUPPORTED;
623 }
624
625 // we need to have at least one attachment to be complete
626 if (missingAttachment)
627 {
628 return GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT;
daniel@transgaming.comcdacc8e2010-07-28 19:20:50 +0000629 }
630
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000631 return GL_FRAMEBUFFER_COMPLETE;
632}
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000633
daniel@transgaming.com16418b12012-11-28 19:32:22 +0000634DefaultFramebuffer::DefaultFramebuffer(rx::Renderer *renderer, Colorbuffer *colorbuffer, DepthStencilbuffer *depthStencil)
635 : Framebuffer(renderer)
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000636{
Geoff Langc90d73a2013-07-22 16:39:23 -0400637 mColorbuffers[0].set(new Renderbuffer(mRenderer, 0, colorbuffer), GL_RENDERBUFFER, 0, 0);
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000638
daniel@transgaming.com70062c92012-11-28 19:32:30 +0000639 Renderbuffer *depthStencilRenderbuffer = new Renderbuffer(mRenderer, 0, depthStencil);
Geoff Langc90d73a2013-07-22 16:39:23 -0400640 mDepthbuffer.set(depthStencilRenderbuffer, (depthStencilRenderbuffer->getDepthSize() != 0) ? GL_RENDERBUFFER : GL_NONE, 0, 0);
641 mStencilbuffer.set(depthStencilRenderbuffer, (depthStencilRenderbuffer->getStencilSize() != 0) ? GL_RENDERBUFFER : GL_NONE, 0, 0);
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000642
643 mDrawBufferStates[0] = GL_BACK;
644 mReadBufferState = GL_BACK;
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000645}
646
shannon.woods%transgaming.com@gtempaccount.com3b57b4f2013-04-13 03:28:29 +0000647int Framebuffer::getSamples() const
daniel@transgaming.com1f135d82010-08-24 19:20:36 +0000648{
649 if (completeness() == GL_FRAMEBUFFER_COMPLETE)
650 {
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000651 // for a complete framebuffer, all attachments must have the same sample count
652 // in this case return the first nonzero sample size
653 for (unsigned int colorAttachment = 0; colorAttachment < IMPLEMENTATION_MAX_DRAW_BUFFERS; colorAttachment++)
654 {
Geoff Langc90d73a2013-07-22 16:39:23 -0400655 if (mColorbuffers[colorAttachment].type() != GL_NONE)
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000656 {
657 return getColorbuffer(colorAttachment)->getSamples();
658 }
659 }
daniel@transgaming.com1f135d82010-08-24 19:20:36 +0000660 }
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000661
662 return 0;
daniel@transgaming.com1f135d82010-08-24 19:20:36 +0000663}
664
shannon.woods%transgaming.com@gtempaccount.com3b57b4f2013-04-13 03:28:29 +0000665GLenum DefaultFramebuffer::completeness() const
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000666{
shannon.woods@transgaming.com3e3da582013-02-28 23:09:03 +0000667 // The default framebuffer *must* always be complete, though it may not be
668 // subject to the same rules as application FBOs. ie, it could have 0x0 size.
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000669 return GL_FRAMEBUFFER_COMPLETE;
670}
671
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000672}