Bumping manifests a=b2g-bump
[gecko.git] / dom / canvas / WebGLContextFramebufferOperations.cpp
blob7b6d92bc9879526a6544357c7f97b1a0ec667ffe
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)
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.");
32 if (mBoundFramebuffer) {
33 if (!mBoundFramebuffer->CheckAndInitializeAttachments())
34 return ErrorInvalidFramebufferOperation("clear: incomplete framebuffer");
36 gl->fClear(mask);
37 return;
38 } else {
39 ClearBackbufferIfNeeded();
42 // Ok, we're clearing the default framebuffer/screen.
44 ScopedMaskWorkaround autoMask(*this);
45 gl->fClear(mask);
48 Invalidate();
49 mShouldPresent = true;
52 static GLclampf
53 GLClampFloat(GLclampf val)
55 if (val < 0.0)
56 return 0.0;
58 if (val > 1.0)
59 return 1.0;
61 return val;
64 void
65 WebGLContext::ClearColor(GLclampf r, GLclampf g,
66 GLclampf b, GLclampf a)
68 if (IsContextLost())
69 return;
71 MakeContextCurrent();
72 mColorClearValue[0] = GLClampFloat(r);
73 mColorClearValue[1] = GLClampFloat(g);
74 mColorClearValue[2] = GLClampFloat(b);
75 mColorClearValue[3] = GLClampFloat(a);
76 gl->fClearColor(r, g, b, a);
79 void
80 WebGLContext::ClearDepth(GLclampf v)
82 if (IsContextLost())
83 return;
85 MakeContextCurrent();
86 mDepthClearValue = GLClampFloat(v);
87 gl->fClearDepth(v);
90 void
91 WebGLContext::ClearStencil(GLint v)
93 if (IsContextLost())
94 return;
96 MakeContextCurrent();
97 mStencilClearValue = v;
98 gl->fClearStencil(v);
101 void
102 WebGLContext::ColorMask(WebGLboolean r, WebGLboolean g, WebGLboolean b, WebGLboolean a)
104 if (IsContextLost())
105 return;
107 MakeContextCurrent();
108 mColorWriteMask[0] = r;
109 mColorWriteMask[1] = g;
110 mColorWriteMask[2] = b;
111 mColorWriteMask[3] = a;
112 gl->fColorMask(r, g, b, a);
115 void
116 WebGLContext::DepthMask(WebGLboolean b)
118 if (IsContextLost())
119 return;
121 MakeContextCurrent();
122 mDepthWriteMask = b;
123 gl->fDepthMask(b);
126 void
127 WebGLContext::DrawBuffers(const dom::Sequence<GLenum>& buffers)
129 if (IsContextLost())
130 return;
132 const size_t buffersLength = buffers.Length();
134 if (buffersLength == 0) {
135 return ErrorInvalidValue("drawBuffers: invalid <buffers> (buffers must not be empty)");
138 if (mBoundFramebuffer == 0)
140 // OK: we are rendering in the default framebuffer
142 /* EXT_draw_buffers :
143 If the GL is bound to the default framebuffer, then <buffersLength> must be 1
144 and the constant must be BACK or NONE. When draw buffer zero is
145 BACK, color values are written into the sole buffer for single-
146 buffered contexts, or into the back buffer for double-buffered
147 contexts. If DrawBuffersEXT is supplied with a constant other than
148 BACK and NONE, the error INVALID_OPERATION is generated.
150 if (buffersLength != 1) {
151 return ErrorInvalidValue("drawBuffers: invalid <buffers> (main framebuffer: buffers.length must be 1)");
154 MakeContextCurrent();
156 if (buffers[0] == LOCAL_GL_NONE) {
157 const GLenum drawBuffersCommand = LOCAL_GL_NONE;
158 gl->fDrawBuffers(1, &drawBuffersCommand);
159 return;
161 else if (buffers[0] == LOCAL_GL_BACK) {
162 const GLenum drawBuffersCommand = LOCAL_GL_COLOR_ATTACHMENT0;
163 gl->fDrawBuffers(1, &drawBuffersCommand);
164 return;
166 return ErrorInvalidOperation("drawBuffers: invalid operation (main framebuffer: buffers[0] must be GL_NONE or GL_BACK)");
169 // OK: we are rendering in a framebuffer object
171 if (buffersLength > size_t(mGLMaxDrawBuffers)) {
172 /* EXT_draw_buffers :
173 The maximum number of draw buffers is implementation-dependent. The
174 number of draw buffers supported can be queried by calling
175 GetIntegerv with the symbolic constant MAX_DRAW_BUFFERS_EXT. An
176 INVALID_VALUE error is generated if <buffersLength> is greater than
177 MAX_DRAW_BUFFERS_EXT.
179 return ErrorInvalidValue("drawBuffers: invalid <buffers> (buffers.length > GL_MAX_DRAW_BUFFERS)");
182 for (uint32_t i = 0; i < buffersLength; i++)
184 /* EXT_draw_buffers :
185 If the GL is bound to a draw framebuffer object, the <i>th buffer listed
186 in <bufs> must be COLOR_ATTACHMENT<i>_EXT or NONE. Specifying a
187 buffer out of order, BACK, or COLOR_ATTACHMENT<m>_EXT where <m> is
188 greater than or equal to the value of MAX_COLOR_ATTACHMENTS_EXT,
189 will generate the error INVALID_OPERATION.
191 /* WEBGL_draw_buffers :
192 The value of the MAX_COLOR_ATTACHMENTS_WEBGL parameter must be greater than or equal to that of the MAX_DRAW_BUFFERS_WEBGL parameter.
194 if (buffers[i] != LOCAL_GL_NONE &&
195 buffers[i] != GLenum(LOCAL_GL_COLOR_ATTACHMENT0 + i)) {
196 return ErrorInvalidOperation("drawBuffers: invalid operation (buffers[i] must be GL_NONE or GL_COLOR_ATTACHMENTi)");
200 MakeContextCurrent();
202 gl->fDrawBuffers(buffersLength, buffers.Elements());
205 void
206 WebGLContext::StencilMask(GLuint mask)
208 if (IsContextLost())
209 return;
211 mStencilWriteMaskFront = mask;
212 mStencilWriteMaskBack = mask;
214 MakeContextCurrent();
215 gl->fStencilMask(mask);
218 void
219 WebGLContext::StencilMaskSeparate(GLenum face, GLuint mask)
221 if (IsContextLost())
222 return;
224 if (!ValidateFaceEnum(face, "stencilMaskSeparate: face"))
225 return;
227 switch (face) {
228 case LOCAL_GL_FRONT_AND_BACK:
229 mStencilWriteMaskFront = mask;
230 mStencilWriteMaskBack = mask;
231 break;
232 case LOCAL_GL_FRONT:
233 mStencilWriteMaskFront = mask;
234 break;
235 case LOCAL_GL_BACK:
236 mStencilWriteMaskBack = mask;
237 break;
240 MakeContextCurrent();
241 gl->fStencilMaskSeparate(face, mask);