~ubuntu-branches/ubuntu/wily/qtbase-opensource-src/wily

« back to all changes in this revision

Viewing changes to src/3rdparty/angle/src/libGLESv2/Framebuffer.cpp

  • Committer: Package Import Robot
  • Author(s): Timo Jyrinki
  • Date: 2013-02-05 12:46:17 UTC
  • Revision ID: package-import@ubuntu.com-20130205124617-c8jouts182j002fx
Tags: upstream-5.0.1+dfsg
ImportĀ upstreamĀ versionĀ 5.0.1+dfsg

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
//
 
2
// Copyright (c) 2002-2012 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
    mNullColorbufferPointer.set(NULL);
 
33
}
 
34
 
 
35
Renderbuffer *Framebuffer::lookupRenderbuffer(GLenum type, GLuint handle) const
 
36
{
 
37
    gl::Context *context = gl::getContext();
 
38
    Renderbuffer *buffer = NULL;
 
39
 
 
40
    if (type == GL_NONE)
 
41
    {
 
42
        buffer = NULL;
 
43
    }
 
44
    else if (type == GL_RENDERBUFFER)
 
45
    {
 
46
        buffer = context->getRenderbuffer(handle);
 
47
    }
 
48
    else if (IsInternalTextureTarget(type))
 
49
    {
 
50
        buffer = context->getTexture(handle)->getRenderbuffer(type);
 
51
    }
 
52
    else
 
53
    {
 
54
        UNREACHABLE();
 
55
    }
 
56
 
 
57
    return buffer;
 
58
}
 
59
 
 
60
void Framebuffer::setColorbuffer(GLenum type, GLuint colorbuffer)
 
61
{
 
62
    mColorbufferType = (colorbuffer != 0) ? type : GL_NONE;
 
63
    mColorbufferPointer.set(lookupRenderbuffer(type, colorbuffer));
 
64
}
 
65
 
 
66
void Framebuffer::setDepthbuffer(GLenum type, GLuint depthbuffer)
 
67
{
 
68
    mDepthbufferType = (depthbuffer != 0) ? type : GL_NONE;
 
69
    mDepthbufferPointer.set(lookupRenderbuffer(type, depthbuffer));
 
70
}
 
71
 
 
72
void Framebuffer::setStencilbuffer(GLenum type, GLuint stencilbuffer)
 
73
{
 
74
    mStencilbufferType = (stencilbuffer != 0) ? type : GL_NONE;
 
75
    mStencilbufferPointer.set(lookupRenderbuffer(type, stencilbuffer));
 
76
}
 
77
 
 
78
void Framebuffer::detachTexture(GLuint texture)
 
79
{
 
80
    if (mColorbufferPointer.id() == texture && IsInternalTextureTarget(mColorbufferType))
 
81
    {
 
82
        mColorbufferType = GL_NONE;
 
83
        mColorbufferPointer.set(NULL);
 
84
    }
 
85
 
 
86
    if (mDepthbufferPointer.id() == texture && IsInternalTextureTarget(mDepthbufferType))
 
87
    {
 
88
        mDepthbufferType = GL_NONE;
 
89
        mDepthbufferPointer.set(NULL);
 
90
    }
 
91
 
 
92
    if (mStencilbufferPointer.id() == texture && IsInternalTextureTarget(mStencilbufferType))
 
93
    {
 
94
        mStencilbufferType = GL_NONE;
 
95
        mStencilbufferPointer.set(NULL);
 
96
    }
 
97
}
 
98
 
 
99
void Framebuffer::detachRenderbuffer(GLuint renderbuffer)
 
100
{
 
101
    if (mColorbufferPointer.id() == renderbuffer && mColorbufferType == GL_RENDERBUFFER)
 
102
    {
 
103
        mColorbufferType = GL_NONE;
 
104
        mColorbufferPointer.set(NULL);
 
105
    }
 
106
 
 
107
    if (mDepthbufferPointer.id() == renderbuffer && mDepthbufferType == GL_RENDERBUFFER)
 
108
    {
 
109
        mDepthbufferType = GL_NONE;
 
110
        mDepthbufferPointer.set(NULL);
 
111
    }
 
112
 
 
113
    if (mStencilbufferPointer.id() == renderbuffer && mStencilbufferType == GL_RENDERBUFFER)
 
114
    {
 
115
        mStencilbufferType = GL_NONE;
 
116
        mStencilbufferPointer.set(NULL);
 
117
    }
 
118
}
 
119
 
 
120
unsigned int Framebuffer::getRenderTargetSerial()
 
