blob: 9a6c38bc94a01dd13b35081de2b57e33dd524e1d [file] [log] [blame]
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001//
2// Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved.
3// Use of this source code is governed by a BSD-style license that can be
4// found in the LICENSE file.
5//
6
7// Framebuffer.cpp: Implements the gl::Framebuffer class. Implements GL framebuffer
8// objects and related functionality. [OpenGL ES 2.0.24] section 4.4 page 105.
9
daniel@transgaming.combbf56f72010-04-20 18:52:13 +000010#include "libGLESv2/Framebuffer.h"
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000011
daniel@transgaming.combbf56f72010-04-20 18:52:13 +000012#include "libGLESv2/main.h"
13#include "libGLESv2/Renderbuffer.h"
14#include "libGLESv2/Texture.h"
daniel@transgaming.com93a81472010-04-20 18:52:58 +000015#include "libGLESv2/utilities.h"
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000016
17namespace gl
18{
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +000019
20Framebuffer::Framebuffer()
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000021{
22 mColorbufferType = GL_NONE;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000023 mDepthbufferType = GL_NONE;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000024 mStencilbufferType = GL_NONE;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000025}
26
27Framebuffer::~Framebuffer()
28{
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +000029 mColorbufferPointer.set(NULL);
30 mDepthbufferPointer.set(NULL);
31 mStencilbufferPointer.set(NULL);
32}
33
34Renderbuffer *Framebuffer::lookupRenderbuffer(GLenum type, GLuint handle) const
35{
36 gl::Context *context = gl::getContext();
37 Renderbuffer *buffer = NULL;
38
39 if (type == GL_NONE)
40 {
41 buffer = NULL;
42 }
43 else if (type == GL_RENDERBUFFER)
44 {
45 buffer = context->getRenderbuffer(handle);
46 }
47 else if (IsTextureTarget(type))
48 {
49 buffer = context->getTexture(handle)->getColorbuffer(type);
50 }
51 else
52 {
53 UNREACHABLE();
54 }
55
56 return buffer;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000057}
58
59void Framebuffer::setColorbuffer(GLenum type, GLuint colorbuffer)
60{
61 mColorbufferType = type;
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +000062 mColorbufferPointer.set(lookupRenderbuffer(type, colorbuffer));
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000063}
64
65void Framebuffer::setDepthbuffer(GLenum type, GLuint depthbuffer)
66{
67 mDepthbufferType = type;
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +000068 mDepthbufferPointer.set(lookupRenderbuffer(type, depthbuffer));
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000069}
70
71void Framebuffer::setStencilbuffer(GLenum type, GLuint stencilbuffer)
72{
73 mStencilbufferType = type;
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +000074 mStencilbufferPointer.set(lookupRenderbuffer(type, stencilbuffer));
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000075}
76
77void Framebuffer::detachTexture(GLuint texture)
78{
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +000079 if (mColorbufferPointer.id() == texture && IsTextureTarget(mColorbufferType))
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000080 {
81 mColorbufferType = GL_NONE;
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +000082 mColorbufferPointer.set(NULL);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000083 }
daniel@transgaming.comfbc09532010-04-26 15:33:41 +000084
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +000085 if (mDepthbufferPointer.id() == texture && IsTextureTarget(mDepthbufferType))
daniel@transgaming.comfbc09532010-04-26 15:33:41 +000086 {
87 mDepthbufferType = GL_NONE;
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +000088 mDepthbufferPointer.set(NULL);
daniel@transgaming.comfbc09532010-04-26 15:33:41 +000089 }
90
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +000091 if (mStencilbufferPointer.id() == texture && IsTextureTarget(mStencilbufferType))
daniel@transgaming.comfbc09532010-04-26 15:33:41 +000092 {
93 mStencilbufferType = GL_NONE;
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +000094 mStencilbufferPointer.set(NULL);
daniel@transgaming.comfbc09532010-04-26 15:33:41 +000095 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000096}
97
98void Framebuffer::detachRenderbuffer(GLuint renderbuffer)
99{
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000100 if (mColorbufferPointer.id() == renderbuffer && mColorbufferType == GL_RENDERBUFFER)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000101 {
102 mColorbufferType = GL_NONE;
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000103 mColorbufferPointer.set(NULL);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000104 }
105
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000106 if (mDepthbufferPointer.id() == renderbuffer && mDepthbufferType == GL_RENDERBUFFER)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000107 {
108 mDepthbufferType = GL_NONE;
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000109 mDepthbufferPointer.set(NULL);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000110 }
111
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000112 if (mStencilbufferPointer.id() == renderbuffer && mStencilbufferType == GL_RENDERBUFFER)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000113 {
114 mStencilbufferType = GL_NONE;
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000115 mStencilbufferPointer.set(NULL);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000116 }
117}
118
daniel@transgaming.com092bd482010-05-12 03:39:36 +0000119unsigned int Framebuffer::getRenderTargetSerial()
120{
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000121 Renderbuffer *colorbuffer = mColorbufferPointer.get();
daniel@transgaming.com092bd482010-05-12 03:39:36 +0000122
123 if (colorbuffer)
124 {
125 return colorbuffer->getSerial();
126 }
127
128 return 0;
129}
130
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000131IDirect3DSurface9 *Framebuffer::getRenderTarget()
132{
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000133 Renderbuffer *colorbuffer = mColorbufferPointer.get();
daniel@transgaming.comfab5a1a2010-03-11 19:22:30 +0000134
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000135 if (colorbuffer)
136 {
137 return colorbuffer->getRenderTarget();
138 }
139
140 return NULL;
141}
142
daniel@transgaming.com339ae702010-05-12 03:40:20 +0000143unsigned int Framebuffer::getDepthbufferSerial()
144{
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000145 Renderbuffer *depthbuffer = mDepthbufferPointer.get();
daniel@transgaming.com339ae702010-05-12 03:40:20 +0000146
147 if (depthbuffer)
148 {
149 return depthbuffer->getSerial();
150 }
151
152 return 0;
153}
154
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000155Colorbuffer *Framebuffer::getColorbuffer()
156{
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000157 Renderbuffer *rb = mColorbufferPointer.get();
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000158
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000159 if (rb != NULL && rb->isColorbuffer())
daniel@transgaming.com93a81472010-04-20 18:52:58 +0000160 {
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000161 return static_cast<Colorbuffer*>(rb->getStorage());
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000162 }
daniel@transgaming.com93a81472010-04-20 18:52:58 +0000163 else
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000164 {
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000165 return NULL;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000166 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000167}
168
daniel@transgaming.comcdacc8e2010-07-28 19:20:50 +0000169DepthStencilbuffer *Framebuffer::getDepthbuffer()
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000170{
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000171 Renderbuffer *rb = mDepthbufferPointer.get();
172
173 if (rb != NULL && rb->isDepthbuffer())
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000174 {
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000175 return static_cast<DepthStencilbuffer*>(rb->getStorage());
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000176 }
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000177 else
178 {
179 return NULL;
180 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000181}
182
daniel@transgaming.comcdacc8e2010-07-28 19:20:50 +0000183DepthStencilbuffer *Framebuffer::getStencilbuffer()
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000184{
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000185 Renderbuffer *rb = mStencilbufferPointer.get();
186
187 if (rb != NULL && rb->isStencilbuffer())
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000188 {
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000189 return static_cast<DepthStencilbuffer*>(rb->getStorage());
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000190 }
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000191 else
192 {
193 return NULL;
194 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000195}
196
daniel@transgaming.comc46c9c02010-04-23 18:34:55 +0000197GLenum Framebuffer::getColorbufferType()
198{
199 return mColorbufferType;
200}
201
202GLenum Framebuffer::getDepthbufferType()
203{
204 return mDepthbufferType;
205}
206
207GLenum Framebuffer::getStencilbufferType()
208{
209 return mStencilbufferType;
210}
211
212GLuint Framebuffer::getColorbufferHandle()
213{
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000214 return mColorbufferPointer.id();
daniel@transgaming.comc46c9c02010-04-23 18:34:55 +0000215}
216
217GLuint Framebuffer::getDepthbufferHandle()
218{
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000219 return mDepthbufferPointer.id();
daniel@transgaming.comc46c9c02010-04-23 18:34:55 +0000220}
221
222GLuint Framebuffer::getStencilbufferHandle()
223{
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000224 return mStencilbufferPointer.id();
daniel@transgaming.comc46c9c02010-04-23 18:34:55 +0000225}
226
daniel@transgaming.coma27ff1e2010-08-24 19:20:11 +0000227bool Framebuffer::hasStencil()
228{
229 if (mStencilbufferType != GL_NONE)
230 {
231 DepthStencilbuffer *stencilbufferObject = getStencilbuffer();
232
233 if (stencilbufferObject)
234 {
235 return stencilbufferObject->getStencilSize() > 0;
236 }
237 }
238
239 return false;
240}
241
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000242GLenum Framebuffer::completeness()
243{
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000244 int width = 0;
245 int height = 0;
246
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000247 if (mColorbufferType != GL_NONE)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000248 {
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000249 Colorbuffer *colorbuffer = getColorbuffer();
250
251 if (!colorbuffer)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000252 {
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000253 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000254 }
255
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000256 if (colorbuffer->getWidth() == 0 || colorbuffer->getHeight() == 0)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000257 {
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000258 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000259 }
260
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000261 width = colorbuffer->getWidth();
262 height = colorbuffer->getHeight();
263 }
264 else
265 {
266 return GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT;
267 }
268
269 DepthStencilbuffer *depthbuffer = NULL;
270 DepthStencilbuffer *stencilbuffer = NULL;
271
272 if (mDepthbufferType != GL_NONE)
273 {
274 depthbuffer = getDepthbuffer();
275
276 if (!depthbuffer)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000277 {
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000278 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000279 }
280
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000281 if (depthbuffer->getWidth() == 0 || depthbuffer->getHeight() == 0)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000282 {
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000283 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
284 }
285
286 if (width == 0)
287 {
288 width = depthbuffer->getWidth();
289 height = depthbuffer->getHeight();
290 }
291 else if (width != depthbuffer->getWidth() || height != depthbuffer->getHeight())
292 {
293 return GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS;
294 }
295 }
296
297 if (mStencilbufferType != GL_NONE)
298 {
299 stencilbuffer = getStencilbuffer();
300
301 if (!stencilbuffer)
302 {
303 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
304 }
305
306 if (stencilbuffer->getWidth() == 0 || stencilbuffer->getHeight() == 0)
307 {
308 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
309 }
310
311 if (width == 0)
312 {
313 width = stencilbuffer->getWidth();
314 height = stencilbuffer->getHeight();
315 }
316 else if (width != stencilbuffer->getWidth() || height != stencilbuffer->getHeight())
317 {
318 return GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS;
319 }
320 }
321
322 if (mDepthbufferType == GL_RENDERBUFFER && mStencilbufferType == GL_RENDERBUFFER)
323 {
324 if (depthbuffer->getFormat() != GL_DEPTH24_STENCIL8_OES ||
325 stencilbuffer->getFormat() != GL_DEPTH24_STENCIL8_OES ||
326 depthbuffer->getSerial() != stencilbuffer->getSerial())
327 {
328 return GL_FRAMEBUFFER_UNSUPPORTED;
daniel@transgaming.comcdacc8e2010-07-28 19:20:50 +0000329 }
330 }
331
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000332 return GL_FRAMEBUFFER_COMPLETE;
333}
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000334
335DefaultFramebuffer::DefaultFramebuffer(Colorbuffer *color, DepthStencilbuffer *depthStencil)
336{
337 mColorbufferType = GL_RENDERBUFFER;
338 mDepthbufferType = GL_RENDERBUFFER;
339 mStencilbufferType = GL_RENDERBUFFER;
340
341 mColorbufferPointer.set(new Renderbuffer(0, color));
342
343 Renderbuffer *depthStencilRenderbuffer = new Renderbuffer(0, depthStencil);
344 mDepthbufferPointer.set(depthStencilRenderbuffer);
345 mStencilbufferPointer.set(depthStencilRenderbuffer);
346}
347
348GLenum DefaultFramebuffer::completeness()
349{
350 return GL_FRAMEBUFFER_COMPLETE;
351}
352
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000353}