initial import
[vuplus_webkit] / Source / ThirdParty / ANGLE / src / libGLESv2 / Framebuffer.cpp
1 //
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
10 #include "libGLESv2/Framebuffer.h"
11
12 #include "libGLESv2/main.h"
13 #include "libGLESv2/Renderbuffer.h"
14 #include "libGLESv2/Texture.h"
15 #include "libGLESv2/utilities.h"
16
17 namespace gl
18 {
19
20 Framebuffer::Framebuffer()
21 {
22     mColorbufferType = GL_NONE;
23     mDepthbufferType = GL_NONE;
24     mStencilbufferType = GL_NONE;
25 }
26
27 Framebuffer::~Framebuffer()
28 {
29     mColorbufferPointer.set(NULL);
30     mDepthbufferPointer.set(NULL);
31     mStencilbufferPointer.set(NULL);
32 }
33
34 Renderbuffer *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)->getRenderbuffer(type);
50     }
51     else
52     {
53         UNREACHABLE();
54     }
55
56     return buffer;
57 }
58
59 void Framebuffer::setColorbuffer(GLenum type, GLuint colorbuffer)
60 {
61     mColorbufferType = type;
62     mColorbufferPointer.set(lookupRenderbuffer(type, colorbuffer));
63 }
64
65 void Framebuffer::setDepthbuffer(GLenum type, GLuint depthbuffer)
66 {
67     mDepthbufferType = type;
68     mDepthbufferPointer.set(lookupRenderbuffer(type, depthbuffer));
69 }
70
71 void Framebuffer::setStencilbuffer(GLenum type, GLuint stencilbuffer)
72 {
73     mStencilbufferType = type;
74     mStencilbufferPointer.set(lookupRenderbuffer(type, stencilbuffer));
75 }
76
77 void Framebuffer::detachTexture(GLuint texture)
78 {
79     if (mColorbufferPointer.id() == texture && IsTextureTarget(mColorbufferType))
80     {
81         mColorbufferType = GL_NONE;
82         mColorbufferPointer.set(NULL);
83     }
84
85     if (mDepthbufferPointer.id() == texture && IsTextureTarget(mDepthbufferType))
86     {
87         mDepthbufferType = GL_NONE;
88         mDepthbufferPointer.set(NULL);
89     }
90
91     if (mStencilbufferPointer.id() == texture && IsTextureTarget(mStencilbufferType))
92     {
93         mStencilbufferType = GL_NONE;
94         mStencilbufferPointer.set(NULL);
95     }
96 }
97
98 void Framebuffer::detachRenderbuffer(GLuint renderbuffer)
99 {
100     if (mColorbufferPointer.id() == renderbuffer && mColorbufferType == GL_RENDERBUFFER)
101     {
102         mColorbufferType = GL_NONE;
103         mColorbufferPointer.set(NULL);
104     }
105
106     if (mDepthbufferPointer.id() == renderbuffer && mDepthbufferType == GL_RENDERBUFFER)
107     {
108         mDepthbufferType = GL_NONE;
109         mDepthbufferPointer.set(NULL);
110     }
111
112     if (mStencilbufferPointer.id() == renderbuffer && mStencilbufferType == GL_RENDERBUFFER)
113     {
114         mStencilbufferType = GL_NONE;
115         mStencilbufferPointer.set(NULL);
116     }
117 }
118
119 unsigned int Framebuffer::getRenderTargetSerial()
120 {
121     Renderbuffer *colorbuffer = mColorbufferPointer.get();
122
123     if (colorbuffer)
124     {
125         return colorbuffer->getSerial();
126     }
127
128     return 0;
129 }
130
131 IDirect3DSurface9 *Framebuffer::getRenderTarget()
132 {
133     Renderbuffer *colorbuffer = mColorbufferPointer.get();
134
135     if (colorbuffer)
136     {
137         return colorbuffer->getRenderTarget();
138     }
139
140     return NULL;
141 }
142
143 IDirect3DSurface9 *Framebuffer::getDepthStencil()
144 {
145     Renderbuffer *depthstencilbuffer = mDepthbufferPointer.get();
146     
147     if (!depthstencilbuffer)
148     {
149         depthstencilbuffer = mStencilbufferPointer.get();
150     }
151
152     if (depthstencilbuffer)
153     {
154         return depthstencilbuffer->getDepthStencil();
155     }
156
157     return NULL;
158 }
159
160 unsigned int Framebuffer::getDepthbufferSerial()
161 {
162     Renderbuffer *depthbuffer = mDepthbufferPointer.get();
163
164     if (depthbuffer)
165     {
166         return depthbuffer->getSerial();
167     }
168
169     return 0;
170 }
171
172 unsigned int Framebuffer::getStencilbufferSerial()
173 {
174     Renderbuffer *stencilbuffer = mStencilbufferPointer.get();
175
176     if (stencilbuffer)
177     {
178         return stencilbuffer->getSerial();
179     }
180
181     return 0;
182 }
183
184 Colorbuffer *Framebuffer::getColorbuffer()
185 {
186     Renderbuffer *rb = mColorbufferPointer.get();
187
188     if (rb != NULL && rb->isColorbuffer())
189     {
190         return static_cast<Colorbuffer*>(rb->getStorage());
191     }
192     else
193     {
194         return NULL;
195     }
196 }
197
198 DepthStencilbuffer *Framebuffer::getDepthbuffer()
199 {
200     Renderbuffer *rb = mDepthbufferPointer.get();
201
202     if (rb != NULL && rb->isDepthbuffer())
203     {
204         return static_cast<DepthStencilbuffer*>(rb->getStorage());
205     }
206     else
207     {
208         return NULL;
209     }
210 }
211
212 DepthStencilbuffer *Framebuffer::getStencilbuffer()
213 {
214     Renderbuffer *rb = mStencilbufferPointer.get();
215
216     if (rb != NULL && rb->isStencilbuffer())
217     {
218         return static_cast<DepthStencilbuffer*>(rb->getStorage());
219     }
220     else
221     {
222         return NULL;
223     }
224 }
225
226 GLenum Framebuffer::getColorbufferType()
227 {
228     return mColorbufferType;
229 }
230
231 GLenum Framebuffer::getDepthbufferType()
232 {
233     return mDepthbufferType;
234 }
235
236 GLenum Framebuffer::getStencilbufferType()
237 {
238     return mStencilbufferType;
239 }
240
241 GLuint Framebuffer::getColorbufferHandle()
242 {
243     return mColorbufferPointer.id();
244 }
245
246 GLuint Framebuffer::getDepthbufferHandle()
247 {
248     return mDepthbufferPointer.id();
249 }
250
251 GLuint Framebuffer::getStencilbufferHandle()
252 {
253     return mStencilbufferPointer.id();
254 }
255
256 bool Framebuffer::hasStencil()
257 {
258     if (mStencilbufferType != GL_NONE)
259     {
260         DepthStencilbuffer *stencilbufferObject = getStencilbuffer();
261
262         if (stencilbufferObject)
263         {
264             return stencilbufferObject->getStencilSize() > 0;
265         }
266     }
267
268     return false;
269 }
270
271 GLenum Framebuffer::completeness()
272 {
273     int width = 0;
274     int height = 0;
275     int samples = -1;
276
277     if (mColorbufferType != GL_NONE)
278     {
279         Colorbuffer *colorbuffer = getColorbuffer();
280
281         if (!colorbuffer)
282         {
283             return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
284         }
285
286         if (colorbuffer->getWidth() == 0 || colorbuffer->getHeight() == 0)
287         {
288             return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
289         }
290
291         if (mColorbufferType == GL_RENDERBUFFER)
292         {
293             if (!gl::IsColorRenderable(colorbuffer->getInternalFormat()))
294             {
295                 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
296             }
297         }
298         else if (IsTextureTarget(mColorbufferType))
299         {
300             if (IsCompressed(colorbuffer->getInternalFormat()))
301             {
302                 return GL_FRAMEBUFFER_UNSUPPORTED;
303             }
304
305             if ((colorbuffer->getType() == GL_FLOAT && !getContext()->supportsFloatRenderableTextures()) || 
306                 (colorbuffer->getType() == GL_HALF_FLOAT_OES && !getContext()->supportsHalfFloatRenderableTextures()))
307             {
308                 return GL_FRAMEBUFFER_UNSUPPORTED;
309             }
310
311             if (colorbuffer->getInternalFormat() == GL_LUMINANCE || colorbuffer->getInternalFormat() == GL_LUMINANCE_ALPHA)
312             {
313                 return GL_FRAMEBUFFER_UNSUPPORTED;
314             }
315         }
316         else UNREACHABLE();
317
318         width = colorbuffer->getWidth();
319         height = colorbuffer->getHeight();
320         samples = colorbuffer->getSamples();
321     }
322     else
323     {
324         return GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT;
325     }
326
327     DepthStencilbuffer *depthbuffer = NULL;
328     DepthStencilbuffer *stencilbuffer = NULL;
329
330     if (mDepthbufferType != GL_NONE)
331     {
332         if (mDepthbufferType != GL_RENDERBUFFER)
333         {
334             return GL_FRAMEBUFFER_UNSUPPORTED;   // Requires GL_OES_depth_texture
335         }
336
337         depthbuffer = getDepthbuffer();
338
339         if (!depthbuffer)
340         {
341             return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
342         }
343
344         if (depthbuffer->getWidth() == 0 || depthbuffer->getHeight() == 0)
345         {
346             return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
347         }
348
349         if (width == 0)
350         {
351             width = depthbuffer->getWidth();
352             height = depthbuffer->getHeight();
353         }
354         else if (width != depthbuffer->getWidth() || height != depthbuffer->getHeight())
355         {
356             return GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS;
357         }
358
359         if (samples == -1)
360         {
361             samples = depthbuffer->getSamples();
362         }
363         else if (samples != depthbuffer->getSamples())
364         {
365             return GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE_ANGLE;
366         }
367     }
368
369     if (mStencilbufferType != GL_NONE)
370     {
371         if (mStencilbufferType != GL_RENDERBUFFER)
372         {
373             return GL_FRAMEBUFFER_UNSUPPORTED;
374         }
375
376         stencilbuffer = getStencilbuffer();
377
378         if (!stencilbuffer)
379         {
380             return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
381         }
382
383         if (stencilbuffer->getWidth() == 0 || stencilbuffer->getHeight() == 0)
384         {
385             return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
386         }
387
388         if (width == 0)
389         {
390             width = stencilbuffer->getWidth();
391             height = stencilbuffer->getHeight();
392         }
393         else if (width != stencilbuffer->getWidth() || height != stencilbuffer->getHeight())
394         {
395             return GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS;
396         }
397
398         if (samples == -1)
399         {
400             samples = stencilbuffer->getSamples();
401         }
402         else if (samples != stencilbuffer->getSamples())
403         {
404             return GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE_ANGLE;
405         }
406     }
407
408     if (mDepthbufferType == GL_RENDERBUFFER && mStencilbufferType == GL_RENDERBUFFER)
409     {
410         if (depthbuffer->getInternalFormat() != GL_DEPTH24_STENCIL8_OES ||
411             stencilbuffer->getInternalFormat() != GL_DEPTH24_STENCIL8_OES ||
412             depthbuffer->getSerial() != stencilbuffer->getSerial())
413         {
414             return GL_FRAMEBUFFER_UNSUPPORTED;
415         }
416     }
417
418     return GL_FRAMEBUFFER_COMPLETE;
419 }
420
421 DefaultFramebuffer::DefaultFramebuffer(Colorbuffer *color, DepthStencilbuffer *depthStencil)
422 {
423     mColorbufferType = GL_RENDERBUFFER;
424     mDepthbufferType = (depthStencil->getDepthSize() != 0) ? GL_RENDERBUFFER : GL_NONE;
425     mStencilbufferType = (depthStencil->getStencilSize() != 0) ? GL_RENDERBUFFER : GL_NONE;
426
427     mColorbufferPointer.set(new Renderbuffer(0, color));
428
429     Renderbuffer *depthStencilRenderbuffer = new Renderbuffer(0, depthStencil);
430     mDepthbufferPointer.set(depthStencilRenderbuffer);
431     mStencilbufferPointer.set(depthStencilRenderbuffer);
432 }
433
434 int Framebuffer::getSamples()
435 {
436     if (completeness() == GL_FRAMEBUFFER_COMPLETE)
437     {
438         return getColorbuffer()->getSamples();
439     }
440     else
441     {
442         return 0;
443     }
444 }
445
446 GLenum DefaultFramebuffer::completeness()
447 {
448     // The default framebuffer should always be complete
449     ASSERT(Framebuffer::completeness() == GL_FRAMEBUFFER_COMPLETE);
450
451     return GL_FRAMEBUFFER_COMPLETE;
452 }
453
454 }