121
{
 
122
    Renderbuffer *colorbuffer = mColorbufferPointer.get();
 
123
 
 
124
    if (colorbuffer)
 
125
    {
 
126
        return colorbuffer->getSerial();
 
127
    }
 
128
 
 
129
    return 0;
 
130
}
 
131
 
 
132
// Increments refcount on surface.
 
133
// caller must Release() the returned surface
 
134
IDirect3DSurface9 *Framebuffer::getRenderTarget()
 
135
{
 
136
    Renderbuffer *colorbuffer = mColorbufferPointer.get();
 
137
 
 
138
    if (colorbuffer)
 
139
    {
 
140
        return colorbuffer->getRenderTarget();
 
141
    }
 
142
 
 
143
    return NULL;
 
144
}
 
145
 
 
146
// Increments refcount on surface.
 
147
// caller must Release() the returned surface
 
148
IDirect3DSurface9 *Framebuffer::getDepthStencil()
 
149
{
 
150
    Renderbuffer *depthstencilbuffer = mDepthbufferPointer.get();
 
151
    
 
152
    if (!depthstencilbuffer)
 
153
    {
 
154
        depthstencilbuffer = mStencilbufferPointer.get();
 
155
    }
 
156
 
 
157
    if (depthstencilbuffer)
 
158
    {
 
159
        return depthstencilbuffer->getDepthStencil();
 
160
    }
 
161
 
 
162
    return NULL;
 
163
}
 
164
 
 
165
unsigned int Framebuffer::getDepthbufferSerial()
 
166
{
 
167
    Renderbuffer *depthbuffer = mDepthbufferPointer.get();
 
168
 
 
169
    if (depthbuffer)
 
170
    {
 
171
        return depthbuffer->getSerial();
 
172
    }
 
173
 
 
174
    return 0;
 
175
}
 
176
 
 
177
unsigned int Framebuffer::getStencilbufferSerial()
 
178
{
 
179
    Renderbuffer *stencilbuffer = mStencilbufferPointer.get();
 
180
 
 
181
    if (stencilbuffer)
 
182
    {
 
183
        return stencilbuffer->getSerial();
 
184
    }
 
185
 
 
186
    return 0;
 
187
}
 
188
 
 
189
Renderbuffer *Framebuffer::getColorbuffer()
 
190
{
 
191
    return mColorbufferPointer.get();
 
192
}
 
193
 
 
194
Renderbuffer *Framebuffer::getDepthbuffer()
 
195
{
 
196
    return mDepthbufferPointer.get();
 
197
}
 
198
 
 
199
Renderbuffer *Framebuffer::getStencilbuffer()
 
200
{
 
201
    return mStencilbufferPointer.get();
 
202
}
 
203
 
 
204
Renderbuffer *Framebuffer::getNullColorbuffer()
 
205
{
 
206
    Renderbuffer *nullbuffer  = mNullColorbufferPointer.get();
 
207
    Renderbuffer *depthbuffer = getDepthbuffer();
 
208
 
 
209
    if (!depthbuffer)
 
210
    {
 
211
        ERR("Unexpected null depthbuffer for depth-only FBO.");
 
212
        return NULL;
 
213
    }
 
214
 
 
215
    GLsizei width  = depthbuffer->getWidth();
 
216
    GLsizei height = depthbuffer->getHeight();
 
217
 
 
218
    if (!nullbuffer ||
 
219
        width != nullbuffer->getWidth() || height != nullbuffer->getHeight())
 
220
    {
 
221
        nullbuffer = new Renderbuffer(0, new Colorbuffer(width, height, GL_NONE, 0));
 
222
        mNullColorbufferPointer.set(nullbuffer);
 
223
    }
 
224
 
 
225
    return nullbuffer;
 
226
}
 
227
 
 
228
GLenum Framebuffer::getColorbufferType()
 
229
{
 
230
    return mColorbufferType;
 
231
}
 
232
 
 
233
GLenum Framebuffer::getDepthbufferType()
 
234
{
 
235
    return mDepthbufferType;
 
236
}
 
237
 
 
238
GLenum Framebuffer::getStencilbufferType()
 
239
{
 
240
    return mStencilbufferType;
 
241
}
 
242
 
 
243
GLuint Framebuffer::getColorbufferHandle()
 
244
{
 
245
    return mColorbufferPointer.id();
 
246
}
 
247
 
 
248
GLuint Framebuffer::getDepthbufferHandle()
 
249
{
 
250
    return mDepthbufferPointer.id();
 
251
}
 
252
 
 
253
GLuint Framebuffer::getStencilbufferHandle()
 
254
{
 
255
    return mStencilbufferPointer.id();
 
256
}
 
257
 
 
258
bool Framebuffer::hasStencil()
 
