Coverage Report

Created: 2018-09-25 14:53

/src/mozilla-central/dom/canvas/WebGLContextFramebufferOperations.cpp
Line
Count
Source (jump to first uncovered line)
1
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
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 "WebGLContext.h"
7
#include "WebGLTexture.h"
8
#include "WebGLRenderbuffer.h"
9
#include "WebGLFramebuffer.h"
10
#include "GLContext.h"
11
#include "GLScreenBuffer.h"
12
13
namespace mozilla {
14
15
void
16
WebGLContext::Clear(GLbitfield mask)
17
0
{
18
0
    const FuncScope funcScope(*this, "clear");
19
0
    if (IsContextLost())
20
0
        return;
21
0
22
0
    uint32_t m = mask & (LOCAL_GL_COLOR_BUFFER_BIT | LOCAL_GL_DEPTH_BUFFER_BIT | LOCAL_GL_STENCIL_BUFFER_BIT);
23
0
    if (mask != m)
24
0
        return ErrorInvalidValue("Invalid mask bits.");
25
0
26
0
    if (mask == 0) {
27
0
        GenerateWarning("Calling gl.clear(0) has no effect.");
28
0
    } else if (mRasterizerDiscardEnabled) {
29
0
        GenerateWarning("Calling gl.clear() with RASTERIZER_DISCARD enabled has no effects.");
30
0
    }
31
0
32
0
    if (mask & LOCAL_GL_COLOR_BUFFER_BIT && mBoundDrawFramebuffer) {
33
0
        if (mask & LOCAL_GL_COLOR_BUFFER_BIT) {
34
0
            for (const auto& cur : mBoundDrawFramebuffer->ColorDrawBuffers()) {
35
0
                if (!cur->HasImage())
36
0
                    continue;
37
0
38
0
                switch (cur->Format()->format->componentType) {
39
0
                case webgl::ComponentType::Float:
40
0
                case webgl::ComponentType::NormInt:
41
0
                case webgl::ComponentType::NormUInt:
42
0
                    break;
43
0
44
0
                default:
45
0
                    ErrorInvalidOperation("Color draw buffers must be floating-point"
46
0
                                          " or fixed-point. (normalized (u)ints)");
47
0
                    return;
48
0
                }
49
0
            }
50
0
        }
51
0
    }
52
0
53
0
    if (!BindCurFBForDraw())
54
0
        return;
55
0
56
0
    auto driverMask = mask;
57
0
    if (!mBoundDrawFramebuffer) {
58
0
        if (mNeedsFakeNoDepth) {
59
0
            driverMask &= ~LOCAL_GL_DEPTH_BUFFER_BIT;
60
0
        }
61
0
        if (mNeedsFakeNoStencil) {
62
0
            driverMask &= ~LOCAL_GL_STENCIL_BUFFER_BIT;
63
0
        }
64
0
    }
65
0
66
0
    const ScopedDrawCallWrapper wrapper(*this);
67
0
    gl->fClear(driverMask);
68
0
}
69
70
static GLfloat
71
GLClampFloat(GLfloat val)
72
0
{
73
0
    if (val < 0.0)
74
0
        return 0.0;
75
0
76
0
    if (val > 1.0)
77
0
        return 1.0;
78
0
79
0
    return val;
80
0
}
81
82
void
83
WebGLContext::ClearColor(GLfloat r, GLfloat g, GLfloat b, GLfloat a)
84
0
{
85
0
    const FuncScope funcScope(*this, "clearColor");
86
0
    if (IsContextLost())
87
0
        return;
88
0
89
0
    const bool supportsFloatColorBuffers = (IsExtensionEnabled(WebGLExtensionID::EXT_color_buffer_float) ||
90
0
                                            IsExtensionEnabled(WebGLExtensionID::EXT_color_buffer_half_float) ||
91
0
                                            IsExtensionEnabled(WebGLExtensionID::WEBGL_color_buffer_float));
92
0
    if (!supportsFloatColorBuffers) {
93
0
        r = GLClampFloat(r);
94
0
        g = GLClampFloat(g);
95
0
        b = GLClampFloat(b);
96
0
        a = GLClampFloat(a);
97
0
    }
98
0
99
0
    gl->fClearColor(r, g, b, a);
100
0
101
0
    mColorClearValue[0] = r;
102
0
    mColorClearValue[1] = g;
103
0
    mColorClearValue[2] = b;
104
0
    mColorClearValue[3] = a;
105
0
}
106
107
void
108
WebGLContext::ClearDepth(GLclampf v)
109
0
{
110
0
    const FuncScope funcScope(*this, "clearDepth");
111
0
    if (IsContextLost())
112
0
        return;
113
0
114
0
    mDepthClearValue = GLClampFloat(v);
115
0
    gl->fClearDepth(mDepthClearValue);
116
0
}
117
118
void
119
WebGLContext::ClearStencil(GLint v)
120
0
{
121
0
    const FuncScope funcScope(*this, "clearStencil");
122
0
    if (IsContextLost())
123
0
        return;
124
0
125
0
    mStencilClearValue = v;
126
0
    gl->fClearStencil(v);
127
0
}
128
129
void
130
WebGLContext::ColorMask(WebGLboolean r, WebGLboolean g, WebGLboolean b, WebGLboolean a)
131
0
{
132
0
    const FuncScope funcScope(*this, "colorMask");
133
0
    if (IsContextLost())
134
0
        return;
135
0
136
0
    mColorWriteMask = uint8_t(bool(r)) << 0 |
137
0
                      uint8_t(bool(g)) << 1 |
138
0
                      uint8_t(bool(b)) << 2 |
139
0
                      uint8_t(bool(a)) << 3;
140
0
}
141
142
void
143
WebGLContext::DepthMask(WebGLboolean b)
144
0
{
145
0
    const FuncScope funcScope(*this, "depthMask");
146
0
    if (IsContextLost())
147
0
        return;
148
0
149
0
    mDepthWriteMask = b;
150
0
    gl->fDepthMask(b);
151
0
}
152
153
void
154
WebGLContext::DrawBuffers(const dom::Sequence<GLenum>& buffers)
155
0
{
156
0
    const FuncScope funcScope(*this, "drawBuffers");
157
0
    if (IsContextLost())
158
0
        return;
159
0
160
0
    if (mBoundDrawFramebuffer) {
161
0
        mBoundDrawFramebuffer->DrawBuffers(buffers);
162
0
        return;
163
0
    }
164
0
165
0
    // GLES 3.0.4 p186:
166
0
    // "If the GL is bound to the default framebuffer, then `n` must be 1 and the
167
0
    //  constant must be BACK or NONE. [...] If DrawBuffers is supplied with a
168
0
    //  constant other than BACK and NONE, or with a value of `n` other than 1, the
169
0
    //  error INVALID_OPERATION is generated."
170
0
    if (buffers.Length() != 1) {
171
0
        ErrorInvalidOperation("For the default framebuffer, `buffers` must have a"
172
0
                              " length of 1.");
173
0
        return;
174
0
    }
175
0
176
0
    switch (buffers[0]) {
177
0
    case LOCAL_GL_NONE:
178
0
    case LOCAL_GL_BACK:
179
0
        break;
180
0
181
0
    default:
182
0
        ErrorInvalidOperation("For the default framebuffer, `buffers[0]` must be"
183
0
                              " BACK or NONE.");
184
0
        return;
185
0
    }
186
0
187
0
    mDefaultFB_DrawBuffer0 = buffers[0];
188
0
    // Don't actually set it.
189
0
}
190
191
void
192
WebGLContext::StencilMask(GLuint mask)
193
0
{
194
0
    const FuncScope funcScope(*this, "stencilMask");
195
0
    if (IsContextLost())
196
0
        return;
197
0
198
0
    mStencilWriteMaskFront = mask;
199
0
    mStencilWriteMaskBack = mask;
200
0
201
0
    gl->fStencilMask(mask);
202
0
}
203
204
void
205
WebGLContext::StencilMaskSeparate(GLenum face, GLuint mask)
206
0
{
207
0
    const FuncScope funcScope(*this, "stencilMaskSeparate");
208
0
    if (IsContextLost())
209
0
        return;
210
0
211
0
    if (!ValidateFaceEnum(face))
212
0
        return;
213
0
214
0
    switch (face) {
215
0
        case LOCAL_GL_FRONT_AND_BACK:
216
0
            mStencilWriteMaskFront = mask;
217
0
            mStencilWriteMaskBack = mask;
218
0
            break;
219
0
        case LOCAL_GL_FRONT:
220
0
            mStencilWriteMaskFront = mask;
221
0
            break;
222
0
        case LOCAL_GL_BACK:
223
0
            mStencilWriteMaskBack = mask;
224
0
            break;
225
0
    }
226
0
227
0
    gl->fStencilMaskSeparate(face, mask);
228
0
}
229
230
} // namespace mozilla