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.)
michael@0 | 1 | /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ |
michael@0 | 2 | /* This Source Code Form is subject to the terms of the Mozilla Public |
michael@0 | 3 | * License, v. 2.0. If a copy of the MPL was not distributed with this |
michael@0 | 4 | * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ |
michael@0 | 5 | |
michael@0 | 6 | #include "WebGLContext.h" |
michael@0 | 7 | #include "WebGLTexture.h" |
michael@0 | 8 | #include "WebGLRenderbuffer.h" |
michael@0 | 9 | #include "WebGLFramebuffer.h" |
michael@0 | 10 | #include "GLContext.h" |
michael@0 | 11 | |
michael@0 | 12 | using namespace mozilla; |
michael@0 | 13 | |
michael@0 | 14 | void |
michael@0 | 15 | WebGLContext::Clear(GLbitfield mask) |
michael@0 | 16 | { |
michael@0 | 17 | if (IsContextLost()) |
michael@0 | 18 | return; |
michael@0 | 19 | |
michael@0 | 20 | MakeContextCurrent(); |
michael@0 | 21 | |
michael@0 | 22 | uint32_t m = mask & (LOCAL_GL_COLOR_BUFFER_BIT | LOCAL_GL_DEPTH_BUFFER_BIT | LOCAL_GL_STENCIL_BUFFER_BIT); |
michael@0 | 23 | if (mask != m) |
michael@0 | 24 | return ErrorInvalidValue("clear: invalid mask bits"); |
michael@0 | 25 | |
michael@0 | 26 | if (mask == 0) { |
michael@0 | 27 | GenerateWarning("Calling gl.clear(0) has no effect."); |
michael@0 | 28 | } else if (mRasterizerDiscardEnabled) { |
michael@0 | 29 | GenerateWarning("Calling gl.clear() with RASTERIZER_DISCARD enabled has no effects."); |
michael@0 | 30 | } |
michael@0 | 31 | |
michael@0 | 32 | if (mBoundFramebuffer) { |
michael@0 | 33 | if (!mBoundFramebuffer->CheckAndInitializeAttachments()) |
michael@0 | 34 | return ErrorInvalidFramebufferOperation("clear: incomplete framebuffer"); |
michael@0 | 35 | |
michael@0 | 36 | gl->fClear(mask); |
michael@0 | 37 | return; |
michael@0 | 38 | } else { |
michael@0 | 39 | ClearBackbufferIfNeeded(); |
michael@0 | 40 | } |
michael@0 | 41 | |
michael@0 | 42 | // Ok, we're clearing the default framebuffer/screen. |
michael@0 | 43 | |
michael@0 | 44 | gl->fClear(mask); |
michael@0 | 45 | |
michael@0 | 46 | Invalidate(); |
michael@0 | 47 | mShouldPresent = true; |
michael@0 | 48 | } |
michael@0 | 49 | |
michael@0 | 50 | static GLclampf |
michael@0 | 51 | GLClampFloat(GLclampf val) |
michael@0 | 52 | { |
michael@0 | 53 | if (val < 0.0) |
michael@0 | 54 | return 0.0; |
michael@0 | 55 | |
michael@0 | 56 | if (val > 1.0) |
michael@0 | 57 | return 1.0; |
michael@0 | 58 | |
michael@0 | 59 | return val; |
michael@0 | 60 | } |
michael@0 | 61 | |
michael@0 | 62 | void |
michael@0 | 63 | WebGLContext::ClearColor(GLclampf r, GLclampf g, |
michael@0 | 64 | GLclampf b, GLclampf a) |
michael@0 | 65 | { |
michael@0 | 66 | if (IsContextLost()) |
michael@0 | 67 | return; |
michael@0 | 68 | |
michael@0 | 69 | MakeContextCurrent(); |
michael@0 | 70 | mColorClearValue[0] = GLClampFloat(r); |
michael@0 | 71 | mColorClearValue[1] = GLClampFloat(g); |
michael@0 | 72 | mColorClearValue[2] = GLClampFloat(b); |
michael@0 | 73 | mColorClearValue[3] = GLClampFloat(a); |
michael@0 | 74 | gl->fClearColor(r, g, b, a); |
michael@0 | 75 | } |
michael@0 | 76 | |
michael@0 | 77 | void |
michael@0 | 78 | WebGLContext::ClearDepth(GLclampf v) |
michael@0 | 79 | { |
michael@0 | 80 | if (IsContextLost()) |
michael@0 | 81 | return; |
michael@0 | 82 | |
michael@0 | 83 | MakeContextCurrent(); |
michael@0 | 84 | mDepthClearValue = GLClampFloat(v); |
michael@0 | 85 | gl->fClearDepth(v); |
michael@0 | 86 | } |
michael@0 | 87 | |
michael@0 | 88 | void |
michael@0 | 89 | WebGLContext::ClearStencil(GLint v) |
michael@0 | 90 | { |
michael@0 | 91 | if (IsContextLost()) |
michael@0 | 92 | return; |
michael@0 | 93 | |
michael@0 | 94 | MakeContextCurrent(); |
michael@0 | 95 | mStencilClearValue = v; |
michael@0 | 96 | gl->fClearStencil(v); |
michael@0 | 97 | } |
michael@0 | 98 | |
michael@0 | 99 | void |
michael@0 | 100 | WebGLContext::ColorMask(WebGLboolean r, WebGLboolean g, WebGLboolean b, WebGLboolean a) |
michael@0 | 101 | { |
michael@0 | 102 | if (IsContextLost()) |
michael@0 | 103 | return; |
michael@0 | 104 | |
michael@0 | 105 | MakeContextCurrent(); |
michael@0 | 106 | mColorWriteMask[0] = r; |
michael@0 | 107 | mColorWriteMask[1] = g; |
michael@0 | 108 | mColorWriteMask[2] = b; |
michael@0 | 109 | mColorWriteMask[3] = a; |
michael@0 | 110 | gl->fColorMask(r, g, b, a); |
michael@0 | 111 | } |
michael@0 | 112 | |
michael@0 | 113 | void |
michael@0 | 114 | WebGLContext::DepthMask(WebGLboolean b) |
michael@0 | 115 | { |
michael@0 | 116 | if (IsContextLost()) |
michael@0 | 117 | return; |
michael@0 | 118 | |
michael@0 | 119 | MakeContextCurrent(); |
michael@0 | 120 | mDepthWriteMask = b; |
michael@0 | 121 | gl->fDepthMask(b); |
michael@0 | 122 | } |
michael@0 | 123 | |
michael@0 | 124 | void |
michael@0 | 125 | WebGLContext::DrawBuffers(const dom::Sequence<GLenum>& buffers) |
michael@0 | 126 | { |
michael@0 | 127 | if (IsContextLost()) |
michael@0 | 128 | return; |
michael@0 | 129 | |
michael@0 | 130 | const size_t buffersLength = buffers.Length(); |
michael@0 | 131 | |
michael@0 | 132 | if (buffersLength == 0) { |
michael@0 | 133 | return ErrorInvalidValue("drawBuffers: invalid <buffers> (buffers must not be empty)"); |
michael@0 | 134 | } |
michael@0 | 135 | |
michael@0 | 136 | if (mBoundFramebuffer == 0) |
michael@0 | 137 | { |
michael@0 | 138 | // OK: we are rendering in the default framebuffer |
michael@0 | 139 | |
michael@0 | 140 | /* EXT_draw_buffers : |
michael@0 | 141 | If the GL is bound to the default framebuffer, then <buffersLength> must be 1 |
michael@0 | 142 | and the constant must be BACK or NONE. When draw buffer zero is |
michael@0 | 143 | BACK, color values are written into the sole buffer for single- |
michael@0 | 144 | buffered contexts, or into the back buffer for double-buffered |
michael@0 | 145 | contexts. If DrawBuffersEXT is supplied with a constant other than |
michael@0 | 146 | BACK and NONE, the error INVALID_OPERATION is generated. |
michael@0 | 147 | */ |
michael@0 | 148 | if (buffersLength != 1) { |
michael@0 | 149 | return ErrorInvalidValue("drawBuffers: invalid <buffers> (main framebuffer: buffers.length must be 1)"); |
michael@0 | 150 | } |
michael@0 | 151 | |
michael@0 | 152 | MakeContextCurrent(); |
michael@0 | 153 | |
michael@0 | 154 | if (buffers[0] == LOCAL_GL_NONE) { |
michael@0 | 155 | const GLenum drawBuffersCommand = LOCAL_GL_NONE; |
michael@0 | 156 | gl->fDrawBuffers(1, &drawBuffersCommand); |
michael@0 | 157 | return; |
michael@0 | 158 | } |
michael@0 | 159 | else if (buffers[0] == LOCAL_GL_BACK) { |
michael@0 | 160 | const GLenum drawBuffersCommand = LOCAL_GL_COLOR_ATTACHMENT0; |
michael@0 | 161 | gl->fDrawBuffers(1, &drawBuffersCommand); |
michael@0 | 162 | return; |
michael@0 | 163 | } |
michael@0 | 164 | return ErrorInvalidOperation("drawBuffers: invalid operation (main framebuffer: buffers[0] must be GL_NONE or GL_BACK)"); |
michael@0 | 165 | } |
michael@0 | 166 | |
michael@0 | 167 | // OK: we are rendering in a framebuffer object |
michael@0 | 168 | |
michael@0 | 169 | if (buffersLength > size_t(mGLMaxDrawBuffers)) { |
michael@0 | 170 | /* EXT_draw_buffers : |
michael@0 | 171 | The maximum number of draw buffers is implementation-dependent. The |
michael@0 | 172 | number of draw buffers supported can be queried by calling |
michael@0 | 173 | GetIntegerv with the symbolic constant MAX_DRAW_BUFFERS_EXT. An |
michael@0 | 174 | INVALID_VALUE error is generated if <buffersLength> is greater than |
michael@0 | 175 | MAX_DRAW_BUFFERS_EXT. |
michael@0 | 176 | */ |
michael@0 | 177 | return ErrorInvalidValue("drawBuffers: invalid <buffers> (buffers.length > GL_MAX_DRAW_BUFFERS)"); |
michael@0 | 178 | } |
michael@0 | 179 | |
michael@0 | 180 | for (uint32_t i = 0; i < buffersLength; i++) |
michael@0 | 181 | { |
michael@0 | 182 | /* EXT_draw_buffers : |
michael@0 | 183 | If the GL is bound to a draw framebuffer object, the <i>th buffer listed |
michael@0 | 184 | in <bufs> must be COLOR_ATTACHMENT<i>_EXT or NONE. Specifying a |
michael@0 | 185 | buffer out of order, BACK, or COLOR_ATTACHMENT<m>_EXT where <m> is |
michael@0 | 186 | greater than or equal to the value of MAX_COLOR_ATTACHMENTS_EXT, |
michael@0 | 187 | will generate the error INVALID_OPERATION. |
michael@0 | 188 | */ |
michael@0 | 189 | /* WEBGL_draw_buffers : |
michael@0 | 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. |
michael@0 | 191 | */ |
michael@0 | 192 | if (buffers[i] != LOCAL_GL_NONE && |
michael@0 | 193 | buffers[i] != GLenum(LOCAL_GL_COLOR_ATTACHMENT0 + i)) { |
michael@0 | 194 | return ErrorInvalidOperation("drawBuffers: invalid operation (buffers[i] must be GL_NONE or GL_COLOR_ATTACHMENTi)"); |
michael@0 | 195 | } |
michael@0 | 196 | } |
michael@0 | 197 | |
michael@0 | 198 | MakeContextCurrent(); |
michael@0 | 199 | |
michael@0 | 200 | gl->fDrawBuffers(buffersLength, buffers.Elements()); |
michael@0 | 201 | } |
michael@0 | 202 | |
michael@0 | 203 | void |
michael@0 | 204 | WebGLContext::StencilMask(GLuint mask) |
michael@0 | 205 | { |
michael@0 | 206 | if (IsContextLost()) |
michael@0 | 207 | return; |
michael@0 | 208 | |
michael@0 | 209 | mStencilWriteMaskFront = mask; |
michael@0 | 210 | mStencilWriteMaskBack = mask; |
michael@0 | 211 | |
michael@0 | 212 | MakeContextCurrent(); |
michael@0 | 213 | gl->fStencilMask(mask); |
michael@0 | 214 | } |
michael@0 | 215 | |
michael@0 | 216 | void |
michael@0 | 217 | WebGLContext::StencilMaskSeparate(GLenum face, GLuint mask) |
michael@0 | 218 | { |
michael@0 | 219 | if (IsContextLost()) |
michael@0 | 220 | return; |
michael@0 | 221 | |
michael@0 | 222 | if (!ValidateFaceEnum(face, "stencilMaskSeparate: face")) |
michael@0 | 223 | return; |
michael@0 | 224 | |
michael@0 | 225 | switch (face) { |
michael@0 | 226 | case LOCAL_GL_FRONT_AND_BACK: |
michael@0 | 227 | mStencilWriteMaskFront = mask; |
michael@0 | 228 | mStencilWriteMaskBack = mask; |
michael@0 | 229 | break; |
michael@0 | 230 | case LOCAL_GL_FRONT: |
michael@0 | 231 | mStencilWriteMaskFront = mask; |
michael@0 | 232 | break; |
michael@0 | 233 | case LOCAL_GL_BACK: |
michael@0 | 234 | mStencilWriteMaskBack = mask; |
michael@0 | 235 | break; |
michael@0 | 236 | } |
michael@0 | 237 | |
michael@0 | 238 | MakeContextCurrent(); |
michael@0 | 239 | gl->fStencilMaskSeparate(face, mask); |
michael@0 | 240 | } |
michael@0 | 241 | |
michael@0 | 242 | |
michael@0 | 243 | |
michael@0 | 244 |