259
{
 
260
    if (mStencilbufferType != GL_NONE)
 
261
    {
 
262
        Renderbuffer *stencilbufferObject = getStencilbuffer();
 
263
 
 
264
        if (stencilbufferObject)
 
265
        {
 
266
            return stencilbufferObject->getStencilSize() > 0;
 
267
        }
 
268
    }
 
269
 
 
270
    return false;
 
271
}
 
272
 
 
273
GLenum Framebuffer::completeness()
 
274
{
 
275
    gl::Context *context = gl::getContext();
 
276
    int width = 0;
 
277
    int height = 0;
 
278
    int samples = -1;
 
279
    bool missingAttachment = true;
 
280
 
 
281
    if (mColorbufferType != GL_NONE)
 
282
    {
 
283
        Renderbuffer *colorbuffer = getColorbuffer();
 
284
 
 
285
        if (!colorbuffer)
 
286
        {
 
287
            return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
 
288
        }
 
289
 
 
290
        if (colorbuffer->getWidth() == 0 || colorbuffer->getHeight() == 0)
 
291
        {
 
292
            return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
 
293
        }
 
294
 
 
295
        if (mColorbufferType == GL_RENDERBUFFER)
 
296
        {
 
297
            if (!gl::IsColorRenderable(colorbuffer->getInternalFormat()))
 
298
            {
 
299
                return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
 
300
            }
 
301
        }
 
302
        else if (IsInternalTextureTarget(mColorbufferType))
 
303
        {
 
304
            GLint internalformat = colorbuffer->getInternalFormat();
 
305
            GLenum format = gl::ExtractFormat(internalformat);
 
306
 
 
307
            if (IsCompressed(format) ||
 
308
                format == GL_ALPHA ||
 
309
                format == GL_LUMINANCE ||
 
310
                format == GL_LUMINANCE_ALPHA)
 
311
            {
 
312
                return GL_FRAMEBUFFER_UNSUPPORTED;
 
313
            }
 
314
 
 
315
            if ((gl::IsFloat32Format(internalformat) && !context->supportsFloat32RenderableTextures()) ||
 
316
                (gl::IsFloat16Format(internalformat) && !context->supportsFloat16RenderableTextures()))
 
317
            {
 
318
                return GL_FRAMEBUFFER_UNSUPPORTED;
 
319
            }
 
320
 
 
321
            if (gl::IsDepthTexture(internalformat) || gl::IsStencilTexture(internalformat))
 
322
            {
 
323
                return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
 
324
            }
 
325
        }
 
326
        else
 
327
        {
 
328
            UNREACHABLE();
 
329
            return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
 
330
        }
 
331
 
 
332
        width = colorbuffer->getWidth();
 
333
        height = colorbuffer->getHeight();
 
334
        samples = colorbuffer->getSamples();
 
335
        missingAttachment = false;
 
336
    }
 
337
 
 
338
    Renderbuffer *depthbuffer = NULL;
 
339
    Renderbuffer *stencilbuffer = NULL;
 
340
 
 
341
    if (mDepthbufferType != GL_NONE)
 
342
    {
 
343
        depthbuffer = getDepthbuffer();
 
344
 
 
345
        if (!depthbuffer)
 
346
        {
 
347
            return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
 
348
        }
 
349
 
 
350
        if (depthbuffer->getWidth() == 0 || depthbuffer->getHeight() == 0)
 
351
        {
 
352
            return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
 
353
        }
 
354
 
 
355
        if (mDepthbufferType == GL_RENDERBUFFER)
 
356
        {
 
357
            if (!gl::IsDepthRenderable(depthbuffer->getInternalFormat()))
 
358
            {
 
359
                return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
 
360
            }
 
361
        }
 
362
        else if (IsInternalTextureTarget(mDepthbufferType))
 
363
        {
 
364
            GLint internalformat = depthbuffer->getInternalFormat();
 
365
 
 
366
            // depth texture attachments require OES/ANGLE_depth_texture
 
367
            if (!context->supportsDepthTextures())
 
368
            {
 
369
                return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
 
370
            }
 
371
 
 
372
            if (!gl::IsDepthTexture(internalformat))
 
373
            {
 
374
                return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
 
375
            }
 
376
        }
 
377
        else
 
378
        {
 
379
            UNREACHABLE();
 
380
            return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
 
381
        }
 
382
 
 
383
        if (missingAttachment)
 
384
        {
 
385
            width = depthbuffer->getWidth();
 
386
            height = depthbuffer->getHeight();
 
387
            samples = depthbuffer->getSamples();
 
388
            missingAttachment = false;
 
389
        }
 
390
        else if (width != depthbuffer->getWidth() || height != depthbuffer->getHeight())
 
391
        {
 
392
            return GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS;
 
393
        }
 
394
        else if (samples != depthbuffer->getSamples())
 
395
        {
 
396
            return GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE_ANGLE;
 
397
        }
 
398
    }
 
399
 
 
400
    if (mStencilbufferType != GL_NONE)
 
401
    {
 
402
        stencilbuffer = getStencilbuffer();
 
403
 
 
404
        if (!stencilbuffer)
 
405
        {
 
406
            return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
 
407
        }
 
408
 
 
409
        if (stencilbuffer->getWidth() == 0 || stencilbuffer->getHeight() == 0)
 
410
        {
 
411
            return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
 
412
        }
 
413
 
 
414
        if (mStencilbufferType == GL_RENDERBUFFER)
 
415
        {
 
416
            if (!gl::IsStencilRenderable(stencilbuffer->getInternalFormat()))
 
417
            {
 
418
                return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
 
419
            }
 
420
        }
 
421
        else if (IsInternalTextureTarget(mStencilbufferType))
 
422
        {
 
423
            GLint internalformat = stencilbuffer->getInternalFormat();
 
424
 
 
425
            // texture stencil attachments come along as part
 
426
            // of OES_packed_depth_stencil + OES/ANGLE_depth_texture
 
427
            if (!context->supportsDepthTextures())
 
428
            {
 
429
                return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
 
430
            }
 
431
 
 
432
            if (!gl::IsStencilTexture(internalformat))
 
433
            {
 
434
                return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
 
435
            }
 
436
        }
 
437
        else
 
438
        {
 
439
            UNREACHABLE();
 
440
            return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
 
441
        }
 
442
 
 
443
        if (missingAttachment)
 
444
        {
 
445
            width = stencilbuffer->getWidth();
 
446
            height = stencilbuffer->getHeight();
 
447
            samples = stencilbuffer->getSamples();
 
448
            missingAttachment = false;
 
449
        }
 
450
        else if (width != stencilbuffer->getWidth() || height != stencilbuffer->getHeight())
 
451
        {
 
452
            return GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS;
 
453
        }
 
454
        else if (samples != stencilbuffer->getSamples())
 
455
        {
 
456
            return GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE_ANGLE;
 
457
        }
 
458
    }
 
459
 
 
460
    // if we have both a depth and stencil buffer, they must refer to the same object
 
461
    // since we only support packed_depth_stencil and not separate depth and stencil
 
462
    if (depthbuffer && stencilbuffer && (depthbuffer != stencilbuffer))
 
463
    {
 
464
        return GL_FRAMEBUFFER_UNSUPPORTED;
 
465
    }
 
466
 
 
467
    // we need to have at least one attachment to be complete
 
468
    if (missingAttachment)
 
469
    {
 
470
        return GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT;
 
471
    }
 
472
 
 
473
    return GL_FRAMEBUFFER_COMPLETE;
 
474
}
 
