Thu, 15 Jan 2015 21:03:48 +0100
Integrate friendly tips from Tor colleagues to make (or not) 4.5 alpha 3;
This includes removal of overloaded (but unused) methods, and addition of
a overlooked call to DataStruct::SetData(nsISupports, uint32_t, bool.)
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/. */
6 #include "WebGLContext.h"
7 #include "WebGLTexture.h"
8 #include "WebGLRenderbuffer.h"
9 #include "WebGLFramebuffer.h"
10 #include "GLContext.h"
12 using namespace mozilla;
14 void
15 WebGLContext::Clear(GLbitfield mask)
16 {
17 if (IsContextLost())
18 return;
20 MakeContextCurrent();
22 uint32_t m = mask & (LOCAL_GL_COLOR_BUFFER_BIT | LOCAL_GL_DEPTH_BUFFER_BIT | LOCAL_GL_STENCIL_BUFFER_BIT);
23 if (mask != m)
24 return ErrorInvalidValue("clear: invalid mask bits");
26 if (mask == 0) {
27 GenerateWarning("Calling gl.clear(0) has no effect.");
28 } else if (mRasterizerDiscardEnabled) {
29 GenerateWarning("Calling gl.clear() with RASTERIZER_DISCARD enabled has no effects.");
30 }
32 if (mBoundFramebuffer) {
33 if (!mBoundFramebuffer->CheckAndInitializeAttachments())
34 return ErrorInvalidFramebufferOperation("clear: incomplete framebuffer");
36 gl->fClear(mask);
37 return;
38 } else {
39 ClearBackbufferIfNeeded();
40 }
42 // Ok, we're clearing the default framebuffer/screen.
44 gl->fClear(mask);
46 Invalidate();
47 mShouldPresent = true;
48 }
50 static GLclampf
51 GLClampFloat(GLclampf val)
52 {
53 if (val < 0.0)
54 return 0.0;
56 if (val > 1.0)
57 return 1.0;
59 return val;
60 }
62 void
63 WebGLContext::ClearColor(GLclampf r, GLclampf g,
64 GLclampf b, GLclampf a)
65 {
66 if (IsContextLost())
67 return;
69 MakeContextCurrent();
70 mColorClearValue[0] = GLClampFloat(r);
71 mColorClearValue[1] = GLClampFloat(g);
72 mColorClearValue[2] = GLClampFloat(b);
73 mColorClearValue[3] = GLClampFloat(a);
74 gl->fClearColor(r, g, b, a);
75 }
77 void
78 WebGLContext::ClearDepth(GLclampf v)
79 {
80 if (IsContextLost())
81 return;
83 MakeContextCurrent();
84 mDepthClearValue = GLClampFloat(v);
85 gl->fClearDepth(v);
86 }
88 void
89 WebGLContext::ClearStencil(GLint v)
90 {
91 if (IsContextLost())
92 return;
94 MakeContextCurrent();
95 mStencilClearValue = v;
96 gl->fClearStencil(v);
97 }
99 void
100 WebGLContext::ColorMask(WebGLboolean r, WebGLboolean g, WebGLboolean b, WebGLboolean a)
101 {
102 if (IsContextLost())
103 return;
105 MakeContextCurrent();
106 mColorWriteMask[0] = r;
107 mColorWriteMask[1] = g;
108 mColorWriteMask[2] = b;
109 mColorWriteMask[3] = a;
110 gl->fColorMask(r, g, b, a);
111 }
113 void
114 WebGLContext::DepthMask(WebGLboolean b)
115 {
116 if (IsContextLost())
117 return;
119 MakeContextCurrent();
120 mDepthWriteMask = b;
121 gl->fDepthMask(b);
122 }
124 void
125 WebGLContext::DrawBuffers(const dom::Sequence<GLenum>& buffers)
126 {
127 if (IsContextLost())
128 return;
130 const size_t buffersLength = buffers.Length();
132 if (buffersLength == 0) {
133 return ErrorInvalidValue("drawBuffers: invalid <buffers> (buffers must not be empty)");
134 }
136 if (mBoundFramebuffer == 0)
137 {
138 // OK: we are rendering in the default framebuffer
140 /* EXT_draw_buffers :
141 If the GL is bound to the default framebuffer, then <buffersLength> must be 1
142 and the constant must be BACK or NONE. When draw buffer zero is
143 BACK, color values are written into the sole buffer for single-
144 buffered contexts, or into the back buffer for double-buffered
145 contexts. If DrawBuffersEXT is supplied with a constant other than
146 BACK and NONE, the error INVALID_OPERATION is generated.
147 */
148 if (buffersLength != 1) {
149 return ErrorInvalidValue("drawBuffers: invalid <buffers> (main framebuffer: buffers.length must be 1)");
150 }
152 MakeContextCurrent();
154 if (buffers[0] == LOCAL_GL_NONE) {
155 const GLenum drawBuffersCommand = LOCAL_GL_NONE;
156 gl->fDrawBuffers(1, &drawBuffersCommand);
157 return;
158 }
159 else if (buffers[0] == LOCAL_GL_BACK) {
160 const GLenum drawBuffersCommand = LOCAL_GL_COLOR_ATTACHMENT0;
161 gl->fDrawBuffers(1, &drawBuffersCommand);
162 return;
163 }
164 return ErrorInvalidOperation("drawBuffers: invalid operation (main framebuffer: buffers[0] must be GL_NONE or GL_BACK)");
165 }
167 // OK: we are rendering in a framebuffer object
169 if (buffersLength > size_t(mGLMaxDrawBuffers)) {
170 /* EXT_draw_buffers :
171 The maximum number of draw buffers is implementation-dependent. The
172 number of draw buffers supported can be queried by calling
173 GetIntegerv with the symbolic constant MAX_DRAW_BUFFERS_EXT. An
174 INVALID_VALUE error is generated if <buffersLength> is greater than
175 MAX_DRAW_BUFFERS_EXT.
176 */
177 return ErrorInvalidValue("drawBuffers: invalid <buffers> (buffers.length > GL_MAX_DRAW_BUFFERS)");
178 }
180 for (uint32_t i = 0; i < buffersLength; i++)
181 {
182 /* EXT_draw_buffers :
183 If the GL is bound to a draw framebuffer object, the <i>th buffer listed
184 in <bufs> must be COLOR_ATTACHMENT<i>_EXT or NONE. Specifying a
185 buffer out of order, BACK, or COLOR_ATTACHMENT<m>_EXT where <m> is
186 greater than or equal to the value of MAX_COLOR_ATTACHMENTS_EXT,
187 will generate the error INVALID_OPERATION.
188 */
189 /* WEBGL_draw_buffers :
190 The value of the MAX_COLOR_ATTACHMENTS_WEBGL parameter must be greater than or equal to that of the MAX_DRAW_BUFFERS_WEBGL parameter.
191 */
192 if (buffers[i] != LOCAL_GL_NONE &&
193 buffers[i] != GLenum(LOCAL_GL_COLOR_ATTACHMENT0 + i)) {
194 return ErrorInvalidOperation("drawBuffers: invalid operation (buffers[i] must be GL_NONE or GL_COLOR_ATTACHMENTi)");
195 }
196 }
198 MakeContextCurrent();
200 gl->fDrawBuffers(buffersLength, buffers.Elements());
201 }
203 void
204 WebGLContext::StencilMask(GLuint mask)
205 {
206 if (IsContextLost())
207 return;
209 mStencilWriteMaskFront = mask;
210 mStencilWriteMaskBack = mask;
212 MakeContextCurrent();
213 gl->fStencilMask(mask);
214 }
216 void
217 WebGLContext::StencilMaskSeparate(GLenum face, GLuint mask)
218 {
219 if (IsContextLost())
220 return;
222 if (!ValidateFaceEnum(face, "stencilMaskSeparate: face"))
223 return;
225 switch (face) {
226 case LOCAL_GL_FRONT_AND_BACK:
227 mStencilWriteMaskFront = mask;
228 mStencilWriteMaskBack = mask;
229 break;
230 case LOCAL_GL_FRONT:
231 mStencilWriteMaskFront = mask;
232 break;
233 case LOCAL_GL_BACK:
234 mStencilWriteMaskBack = mask;
235 break;
236 }
238 MakeContextCurrent();
239 gl->fStencilMaskSeparate(face, mask);
240 }