Coverage Report

Created: 2018-09-25 14:53

/src/mozilla-central/gfx/gl/MozFramebuffer.cpp
Line
Count
Source (jump to first uncovered line)
1
/* -*- Mode: c++; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 40; -*- */
2
/* This Source Code Form is subject to the terms of the Mozilla Public
3
 * License, v. 2.0. If a copy of the MPL was not distributed with this
4
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
5
6
#include "MozFramebuffer.h"
7
8
#include "GLContext.h"
9
#include "mozilla/gfx/Logging.h"
10
#include "ScopedGLHelpers.h"
11
12
namespace mozilla {
13
namespace gl {
14
15
static void
16
DeleteByTarget(GLContext* const gl, const GLenum target, const GLuint name)
17
0
{
18
0
    if (target == LOCAL_GL_RENDERBUFFER) {
19
0
        gl->DeleteRenderbuffer(name);
20
0
    } else {
21
0
        gl->DeleteTexture(name);
22
0
    }
23
0
}
24
25
UniquePtr<MozFramebuffer>
26
MozFramebuffer::Create(GLContext* const gl, const gfx::IntSize& size,
27
                       const uint32_t samples, const bool depthStencil)
28
0
{
29
0
    if (samples && !gl->IsSupported(GLFeature::framebuffer_multisample))
30
0
        return nullptr;
31
0
32
0
    if (uint32_t(size.width) > gl->MaxTexOrRbSize() ||
33
0
        uint32_t(size.height) > gl->MaxTexOrRbSize() ||
34
0
        samples > gl->MaxSamples())
35
0
    {
36
0
        return nullptr;
37
0
    }
38
0
39
0
    gl->MakeCurrent();
40
0
41
0
    GLContext::LocalErrorScope errorScope(*gl);
42
0
43
0
    GLenum colorTarget;
44
0
    GLuint colorName;
45
0
    if (samples) {
46
0
        colorTarget = LOCAL_GL_RENDERBUFFER;
47
0
        colorName = gl->CreateRenderbuffer();
48
0
        const ScopedBindRenderbuffer bindRB(gl, colorName);
49
0
        gl->fRenderbufferStorageMultisample(colorTarget, samples, LOCAL_GL_RGBA8,
50
0
                                            size.width, size.height);
51
0
    } else {
52
0
        colorTarget = LOCAL_GL_TEXTURE_2D;
53
0
        colorName = gl->CreateTexture();
54
0
        const ScopedBindTexture bindTex(gl, colorName);
55
0
        gl->TexParams_SetClampNoMips();
56
0
        gl->fTexImage2D(colorTarget, 0, LOCAL_GL_RGBA,
57
0
                        size.width, size.height, 0,
58
0
                        LOCAL_GL_RGBA, LOCAL_GL_UNSIGNED_BYTE, nullptr);
59
0
    }
60
0
61
0
    const auto err = errorScope.GetError();
62
0
    if (err) {
63
0
        if (err != LOCAL_GL_OUT_OF_MEMORY) {
64
0
            gfxCriticalNote << "Unexpected error: " << gfx::hexa(err) << ": "
65
0
                            << GLContext::GLErrorToString(err);
66
0
        }
67
0
        DeleteByTarget(gl, colorTarget, colorName);
68
0
        return nullptr;
69
0
    }
70
0
71
0
    return CreateWith(gl, size, samples, depthStencil, colorTarget, colorName);
72
0
}
73
74
UniquePtr<MozFramebuffer>
75
MozFramebuffer::CreateWith(GLContext* const gl, const gfx::IntSize& size,
76
                           const uint32_t samples, const bool depthStencil,
77
                           const GLenum colorTarget, const GLuint colorName)
78
0
{
79
0
    UniquePtr<MozFramebuffer> mozFB(new MozFramebuffer(gl, size, samples, depthStencil,
80
0
                                                       colorTarget, colorName));
81
0
82
0
    const ScopedBindFramebuffer bindFB(gl, mozFB->mFB);
83
0
84
0
    if (colorTarget == LOCAL_GL_RENDERBUFFER) {
85
0
        gl->fFramebufferRenderbuffer(LOCAL_GL_FRAMEBUFFER, LOCAL_GL_COLOR_ATTACHMENT0,
86
0
                                     colorTarget, colorName);
87
0
    } else {
88
0
        gl->fFramebufferTexture2D(LOCAL_GL_FRAMEBUFFER, LOCAL_GL_COLOR_ATTACHMENT0,
89
0
                                  colorTarget, colorName, 0);
90
0
    }
91
0
92
0
    const auto fnAllocRB = [&](GLuint rb, GLenum format) {
93
0
        const ScopedBindRenderbuffer bindRB(gl, rb);
94
0
        if (samples) {
95
0
            gl->fRenderbufferStorageMultisample(LOCAL_GL_RENDERBUFFER, samples, format,
96
0
                                                size.width, size.height);
97
0
        } else {
98
0
            gl->fRenderbufferStorage(LOCAL_GL_RENDERBUFFER, format, size.width,
99
0
                                     size.height);
100
0
        }
101
0
        return rb;
102
0
    };
103
0
104
0
    if (depthStencil) {
105
0
        GLuint depthRB, stencilRB;
106
0
107
0
        {
108
0
            GLContext::LocalErrorScope errorScope(*gl);
109
0
110
0
            if (gl->IsSupported(GLFeature::packed_depth_stencil)) {
111
0
                depthRB = fnAllocRB(mozFB->mDepthRB, LOCAL_GL_DEPTH24_STENCIL8);
112
0
                stencilRB = depthRB; // Ignore unused mStencilRB.
113
0
            } else {
114
0
                depthRB   = fnAllocRB(mozFB->mDepthRB  , LOCAL_GL_DEPTH_COMPONENT24);
115
0
                stencilRB = fnAllocRB(mozFB->mStencilRB, LOCAL_GL_STENCIL_INDEX8);
116
0
            }
117
0
118
0
            const auto err = errorScope.GetError();
119
0
            if (err) {
120
0
                MOZ_ASSERT(err == LOCAL_GL_OUT_OF_MEMORY);
121
0
                return nullptr;
122
0
            }
123
0
        }
124
0
125
0
        gl->fFramebufferRenderbuffer(LOCAL_GL_FRAMEBUFFER, LOCAL_GL_DEPTH_ATTACHMENT,
126
0
                                     LOCAL_GL_RENDERBUFFER, depthRB);
127
0
        gl->fFramebufferRenderbuffer(LOCAL_GL_FRAMEBUFFER, LOCAL_GL_STENCIL_ATTACHMENT,
128
0
                                     LOCAL_GL_RENDERBUFFER, stencilRB);
129
0
    }
130
0
131
0
    const auto status = gl->fCheckFramebufferStatus(LOCAL_GL_FRAMEBUFFER);
132
0
    if (status != LOCAL_GL_FRAMEBUFFER_COMPLETE) {
133
0
        MOZ_ASSERT(false);
134
0
        return nullptr;
135
0
    }
136
0
137
0
    return mozFB;
138
0
}
139
140
////////////////////
141
142
MozFramebuffer::MozFramebuffer(GLContext* const gl, const gfx::IntSize& size,
143
                               const uint32_t samples, const bool depthStencil,
144
                               const GLenum colorTarget, const GLuint colorName)
145
    : mWeakGL(gl)
146
    , mSize(size)
147
    , mSamples(samples)
148
    , mFB(gl->CreateFramebuffer())
149
    , mColorTarget(colorTarget)
150
    , mColorName(colorName)
151
    , mDepthRB(depthStencil ? gl->CreateRenderbuffer() : 0)
152
    , mStencilRB(depthStencil ? gl->CreateRenderbuffer() : 0)
153
0
{
154
0
    MOZ_ASSERT(mColorTarget);
155
0
    MOZ_ASSERT(mColorName);
156
0
}
157
158
MozFramebuffer::~MozFramebuffer()
159
0
{
160
0
    GLContext* const gl = mWeakGL;
161
0
    if (!gl || !gl->MakeCurrent())
162
0
        return;
163
0
164
0
    gl->DeleteFramebuffer(mFB);
165
0
    gl->DeleteRenderbuffer(mDepthRB);
166
0
    gl->DeleteRenderbuffer(mStencilRB);
167
0
168
0
    DeleteByTarget(gl, mColorTarget, mColorName);
169
0
}
170
171
} // namespace gl
172
} // namespace mozilla