475
 
 
476
DefaultFramebuffer::DefaultFramebuffer(Colorbuffer *colorbuffer, DepthStencilbuffer *depthStencil)
 
477
{
 
478
    mColorbufferPointer.set(new Renderbuffer(0, colorbuffer));
 
479
 
 
480
    Renderbuffer *depthStencilRenderbuffer = new Renderbuffer(0, depthStencil);
 
481
    mDepthbufferPointer.set(depthStencilRenderbuffer);
 
482
    mStencilbufferPointer.set(depthStencilRenderbuffer);
 
483
 
 
484
    mColorbufferType = GL_RENDERBUFFER;
 
485
    mDepthbufferType = (depthStencilRenderbuffer->getDepthSize() != 0) ? GL_RENDERBUFFER : GL_NONE;
 
486
    mStencilbufferType = (depthStencilRenderbuffer->getStencilSize() != 0) ? GL_RENDERBUFFER : GL_NONE;
 
487
}
 
488
 
 
489
int Framebuffer::getSamples()
 
490
{
 
491
    if (completeness() == GL_FRAMEBUFFER_COMPLETE)
 
492
    {
 
493
        return getColorbuffer()->getSamples();
 
494
    }
 
495
    else
 
496
    {
 
497
        return 0;
 
498
    }
 
499
}
 
500
 
 
501
GLenum DefaultFramebuffer::completeness()
 
502
{
 
503
    // The default framebuffer should always be complete
 
504
    ASSERT(Framebuffer::completeness() == GL_FRAMEBUFFER_COMPLETE);
 
505
 
 
506
    return GL_FRAMEBUFFER_COMPLETE;
 
507
}
 
508
 
 
509
}