Coverage Report

Created: 2018-09-25 14:53

/src/mozilla-central/dom/canvas/WebGLTransformFeedback.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 "WebGLTransformFeedback.h"
7
8
#include "GLContext.h"
9
#include "mozilla/dom/WebGL2RenderingContextBinding.h"
10
#include "WebGL2Context.h"
11
#include "WebGLProgram.h"
12
13
namespace mozilla {
14
15
WebGLTransformFeedback::WebGLTransformFeedback(WebGLContext* webgl, GLuint tf)
16
    : WebGLRefCountedObject(webgl)
17
    , mGLName(tf)
18
    , mIndexedBindings(webgl->mGLMaxTransformFeedbackSeparateAttribs)
19
    , mIsPaused(false)
20
    , mIsActive(false)
21
0
{
22
0
    mContext->mTransformFeedbacks.insertBack(this);
23
0
}
24
25
WebGLTransformFeedback::~WebGLTransformFeedback()
26
0
{
27
0
    DeleteOnce();
28
0
}
29
30
void
31
WebGLTransformFeedback::Delete()
32
0
{
33
0
    if (mGLName) {
34
0
        mContext->gl->fDeleteTransformFeedbacks(1, &mGLName);
35
0
    }
36
0
    removeFrom(mContext->mTransformFeedbacks);
37
0
}
38
39
////////////////////////////////////////
40
41
void
42
WebGLTransformFeedback::BeginTransformFeedback(GLenum primMode)
43
0
{
44
0
    if (mIsActive)
45
0
        return mContext->ErrorInvalidOperation("Already active.");
46
0
47
0
    switch (primMode) {
48
0
    case LOCAL_GL_POINTS:
49
0
    case LOCAL_GL_LINES:
50
0
    case LOCAL_GL_TRIANGLES:
51
0
        break;
52
0
    default:
53
0
        mContext->ErrorInvalidEnum("`primitiveMode` must be one of POINTS, LINES, or"
54
0
                                   " TRIANGLES.");
55
0
        return;
56
0
    }
57
0
58
0
    const auto& prog = mContext->mCurrentProgram;
59
0
    if (!prog ||
60
0
        !prog->IsLinked() ||
61
0
        prog->LinkInfo()->componentsPerTFVert.empty())
62
0
    {
63
0
        mContext->ErrorInvalidOperation("Current program not valid for transform"
64
0
                                        " feedback.");
65
0
        return;
66
0
    }
67
0
68
0
    const auto& linkInfo = prog->LinkInfo();
69
0
    const auto& componentsPerTFVert = linkInfo->componentsPerTFVert;
70
0
71
0
    size_t minVertCapacity = SIZE_MAX;
72
0
    for (size_t i = 0; i < componentsPerTFVert.size(); i++) {
73
0
        const auto& indexedBinding = mIndexedBindings[i];
74
0
        const auto& componentsPerVert = componentsPerTFVert[i];
75
0
76
0
        const auto& buffer = indexedBinding.mBufferBinding;
77
0
        if (!buffer) {
78
0
            mContext->ErrorInvalidOperation("No buffer attached to required transform"
79
0
                                            " feedback index %u.",
80
0
                                            (uint32_t)i);
81
0
            return;
82
0
        }
83
0
84
0
        const size_t vertCapacity = buffer->ByteLength() / 4 / componentsPerVert;
85
0
        minVertCapacity = std::min(minVertCapacity, vertCapacity);
86
0
    }
87
0
88
0
    ////
89
0
90
0
    const auto& gl = mContext->gl;
91
0
    gl->fBeginTransformFeedback(primMode);
92
0
93
0
    ////
94
0
95
0
    mIsActive = true;
96
0
    MOZ_ASSERT(!mIsPaused);
97
0
98
0
    mActive_Program = prog;
99
0
    mActive_PrimMode = primMode;
100
0
    mActive_VertPosition = 0;
101
0
    mActive_VertCapacity = minVertCapacity;
102
0
103
0
    ////
104
0
105
0
    mActive_Program->mNumActiveTFOs++;
106
0
}
107
108
109
void
110
WebGLTransformFeedback::EndTransformFeedback()
111
0
{
112
0
    if (!mIsActive)
113
0
        return mContext->ErrorInvalidOperation("Not active.");
114
0
115
0
    ////
116
0
117
0
    const auto& gl = mContext->gl;
118
0
    gl->fEndTransformFeedback();
119
0
120
0
    if (gl->WorkAroundDriverBugs()) {
121
#ifdef XP_MACOSX
122
        // Multi-threaded GL on mac will generate INVALID_OP in some cases for at least
123
        // BindBufferBase after an EndTransformFeedback if there is not a flush between
124
        // the two.
125
        // Single-threaded GL does not have this issue.
126
        // This is likely due to not synchronizing client/server state, and erroring in
127
        // BindBufferBase because the client thinks we're still in transform feedback.
128
        gl->fFlush();
129
#endif
130
    }
131
0
132
0
    ////
133
0
134
0
    mIsActive = false;
135
0
    mIsPaused = false;
136
0
137
0
    ////
138
0
139
0
    mActive_Program->mNumActiveTFOs--;
140
0
}
141
142
void
143
WebGLTransformFeedback::PauseTransformFeedback()
144
0
{
145
0
    if (!mIsActive ||
146
0
        mIsPaused)
147
0
    {
148
0
        mContext->ErrorInvalidOperation("Not active or is paused.");
149
0
        return;
150
0
    }
151
0
152
0
    ////
153
0
154
0
    const auto& gl = mContext->gl;
155
0
    gl->fPauseTransformFeedback();
156
0
157
0
    ////
158
0
159
0
    mIsPaused = true;
160
0
}
161
162
void
163
WebGLTransformFeedback::ResumeTransformFeedback()
164
0
{
165
0
    if (!mIsPaused)
166
0
        return mContext->ErrorInvalidOperation("Not paused.");
167
0
168
0
    if (mContext->mCurrentProgram != mActive_Program) {
169
0
        mContext->ErrorInvalidOperation("Active program differs from original.");
170
0
        return;
171
0
    }
172
0
173
0
    ////
174
0
175
0
    const auto& gl = mContext->gl;
176
0
    gl->fResumeTransformFeedback();
177
0
178
0
    ////
179
0
180
0
    MOZ_ASSERT(mIsActive);
181
0
    mIsPaused = false;
182
0
}
183
184
////////////////////////////////////////
185
186
void
187
WebGLTransformFeedback::AddBufferBindCounts(int8_t addVal) const
188
0
{
189
0
    const GLenum target = LOCAL_GL_TRANSFORM_FEEDBACK_BUFFER;
190
0
    for (const auto& binding : mIndexedBindings) {
191
0
        WebGLBuffer::AddBindCount(target, binding.mBufferBinding.get(), addVal);
192
0
    }
193
0
}
194
195
////////////////////////////////////////
196
197
JSObject*
198
WebGLTransformFeedback::WrapObject(JSContext* cx, JS::Handle<JSObject*> givenProto)
199
0
{
200
0
    return dom::WebGLTransformFeedback_Binding::Wrap(cx, this, givenProto);
201
0
}
202
203
NS_IMPL_CYCLE_COLLECTION_ROOT_NATIVE(WebGLTransformFeedback, AddRef)
204
NS_IMPL_CYCLE_COLLECTION_UNROOT_NATIVE(WebGLTransformFeedback, Release)
205
NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE(WebGLTransformFeedback,
206
                                      mIndexedBindings,
207
                                      mActive_Program)
208
209
} // namespace mozilla