|
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 #ifndef WEBGLCONTEXT_H_ |
|
7 #define WEBGLCONTEXT_H_ |
|
8 |
|
9 #include "mozilla/Attributes.h" |
|
10 #include "GLDefs.h" |
|
11 #include "WebGLActiveInfo.h" |
|
12 #include "WebGLObjectModel.h" |
|
13 #include <stdarg.h> |
|
14 |
|
15 #include "nsTArray.h" |
|
16 #include "nsCycleCollectionNoteChild.h" |
|
17 |
|
18 #include "nsIDOMWebGLRenderingContext.h" |
|
19 #include "nsICanvasRenderingContextInternal.h" |
|
20 #include "mozilla/dom/HTMLCanvasElement.h" |
|
21 #include "nsWrapperCache.h" |
|
22 #include "nsIObserver.h" |
|
23 #include "nsLayoutUtils.h" |
|
24 |
|
25 #include "GLContextProvider.h" |
|
26 |
|
27 #include "mozilla/EnumeratedArray.h" |
|
28 #include "mozilla/LinkedList.h" |
|
29 #include "mozilla/CheckedInt.h" |
|
30 #include "mozilla/Scoped.h" |
|
31 #include "mozilla/gfx/2D.h" |
|
32 |
|
33 #ifdef XP_MACOSX |
|
34 #include "ForceDiscreteGPUHelperCGL.h" |
|
35 #endif |
|
36 |
|
37 #include "mozilla/dom/TypedArray.h" |
|
38 #include "mozilla/ErrorResult.h" |
|
39 |
|
40 class nsIDocShell; |
|
41 |
|
42 /* |
|
43 * Minimum value constants defined in 6.2 State Tables of OpenGL ES - 2.0.25 |
|
44 * https://bugzilla.mozilla.org/show_bug.cgi?id=686732 |
|
45 * |
|
46 * Exceptions: some of the following values are set to higher values than in the spec because |
|
47 * the values in the spec are ridiculously low. They are explicitly marked below |
|
48 */ |
|
49 #define MINVALUE_GL_MAX_TEXTURE_SIZE 1024 // Different from the spec, which sets it to 64 on page 162 |
|
50 #define MINVALUE_GL_MAX_CUBE_MAP_TEXTURE_SIZE 512 // Different from the spec, which sets it to 16 on page 162 |
|
51 #define MINVALUE_GL_MAX_VERTEX_ATTRIBS 8 // Page 164 |
|
52 #define MINVALUE_GL_MAX_FRAGMENT_UNIFORM_VECTORS 16 // Page 164 |
|
53 #define MINVALUE_GL_MAX_VERTEX_UNIFORM_VECTORS 128 // Page 164 |
|
54 #define MINVALUE_GL_MAX_VARYING_VECTORS 8 // Page 164 |
|
55 #define MINVALUE_GL_MAX_TEXTURE_IMAGE_UNITS 8 // Page 164 |
|
56 #define MINVALUE_GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS 0 // Page 164 |
|
57 #define MINVALUE_GL_MAX_RENDERBUFFER_SIZE 1024 // Different from the spec, which sets it to 1 on page 164 |
|
58 #define MINVALUE_GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS 8 // Page 164 |
|
59 |
|
60 namespace mozilla { |
|
61 |
|
62 class WebGLMemoryPressureObserver; |
|
63 class WebGLContextBoundObject; |
|
64 class WebGLActiveInfo; |
|
65 class WebGLExtensionBase; |
|
66 class WebGLBuffer; |
|
67 class WebGLVertexAttribData; |
|
68 class WebGLShader; |
|
69 class WebGLProgram; |
|
70 class WebGLQuery; |
|
71 class WebGLUniformLocation; |
|
72 class WebGLFramebuffer; |
|
73 class WebGLRenderbuffer; |
|
74 class WebGLShaderPrecisionFormat; |
|
75 class WebGLTexture; |
|
76 class WebGLVertexArray; |
|
77 |
|
78 namespace dom { |
|
79 class ImageData; |
|
80 |
|
81 struct WebGLContextAttributes; |
|
82 template<typename> struct Nullable; |
|
83 } |
|
84 |
|
85 namespace gfx { |
|
86 class SourceSurface; |
|
87 } |
|
88 |
|
89 WebGLTexelFormat GetWebGLTexelFormat(GLenum format, GLenum type); |
|
90 |
|
91 struct WebGLContextOptions { |
|
92 // these are defaults |
|
93 WebGLContextOptions(); |
|
94 |
|
95 bool operator==(const WebGLContextOptions& other) const { |
|
96 return |
|
97 alpha == other.alpha && |
|
98 depth == other.depth && |
|
99 stencil == other.stencil && |
|
100 premultipliedAlpha == other.premultipliedAlpha && |
|
101 antialias == other.antialias && |
|
102 preserveDrawingBuffer == other.preserveDrawingBuffer; |
|
103 } |
|
104 |
|
105 bool operator!=(const WebGLContextOptions& other) const { |
|
106 return !operator==(other); |
|
107 } |
|
108 |
|
109 bool alpha; |
|
110 bool depth; |
|
111 bool stencil; |
|
112 bool premultipliedAlpha; |
|
113 bool antialias; |
|
114 bool preserveDrawingBuffer; |
|
115 }; |
|
116 |
|
117 class WebGLContext : |
|
118 public nsIDOMWebGLRenderingContext, |
|
119 public nsICanvasRenderingContextInternal, |
|
120 public nsSupportsWeakReference, |
|
121 public WebGLRectangleObject, |
|
122 public nsWrapperCache |
|
123 { |
|
124 friend class WebGLContextUserData; |
|
125 friend class WebGLExtensionCompressedTextureATC; |
|
126 friend class WebGLExtensionCompressedTextureETC1; |
|
127 friend class WebGLExtensionCompressedTexturePVRTC; |
|
128 friend class WebGLExtensionCompressedTextureS3TC; |
|
129 friend class WebGLExtensionDepthTexture; |
|
130 friend class WebGLExtensionDrawBuffers; |
|
131 friend class WebGLExtensionLoseContext; |
|
132 friend class WebGLExtensionVertexArray; |
|
133 friend class WebGLMemoryPressureObserver; |
|
134 friend class WebGLMemoryTracker; |
|
135 |
|
136 enum { |
|
137 UNPACK_FLIP_Y_WEBGL = 0x9240, |
|
138 UNPACK_PREMULTIPLY_ALPHA_WEBGL = 0x9241, |
|
139 CONTEXT_LOST_WEBGL = 0x9242, |
|
140 UNPACK_COLORSPACE_CONVERSION_WEBGL = 0x9243, |
|
141 BROWSER_DEFAULT_WEBGL = 0x9244, |
|
142 UNMASKED_VENDOR_WEBGL = 0x9245, |
|
143 UNMASKED_RENDERER_WEBGL = 0x9246 |
|
144 }; |
|
145 |
|
146 public: |
|
147 WebGLContext(); |
|
148 virtual ~WebGLContext(); |
|
149 |
|
150 NS_DECL_CYCLE_COLLECTING_ISUPPORTS |
|
151 |
|
152 NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS_AMBIGUOUS(WebGLContext, |
|
153 nsIDOMWebGLRenderingContext) |
|
154 |
|
155 virtual JSObject* WrapObject(JSContext *cx) = 0; |
|
156 |
|
157 NS_DECL_NSIDOMWEBGLRENDERINGCONTEXT |
|
158 |
|
159 // nsICanvasRenderingContextInternal |
|
160 #ifdef DEBUG |
|
161 virtual int32_t GetWidth() const MOZ_OVERRIDE; |
|
162 virtual int32_t GetHeight() const MOZ_OVERRIDE; |
|
163 #endif |
|
164 NS_IMETHOD SetDimensions(int32_t width, int32_t height) MOZ_OVERRIDE; |
|
165 NS_IMETHOD InitializeWithSurface(nsIDocShell *docShell, gfxASurface *surface, int32_t width, int32_t height) MOZ_OVERRIDE |
|
166 { return NS_ERROR_NOT_IMPLEMENTED; } |
|
167 NS_IMETHOD Reset() MOZ_OVERRIDE |
|
168 { /* (InitializeWithSurface) */ return NS_ERROR_NOT_IMPLEMENTED; } |
|
169 virtual void GetImageBuffer(uint8_t** aImageBuffer, int32_t* aFormat); |
|
170 NS_IMETHOD GetInputStream(const char* aMimeType, |
|
171 const char16_t* aEncoderOptions, |
|
172 nsIInputStream **aStream) MOZ_OVERRIDE; |
|
173 mozilla::TemporaryRef<mozilla::gfx::SourceSurface> GetSurfaceSnapshot(bool* aPremultAlpha) MOZ_OVERRIDE; |
|
174 |
|
175 NS_IMETHOD SetIsOpaque(bool b) MOZ_OVERRIDE { return NS_OK; }; |
|
176 bool GetIsOpaque() MOZ_OVERRIDE { return false; } |
|
177 NS_IMETHOD SetContextOptions(JSContext* aCx, |
|
178 JS::Handle<JS::Value> aOptions) MOZ_OVERRIDE; |
|
179 |
|
180 NS_IMETHOD SetIsIPC(bool b) MOZ_OVERRIDE { return NS_ERROR_NOT_IMPLEMENTED; } |
|
181 NS_IMETHOD Redraw(const gfxRect&) { return NS_ERROR_NOT_IMPLEMENTED; } |
|
182 NS_IMETHOD Swap(mozilla::ipc::Shmem& aBack, |
|
183 int32_t x, int32_t y, int32_t w, int32_t h) |
|
184 { return NS_ERROR_NOT_IMPLEMENTED; } |
|
185 NS_IMETHOD Swap(uint32_t nativeID, |
|
186 int32_t x, int32_t y, int32_t w, int32_t h) |
|
187 { return NS_ERROR_NOT_IMPLEMENTED; } |
|
188 |
|
189 bool LoseContext(); |
|
190 bool RestoreContext(); |
|
191 |
|
192 void SynthesizeGLError(GLenum err); |
|
193 void SynthesizeGLError(GLenum err, const char *fmt, ...); |
|
194 |
|
195 void ErrorInvalidEnum(const char *fmt = 0, ...); |
|
196 void ErrorInvalidOperation(const char *fmt = 0, ...); |
|
197 void ErrorInvalidValue(const char *fmt = 0, ...); |
|
198 void ErrorInvalidFramebufferOperation(const char *fmt = 0, ...); |
|
199 void ErrorInvalidEnumInfo(const char *info, GLenum enumvalue); |
|
200 void ErrorOutOfMemory(const char *fmt = 0, ...); |
|
201 |
|
202 const char *ErrorName(GLenum error); |
|
203 bool IsTextureFormatCompressed(GLenum format); |
|
204 |
|
205 void DummyFramebufferOperation(const char *info); |
|
206 |
|
207 WebGLTexture *activeBoundTextureForTarget(GLenum target) const { |
|
208 return target == LOCAL_GL_TEXTURE_2D ? mBound2DTextures[mActiveTexture] |
|
209 : mBoundCubeMapTextures[mActiveTexture]; |
|
210 } |
|
211 |
|
212 already_AddRefed<CanvasLayer> GetCanvasLayer(nsDisplayListBuilder* aBuilder, |
|
213 CanvasLayer *aOldLayer, |
|
214 LayerManager *aManager) MOZ_OVERRIDE; |
|
215 |
|
216 // Note that 'clean' here refers to its invalidation state, not the |
|
217 // contents of the buffer. |
|
218 void MarkContextClean() MOZ_OVERRIDE { mInvalidated = false; } |
|
219 |
|
220 gl::GLContext* GL() const { return gl; } |
|
221 |
|
222 bool IsPremultAlpha() const { return mOptions.premultipliedAlpha; } |
|
223 |
|
224 bool PresentScreenBuffer(); |
|
225 |
|
226 // a number that increments every time we have an event that causes |
|
227 // all context resources to be lost. |
|
228 uint32_t Generation() { return mGeneration.value(); } |
|
229 |
|
230 // Returns null if the current bound FB is not likely complete. |
|
231 const WebGLRectangleObject* CurValidFBRectObject() const; |
|
232 |
|
233 static const size_t sMaxColorAttachments = 16; |
|
234 |
|
235 // This is similar to GLContext::ClearSafely, but tries to minimize the |
|
236 // amount of work it does. |
|
237 // It only clears the buffers we specify, and can reset its state without |
|
238 // first having to query anything, as WebGL knows its state at all times. |
|
239 void ForceClearFramebufferWithDefaultValues(GLbitfield mask, const bool colorAttachmentsMask[sMaxColorAttachments]); |
|
240 |
|
241 // Calls ForceClearFramebufferWithDefaultValues() for the Context's 'screen'. |
|
242 void ClearScreen(); |
|
243 void ClearBackbufferIfNeeded(); |
|
244 |
|
245 bool MinCapabilityMode() const { return mMinCapability; } |
|
246 |
|
247 void RobustnessTimerCallback(nsITimer* timer); |
|
248 static void RobustnessTimerCallbackStatic(nsITimer* timer, void *thisPointer); |
|
249 void SetupContextLossTimer(); |
|
250 void TerminateContextLossTimer(); |
|
251 |
|
252 // WebIDL WebGLRenderingContext API |
|
253 dom::HTMLCanvasElement* GetCanvas() const { return mCanvasElement; } |
|
254 GLsizei DrawingBufferWidth() const { return IsContextLost() ? 0 : mWidth; } |
|
255 GLsizei DrawingBufferHeight() const { return IsContextLost() ? 0 : mHeight; } |
|
256 |
|
257 void GetContextAttributes(dom::Nullable<dom::WebGLContextAttributes>& retval); |
|
258 bool IsContextLost() const { return mContextStatus != ContextNotLost; } |
|
259 void GetSupportedExtensions(JSContext *cx, dom::Nullable< nsTArray<nsString> > &retval); |
|
260 void GetExtension(JSContext* cx, const nsAString& aName, |
|
261 JS::MutableHandle<JSObject*> aRetval, |
|
262 ErrorResult& rv); |
|
263 void ActiveTexture(GLenum texture); |
|
264 void AttachShader(WebGLProgram* program, WebGLShader* shader); |
|
265 void BindAttribLocation(WebGLProgram* program, GLuint location, |
|
266 const nsAString& name); |
|
267 void BindFramebuffer(GLenum target, WebGLFramebuffer* wfb); |
|
268 void BindRenderbuffer(GLenum target, WebGLRenderbuffer* wrb); |
|
269 void BindTexture(GLenum target, WebGLTexture *tex); |
|
270 void BindVertexArray(WebGLVertexArray *vao); |
|
271 void BlendColor(GLclampf r, GLclampf g, GLclampf b, GLclampf a); |
|
272 void BlendEquation(GLenum mode); |
|
273 void BlendEquationSeparate(GLenum modeRGB, GLenum modeAlpha); |
|
274 void BlendFunc(GLenum sfactor, GLenum dfactor); |
|
275 void BlendFuncSeparate(GLenum srcRGB, GLenum dstRGB, |
|
276 GLenum srcAlpha, GLenum dstAlpha); |
|
277 GLenum CheckFramebufferStatus(GLenum target); |
|
278 void Clear(GLbitfield mask); |
|
279 void ClearColor(GLclampf r, GLclampf g, GLclampf b, GLclampf a); |
|
280 void ClearDepth(GLclampf v); |
|
281 void ClearStencil(GLint v); |
|
282 void ColorMask(WebGLboolean r, WebGLboolean g, WebGLboolean b, WebGLboolean a); |
|
283 void CompileShader(WebGLShader *shader); |
|
284 void CompressedTexImage2D(GLenum target, GLint level, |
|
285 GLenum internalformat, GLsizei width, |
|
286 GLsizei height, GLint border, |
|
287 const dom::ArrayBufferView& view); |
|
288 void CompressedTexSubImage2D(GLenum target, GLint level, |
|
289 GLint xoffset, GLint yoffset, |
|
290 GLsizei width, GLsizei height, |
|
291 GLenum format, |
|
292 const dom::ArrayBufferView& view); |
|
293 void CopyTexImage2D(GLenum target, GLint level, |
|
294 GLenum internalformat, GLint x, GLint y, |
|
295 GLsizei width, GLsizei height, GLint border); |
|
296 void CopyTexSubImage2D(GLenum target, GLint level, GLint xoffset, |
|
297 GLint yoffset, GLint x, GLint y, |
|
298 GLsizei width, GLsizei height); |
|
299 already_AddRefed<WebGLFramebuffer> CreateFramebuffer(); |
|
300 already_AddRefed<WebGLProgram> CreateProgram(); |
|
301 already_AddRefed<WebGLRenderbuffer> CreateRenderbuffer(); |
|
302 already_AddRefed<WebGLTexture> CreateTexture(); |
|
303 already_AddRefed<WebGLShader> CreateShader(GLenum type); |
|
304 already_AddRefed<WebGLVertexArray> CreateVertexArray(); |
|
305 void CullFace(GLenum face); |
|
306 void DeleteFramebuffer(WebGLFramebuffer *fbuf); |
|
307 void DeleteProgram(WebGLProgram *prog); |
|
308 void DeleteRenderbuffer(WebGLRenderbuffer *rbuf); |
|
309 void DeleteShader(WebGLShader *shader); |
|
310 void DeleteVertexArray(WebGLVertexArray *vao); |
|
311 void DeleteTexture(WebGLTexture *tex); |
|
312 void DepthFunc(GLenum func); |
|
313 void DepthMask(WebGLboolean b); |
|
314 void DepthRange(GLclampf zNear, GLclampf zFar); |
|
315 void DetachShader(WebGLProgram *program, WebGLShader *shader); |
|
316 void DrawBuffers(const dom::Sequence<GLenum>& buffers); |
|
317 void Flush(); |
|
318 void Finish(); |
|
319 void FramebufferRenderbuffer(GLenum target, GLenum attachment, |
|
320 GLenum rbtarget, WebGLRenderbuffer *wrb); |
|
321 void FramebufferTexture2D(GLenum target, GLenum attachment, |
|
322 GLenum textarget, WebGLTexture *tobj, |
|
323 GLint level); |
|
324 void FrontFace(GLenum mode); |
|
325 void GenerateMipmap(GLenum target); |
|
326 already_AddRefed<WebGLActiveInfo> GetActiveAttrib(WebGLProgram *prog, |
|
327 GLuint index); |
|
328 already_AddRefed<WebGLActiveInfo> GetActiveUniform(WebGLProgram *prog, |
|
329 GLuint index); |
|
330 void GetAttachedShaders(WebGLProgram* prog, |
|
331 dom::Nullable< nsTArray<WebGLShader*> > &retval); |
|
332 GLint GetAttribLocation(WebGLProgram* prog, const nsAString& name); |
|
333 JS::Value GetBufferParameter(GLenum target, GLenum pname); |
|
334 void GetBufferParameter(JSContext* /* unused */, GLenum target, |
|
335 GLenum pname, |
|
336 JS::MutableHandle<JS::Value> retval) { |
|
337 retval.set(GetBufferParameter(target, pname)); |
|
338 } |
|
339 GLenum GetError(); |
|
340 JS::Value GetFramebufferAttachmentParameter(JSContext* cx, |
|
341 GLenum target, |
|
342 GLenum attachment, |
|
343 GLenum pname, |
|
344 ErrorResult& rv); |
|
345 void GetFramebufferAttachmentParameter(JSContext* cx, |
|
346 GLenum target, |
|
347 GLenum attachment, |
|
348 GLenum pname, |
|
349 JS::MutableHandle<JS::Value> retval, |
|
350 ErrorResult& rv) { |
|
351 retval.set(GetFramebufferAttachmentParameter(cx, target, attachment, |
|
352 pname, rv)); |
|
353 } |
|
354 JS::Value GetProgramParameter(WebGLProgram *prog, GLenum pname); |
|
355 void GetProgramParameter(JSContext* /* unused */, WebGLProgram *prog, |
|
356 GLenum pname, |
|
357 JS::MutableHandle<JS::Value> retval) { |
|
358 retval.set(GetProgramParameter(prog, pname)); |
|
359 } |
|
360 void GetProgramInfoLog(WebGLProgram *prog, nsACString& retval); |
|
361 void GetProgramInfoLog(WebGLProgram *prog, nsAString& retval); |
|
362 JS::Value GetRenderbufferParameter(GLenum target, GLenum pname); |
|
363 void GetRenderbufferParameter(JSContext* /* unused */, |
|
364 GLenum target, GLenum pname, |
|
365 JS::MutableHandle<JS::Value> retval) { |
|
366 retval.set(GetRenderbufferParameter(target, pname)); |
|
367 } |
|
368 JS::Value GetShaderParameter(WebGLShader *shader, GLenum pname); |
|
369 void GetShaderParameter(JSContext* /* unused */, WebGLShader *shader, |
|
370 GLenum pname, |
|
371 JS::MutableHandle<JS::Value> retval) { |
|
372 retval.set(GetShaderParameter(shader, pname)); |
|
373 } |
|
374 already_AddRefed<WebGLShaderPrecisionFormat> |
|
375 GetShaderPrecisionFormat(GLenum shadertype, GLenum precisiontype); |
|
376 void GetShaderInfoLog(WebGLShader *shader, nsACString& retval); |
|
377 void GetShaderInfoLog(WebGLShader *shader, nsAString& retval); |
|
378 void GetShaderSource(WebGLShader *shader, nsAString& retval); |
|
379 void GetShaderTranslatedSource(WebGLShader *shader, nsAString& retval); |
|
380 JS::Value GetTexParameter(GLenum target, GLenum pname); |
|
381 void GetTexParameter(JSContext * /* unused */, GLenum target, |
|
382 GLenum pname, |
|
383 JS::MutableHandle<JS::Value> retval) { |
|
384 retval.set(GetTexParameter(target, pname)); |
|
385 } |
|
386 JS::Value GetUniform(JSContext* cx, WebGLProgram *prog, |
|
387 WebGLUniformLocation *location); |
|
388 void GetUniform(JSContext* cx, WebGLProgram *prog, |
|
389 WebGLUniformLocation *location, |
|
390 JS::MutableHandle<JS::Value> retval) { |
|
391 retval.set(GetUniform(cx, prog, location)); |
|
392 } |
|
393 already_AddRefed<WebGLUniformLocation> |
|
394 GetUniformLocation(WebGLProgram *prog, const nsAString& name); |
|
395 void Hint(GLenum target, GLenum mode); |
|
396 bool IsFramebuffer(WebGLFramebuffer *fb); |
|
397 bool IsProgram(WebGLProgram *prog); |
|
398 bool IsRenderbuffer(WebGLRenderbuffer *rb); |
|
399 bool IsShader(WebGLShader *shader); |
|
400 bool IsTexture(WebGLTexture *tex); |
|
401 bool IsVertexArray(WebGLVertexArray *vao); |
|
402 void LineWidth(GLfloat width); |
|
403 void LinkProgram(WebGLProgram *program); |
|
404 void PixelStorei(GLenum pname, GLint param); |
|
405 void PolygonOffset(GLfloat factor, GLfloat units); |
|
406 void ReadPixels(GLint x, GLint y, GLsizei width, GLsizei height, |
|
407 GLenum format, GLenum type, |
|
408 const Nullable<dom::ArrayBufferView> &pixels, |
|
409 ErrorResult& rv); |
|
410 void RenderbufferStorage(GLenum target, GLenum internalformat, |
|
411 GLsizei width, GLsizei height); |
|
412 void SampleCoverage(GLclampf value, WebGLboolean invert); |
|
413 void Scissor(GLint x, GLint y, GLsizei width, GLsizei height); |
|
414 void ShaderSource(WebGLShader *shader, const nsAString& source); |
|
415 void StencilFunc(GLenum func, GLint ref, GLuint mask); |
|
416 void StencilFuncSeparate(GLenum face, GLenum func, GLint ref, |
|
417 GLuint mask); |
|
418 void StencilMask(GLuint mask); |
|
419 void StencilMaskSeparate(GLenum face, GLuint mask); |
|
420 void StencilOp(GLenum sfail, GLenum dpfail, GLenum dppass); |
|
421 void StencilOpSeparate(GLenum face, GLenum sfail, GLenum dpfail, |
|
422 GLenum dppass); |
|
423 void TexImage2D(GLenum target, GLint level, |
|
424 GLenum internalformat, GLsizei width, |
|
425 GLsizei height, GLint border, GLenum format, |
|
426 GLenum type, |
|
427 const Nullable<dom::ArrayBufferView> &pixels, |
|
428 ErrorResult& rv); |
|
429 void TexImage2D(GLenum target, GLint level, |
|
430 GLenum internalformat, GLenum format, GLenum type, |
|
431 dom::ImageData* pixels, ErrorResult& rv); |
|
432 // Allow whatever element types the bindings are willing to pass |
|
433 // us in TexImage2D |
|
434 template<class ElementType> |
|
435 void TexImage2D(GLenum target, GLint level, |
|
436 GLenum internalformat, GLenum format, GLenum type, |
|
437 ElementType& elt, ErrorResult& rv) |
|
438 { |
|
439 if (IsContextLost()) |
|
440 return; |
|
441 RefPtr<gfx::DataSourceSurface> data; |
|
442 WebGLTexelFormat srcFormat; |
|
443 nsLayoutUtils::SurfaceFromElementResult res = SurfaceFromElement(elt); |
|
444 rv = SurfaceFromElementResultToImageSurface(res, data, |
|
445 &srcFormat); |
|
446 if (rv.Failed() || !data) |
|
447 return; |
|
448 |
|
449 gfx::IntSize size = data->GetSize(); |
|
450 uint32_t byteLength = data->Stride() * size.height; |
|
451 return TexImage2D_base(target, level, internalformat, |
|
452 size.width, size.height, data->Stride(), |
|
453 0, format, type, data->GetData(), byteLength, |
|
454 -1, srcFormat, mPixelStorePremultiplyAlpha); |
|
455 } |
|
456 void TexParameterf(GLenum target, GLenum pname, GLfloat param) { |
|
457 TexParameter_base(target, pname, nullptr, ¶m); |
|
458 } |
|
459 void TexParameteri(GLenum target, GLenum pname, GLint param) { |
|
460 TexParameter_base(target, pname, ¶m, nullptr); |
|
461 } |
|
462 |
|
463 void TexSubImage2D(GLenum target, GLint level, |
|
464 GLint xoffset, GLint yoffset, |
|
465 GLsizei width, GLsizei height, GLenum format, |
|
466 GLenum type, |
|
467 const Nullable<dom::ArrayBufferView> &pixels, |
|
468 ErrorResult& rv); |
|
469 void TexSubImage2D(GLenum target, GLint level, |
|
470 GLint xoffset, GLint yoffset, GLenum format, |
|
471 GLenum type, dom::ImageData* pixels, ErrorResult& rv); |
|
472 // Allow whatever element types the bindings are willing to pass |
|
473 // us in TexSubImage2D |
|
474 template<class ElementType> |
|
475 void TexSubImage2D(GLenum target, GLint level, |
|
476 GLint xoffset, GLint yoffset, GLenum format, |
|
477 GLenum type, ElementType& elt, ErrorResult& rv) |
|
478 { |
|
479 if (IsContextLost()) |
|
480 return; |
|
481 RefPtr<gfx::DataSourceSurface> data; |
|
482 WebGLTexelFormat srcFormat; |
|
483 nsLayoutUtils::SurfaceFromElementResult res = SurfaceFromElement(elt); |
|
484 rv = SurfaceFromElementResultToImageSurface(res, data, |
|
485 &srcFormat); |
|
486 if (rv.Failed() || !data) |
|
487 return; |
|
488 |
|
489 gfx::IntSize size = data->GetSize(); |
|
490 uint32_t byteLength = data->Stride() * size.height; |
|
491 return TexSubImage2D_base(target, level, xoffset, yoffset, |
|
492 size.width, size.height, |
|
493 data->Stride(), format, type, |
|
494 data->GetData(), byteLength, |
|
495 -1, srcFormat, mPixelStorePremultiplyAlpha); |
|
496 |
|
497 } |
|
498 |
|
499 void Uniform1i(WebGLUniformLocation* location, GLint x); |
|
500 void Uniform2i(WebGLUniformLocation* location, GLint x, GLint y); |
|
501 void Uniform3i(WebGLUniformLocation* location, GLint x, GLint y, |
|
502 GLint z); |
|
503 void Uniform4i(WebGLUniformLocation* location, GLint x, GLint y, |
|
504 GLint z, GLint w); |
|
505 |
|
506 void Uniform1f(WebGLUniformLocation* location, GLfloat x); |
|
507 void Uniform2f(WebGLUniformLocation* location, GLfloat x, GLfloat y); |
|
508 void Uniform3f(WebGLUniformLocation* location, GLfloat x, GLfloat y, |
|
509 GLfloat z); |
|
510 void Uniform4f(WebGLUniformLocation* location, GLfloat x, GLfloat y, |
|
511 GLfloat z, GLfloat w); |
|
512 |
|
513 void Uniform1iv(WebGLUniformLocation* location, |
|
514 const dom::Int32Array& arr) { |
|
515 arr.ComputeLengthAndData(); |
|
516 Uniform1iv_base(location, arr.Length(), arr.Data()); |
|
517 } |
|
518 void Uniform1iv(WebGLUniformLocation* location, |
|
519 const dom::Sequence<GLint>& arr) { |
|
520 Uniform1iv_base(location, arr.Length(), arr.Elements()); |
|
521 } |
|
522 void Uniform1iv_base(WebGLUniformLocation* location, uint32_t arrayLength, |
|
523 const GLint* data); |
|
524 |
|
525 void Uniform2iv(WebGLUniformLocation* location, |
|
526 const dom::Int32Array& arr) { |
|
527 arr.ComputeLengthAndData(); |
|
528 Uniform2iv_base(location, arr.Length(), arr.Data()); |
|
529 } |
|
530 void Uniform2iv(WebGLUniformLocation* location, |
|
531 const dom::Sequence<GLint>& arr) { |
|
532 Uniform2iv_base(location, arr.Length(), arr.Elements()); |
|
533 } |
|
534 void Uniform2iv_base(WebGLUniformLocation* location, uint32_t arrayLength, |
|
535 const GLint* data); |
|
536 |
|
537 void Uniform3iv(WebGLUniformLocation* location, |
|
538 const dom::Int32Array& arr) { |
|
539 arr.ComputeLengthAndData(); |
|
540 Uniform3iv_base(location, arr.Length(), arr.Data()); |
|
541 } |
|
542 void Uniform3iv(WebGLUniformLocation* location, |
|
543 const dom::Sequence<GLint>& arr) { |
|
544 Uniform3iv_base(location, arr.Length(), arr.Elements()); |
|
545 } |
|
546 void Uniform3iv_base(WebGLUniformLocation* location, uint32_t arrayLength, |
|
547 const GLint* data); |
|
548 |
|
549 void Uniform4iv(WebGLUniformLocation* location, |
|
550 const dom::Int32Array& arr) { |
|
551 arr.ComputeLengthAndData(); |
|
552 Uniform4iv_base(location, arr.Length(), arr.Data()); |
|
553 } |
|
554 void Uniform4iv(WebGLUniformLocation* location, |
|
555 const dom::Sequence<GLint>& arr) { |
|
556 Uniform4iv_base(location, arr.Length(), arr.Elements()); |
|
557 } |
|
558 void Uniform4iv_base(WebGLUniformLocation* location, uint32_t arrayLength, |
|
559 const GLint* data); |
|
560 |
|
561 void Uniform1fv(WebGLUniformLocation* location, |
|
562 const dom::Float32Array& arr) { |
|
563 arr.ComputeLengthAndData(); |
|
564 Uniform1fv_base(location, arr.Length(), arr.Data()); |
|
565 } |
|
566 void Uniform1fv(WebGLUniformLocation* location, |
|
567 const dom::Sequence<GLfloat>& arr) { |
|
568 Uniform1fv_base(location, arr.Length(), arr.Elements()); |
|
569 } |
|
570 void Uniform1fv_base(WebGLUniformLocation* location, uint32_t arrayLength, |
|
571 const GLfloat* data); |
|
572 |
|
573 void Uniform2fv(WebGLUniformLocation* location, |
|
574 const dom::Float32Array& arr) { |
|
575 arr.ComputeLengthAndData(); |
|
576 Uniform2fv_base(location, arr.Length(), arr.Data()); |
|
577 } |
|
578 void Uniform2fv(WebGLUniformLocation* location, |
|
579 const dom::Sequence<GLfloat>& arr) { |
|
580 Uniform2fv_base(location, arr.Length(), arr.Elements()); |
|
581 } |
|
582 void Uniform2fv_base(WebGLUniformLocation* location, uint32_t arrayLength, |
|
583 const GLfloat* data); |
|
584 |
|
585 void Uniform3fv(WebGLUniformLocation* location, |
|
586 const dom::Float32Array& arr) { |
|
587 arr.ComputeLengthAndData(); |
|
588 Uniform3fv_base(location, arr.Length(), arr.Data()); |
|
589 } |
|
590 void Uniform3fv(WebGLUniformLocation* location, |
|
591 const dom::Sequence<GLfloat>& arr) { |
|
592 Uniform3fv_base(location, arr.Length(), arr.Elements()); |
|
593 } |
|
594 void Uniform3fv_base(WebGLUniformLocation* location, uint32_t arrayLength, |
|
595 const GLfloat* data); |
|
596 |
|
597 void Uniform4fv(WebGLUniformLocation* location, |
|
598 const dom::Float32Array& arr) { |
|
599 arr.ComputeLengthAndData(); |
|
600 Uniform4fv_base(location, arr.Length(), arr.Data()); |
|
601 } |
|
602 void Uniform4fv(WebGLUniformLocation* location, |
|
603 const dom::Sequence<GLfloat>& arr) { |
|
604 Uniform4fv_base(location, arr.Length(), arr.Elements()); |
|
605 } |
|
606 void Uniform4fv_base(WebGLUniformLocation* location, uint32_t arrayLength, |
|
607 const GLfloat* data); |
|
608 |
|
609 void UniformMatrix2fv(WebGLUniformLocation* location, |
|
610 WebGLboolean transpose, |
|
611 const dom::Float32Array &value) { |
|
612 value.ComputeLengthAndData(); |
|
613 UniformMatrix2fv_base(location, transpose, value.Length(), value.Data()); |
|
614 } |
|
615 void UniformMatrix2fv(WebGLUniformLocation* location, |
|
616 WebGLboolean transpose, |
|
617 const dom::Sequence<float> &value) { |
|
618 UniformMatrix2fv_base(location, transpose, value.Length(), |
|
619 value.Elements()); |
|
620 } |
|
621 void UniformMatrix2fv_base(WebGLUniformLocation* location, |
|
622 WebGLboolean transpose, uint32_t arrayLength, |
|
623 const float* data); |
|
624 |
|
625 void UniformMatrix3fv(WebGLUniformLocation* location, |
|
626 WebGLboolean transpose, |
|
627 const dom::Float32Array &value) { |
|
628 value.ComputeLengthAndData(); |
|
629 UniformMatrix3fv_base(location, transpose, value.Length(), value.Data()); |
|
630 } |
|
631 void UniformMatrix3fv(WebGLUniformLocation* location, |
|
632 WebGLboolean transpose, |
|
633 const dom::Sequence<float> &value) { |
|
634 UniformMatrix3fv_base(location, transpose, value.Length(), |
|
635 value.Elements()); |
|
636 } |
|
637 void UniformMatrix3fv_base(WebGLUniformLocation* location, |
|
638 WebGLboolean transpose, uint32_t arrayLength, |
|
639 const float* data); |
|
640 |
|
641 void UniformMatrix4fv(WebGLUniformLocation* location, |
|
642 WebGLboolean transpose, |
|
643 const dom::Float32Array &value) { |
|
644 value.ComputeLengthAndData(); |
|
645 UniformMatrix4fv_base(location, transpose, value.Length(), value.Data()); |
|
646 } |
|
647 void UniformMatrix4fv(WebGLUniformLocation* location, |
|
648 WebGLboolean transpose, |
|
649 const dom::Sequence<float> &value) { |
|
650 UniformMatrix4fv_base(location, transpose, value.Length(), |
|
651 value.Elements()); |
|
652 } |
|
653 void UniformMatrix4fv_base(WebGLUniformLocation* location, |
|
654 WebGLboolean transpose, uint32_t arrayLength, |
|
655 const float* data); |
|
656 |
|
657 void UseProgram(WebGLProgram *prog); |
|
658 bool ValidateAttribArraySetter(const char* name, uint32_t cnt, uint32_t arrayLength); |
|
659 bool ValidateUniformArraySetter(const char* name, uint32_t expectedElemSize, WebGLUniformLocation *location_object, |
|
660 GLint& location, uint32_t& numElementsToUpload, uint32_t arrayLength); |
|
661 bool ValidateUniformMatrixArraySetter(const char* name, int dim, WebGLUniformLocation *location_object, |
|
662 GLint& location, uint32_t& numElementsToUpload, uint32_t arrayLength, |
|
663 WebGLboolean aTranspose); |
|
664 bool ValidateUniformSetter(const char* name, WebGLUniformLocation *location_object, GLint& location); |
|
665 void ValidateProgram(WebGLProgram *prog); |
|
666 bool ValidateUniformLocation(const char* info, WebGLUniformLocation *location_object); |
|
667 bool ValidateSamplerUniformSetter(const char* info, |
|
668 WebGLUniformLocation *location, |
|
669 GLint value); |
|
670 |
|
671 void Viewport(GLint x, GLint y, GLsizei width, GLsizei height); |
|
672 |
|
673 // ----------------------------------------------------------------------------- |
|
674 // Asynchronous Queries (WebGLContextAsyncQueries.cpp) |
|
675 public: |
|
676 already_AddRefed<WebGLQuery> CreateQuery(); |
|
677 void DeleteQuery(WebGLQuery *query); |
|
678 void BeginQuery(GLenum target, WebGLQuery *query); |
|
679 void EndQuery(GLenum target); |
|
680 bool IsQuery(WebGLQuery *query); |
|
681 already_AddRefed<WebGLQuery> GetQuery(GLenum target, GLenum pname); |
|
682 JS::Value GetQueryObject(JSContext* cx, WebGLQuery *query, GLenum pname); |
|
683 void GetQueryObject(JSContext* cx, WebGLQuery *query, GLenum pname, |
|
684 JS::MutableHandle<JS::Value> retval) { |
|
685 retval.set(GetQueryObject(cx, query, pname)); |
|
686 } |
|
687 |
|
688 private: |
|
689 // ANY_SAMPLES_PASSED(_CONSERVATIVE) slot |
|
690 WebGLRefPtr<WebGLQuery> mActiveOcclusionQuery; |
|
691 |
|
692 // LOCAL_GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN slot |
|
693 WebGLRefPtr<WebGLQuery> mActiveTransformFeedbackQuery; |
|
694 |
|
695 WebGLRefPtr<WebGLQuery>* GetQueryTargetSlot(GLenum target, const char* infos); |
|
696 |
|
697 // ----------------------------------------------------------------------------- |
|
698 // Buffer Objects (WebGLContextBuffers.cpp) |
|
699 public: |
|
700 void BindBuffer(GLenum target, WebGLBuffer* buf); |
|
701 void BindBufferBase(GLenum target, GLuint index, WebGLBuffer* buffer); |
|
702 void BindBufferRange(GLenum target, GLuint index, WebGLBuffer* buffer, |
|
703 WebGLintptr offset, WebGLsizeiptr size); |
|
704 void BufferData(GLenum target, WebGLsizeiptr size, GLenum usage); |
|
705 void BufferData(GLenum target, const dom::ArrayBufferView &data, |
|
706 GLenum usage); |
|
707 void BufferData(GLenum target, |
|
708 const Nullable<dom::ArrayBuffer> &maybeData, |
|
709 GLenum usage); |
|
710 void BufferSubData(GLenum target, WebGLsizeiptr byteOffset, |
|
711 const dom::ArrayBufferView &data); |
|
712 void BufferSubData(GLenum target, WebGLsizeiptr byteOffset, |
|
713 const Nullable<dom::ArrayBuffer> &maybeData); |
|
714 already_AddRefed<WebGLBuffer> CreateBuffer(); |
|
715 void DeleteBuffer(WebGLBuffer *buf); |
|
716 bool IsBuffer(WebGLBuffer *buffer); |
|
717 |
|
718 private: |
|
719 // ARRAY_BUFFER slot |
|
720 WebGLRefPtr<WebGLBuffer> mBoundArrayBuffer; |
|
721 |
|
722 // TRANSFORM_FEEDBACK_BUFFER slot |
|
723 WebGLRefPtr<WebGLBuffer> mBoundTransformFeedbackBuffer; |
|
724 |
|
725 // these two functions emit INVALID_ENUM for invalid `target`. |
|
726 WebGLRefPtr<WebGLBuffer>* GetBufferSlotByTarget(GLenum target, const char* infos); |
|
727 WebGLRefPtr<WebGLBuffer>* GetBufferSlotByTargetIndexed(GLenum target, GLuint index, const char* infos); |
|
728 bool ValidateBufferUsageEnum(GLenum target, const char* infos); |
|
729 |
|
730 // ----------------------------------------------------------------------------- |
|
731 // State and State Requests (WebGLContextState.cpp) |
|
732 public: |
|
733 void Disable(GLenum cap); |
|
734 void Enable(GLenum cap); |
|
735 JS::Value GetParameter(JSContext* cx, GLenum pname, ErrorResult& rv); |
|
736 void GetParameter(JSContext* cx, GLenum pname, |
|
737 JS::MutableHandle<JS::Value> retval, ErrorResult& rv) { |
|
738 retval.set(GetParameter(cx, pname, rv)); |
|
739 } |
|
740 void GetParameterIndexed(JSContext* cx, GLenum pname, GLuint index, |
|
741 JS::MutableHandle<JS::Value> retval); |
|
742 bool IsEnabled(GLenum cap); |
|
743 |
|
744 private: |
|
745 // State tracking slots |
|
746 realGLboolean mDitherEnabled; |
|
747 realGLboolean mRasterizerDiscardEnabled; |
|
748 realGLboolean mScissorTestEnabled; |
|
749 |
|
750 bool ValidateCapabilityEnum(GLenum cap, const char* info); |
|
751 realGLboolean* GetStateTrackingSlot(GLenum cap); |
|
752 |
|
753 // ----------------------------------------------------------------------------- |
|
754 // Vertices Feature (WebGLContextVertices.cpp) |
|
755 public: |
|
756 void DrawArrays(GLenum mode, GLint first, GLsizei count); |
|
757 void DrawArraysInstanced(GLenum mode, GLint first, GLsizei count, GLsizei primcount); |
|
758 void DrawElements(GLenum mode, GLsizei count, GLenum type, WebGLintptr byteOffset); |
|
759 void DrawElementsInstanced(GLenum mode, GLsizei count, GLenum type, |
|
760 WebGLintptr byteOffset, GLsizei primcount); |
|
761 |
|
762 void EnableVertexAttribArray(GLuint index); |
|
763 void DisableVertexAttribArray(GLuint index); |
|
764 |
|
765 JS::Value GetVertexAttrib(JSContext* cx, GLuint index, GLenum pname, |
|
766 ErrorResult& rv); |
|
767 void GetVertexAttrib(JSContext* cx, GLuint index, GLenum pname, |
|
768 JS::MutableHandle<JS::Value> retval, |
|
769 ErrorResult& rv) { |
|
770 retval.set(GetVertexAttrib(cx, index, pname, rv)); |
|
771 } |
|
772 WebGLsizeiptr GetVertexAttribOffset(GLuint index, GLenum pname); |
|
773 |
|
774 void VertexAttrib1f(GLuint index, GLfloat x0); |
|
775 void VertexAttrib2f(GLuint index, GLfloat x0, GLfloat x1); |
|
776 void VertexAttrib3f(GLuint index, GLfloat x0, GLfloat x1, |
|
777 GLfloat x2); |
|
778 void VertexAttrib4f(GLuint index, GLfloat x0, GLfloat x1, |
|
779 GLfloat x2, GLfloat x3); |
|
780 |
|
781 void VertexAttrib1fv(GLuint idx, const dom::Float32Array &arr) { |
|
782 arr.ComputeLengthAndData(); |
|
783 VertexAttrib1fv_base(idx, arr.Length(), arr.Data()); |
|
784 } |
|
785 void VertexAttrib1fv(GLuint idx, const dom::Sequence<GLfloat>& arr) { |
|
786 VertexAttrib1fv_base(idx, arr.Length(), arr.Elements()); |
|
787 } |
|
788 |
|
789 void VertexAttrib2fv(GLuint idx, const dom::Float32Array &arr) { |
|
790 arr.ComputeLengthAndData(); |
|
791 VertexAttrib2fv_base(idx, arr.Length(), arr.Data()); |
|
792 } |
|
793 void VertexAttrib2fv(GLuint idx, const dom::Sequence<GLfloat>& arr) { |
|
794 VertexAttrib2fv_base(idx, arr.Length(), arr.Elements()); |
|
795 } |
|
796 |
|
797 void VertexAttrib3fv(GLuint idx, const dom::Float32Array &arr) { |
|
798 arr.ComputeLengthAndData(); |
|
799 VertexAttrib3fv_base(idx, arr.Length(), arr.Data()); |
|
800 } |
|
801 void VertexAttrib3fv(GLuint idx, const dom::Sequence<GLfloat>& arr) { |
|
802 VertexAttrib3fv_base(idx, arr.Length(), arr.Elements()); |
|
803 } |
|
804 |
|
805 void VertexAttrib4fv(GLuint idx, const dom::Float32Array &arr) { |
|
806 arr.ComputeLengthAndData(); |
|
807 VertexAttrib4fv_base(idx, arr.Length(), arr.Data()); |
|
808 } |
|
809 void VertexAttrib4fv(GLuint idx, const dom::Sequence<GLfloat>& arr) { |
|
810 VertexAttrib4fv_base(idx, arr.Length(), arr.Elements()); |
|
811 } |
|
812 |
|
813 void VertexAttribPointer(GLuint index, GLint size, GLenum type, |
|
814 WebGLboolean normalized, GLsizei stride, |
|
815 WebGLintptr byteOffset); |
|
816 void VertexAttribDivisor(GLuint index, GLuint divisor); |
|
817 |
|
818 private: |
|
819 // Cache the max number of vertices and instances that can be read from |
|
820 // bound VBOs (result of ValidateBuffers). |
|
821 bool mBufferFetchingIsVerified; |
|
822 bool mBufferFetchingHasPerVertex; |
|
823 uint32_t mMaxFetchedVertices; |
|
824 uint32_t mMaxFetchedInstances; |
|
825 |
|
826 inline void InvalidateBufferFetching() |
|
827 { |
|
828 mBufferFetchingIsVerified = false; |
|
829 mBufferFetchingHasPerVertex = false; |
|
830 mMaxFetchedVertices = 0; |
|
831 mMaxFetchedInstances = 0; |
|
832 } |
|
833 |
|
834 bool DrawArrays_check(GLint first, GLsizei count, GLsizei primcount, const char* info); |
|
835 bool DrawElements_check(GLsizei count, GLenum type, WebGLintptr byteOffset, |
|
836 GLsizei primcount, const char* info, |
|
837 GLuint* out_upperBound = nullptr); |
|
838 bool DrawInstanced_check(const char* info); |
|
839 void Draw_cleanup(); |
|
840 |
|
841 void VertexAttrib1fv_base(GLuint idx, uint32_t arrayLength, const GLfloat* ptr); |
|
842 void VertexAttrib2fv_base(GLuint idx, uint32_t arrayLength, const GLfloat* ptr); |
|
843 void VertexAttrib3fv_base(GLuint idx, uint32_t arrayLength, const GLfloat* ptr); |
|
844 void VertexAttrib4fv_base(GLuint idx, uint32_t arrayLength, const GLfloat* ptr); |
|
845 |
|
846 bool ValidateBufferFetching(const char *info); |
|
847 bool BindArrayAttribToLocation0(WebGLProgram *program); |
|
848 |
|
849 // ----------------------------------------------------------------------------- |
|
850 // PROTECTED |
|
851 protected: |
|
852 void SetFakeBlackStatus(WebGLContextFakeBlackStatus x) { |
|
853 mFakeBlackStatus = x; |
|
854 } |
|
855 // Returns the current fake-black-status, except if it was Unknown, |
|
856 // in which case this function resolves it first, so it never returns Unknown. |
|
857 WebGLContextFakeBlackStatus ResolvedFakeBlackStatus(); |
|
858 |
|
859 void BindFakeBlackTextures(); |
|
860 void UnbindFakeBlackTextures(); |
|
861 |
|
862 WebGLVertexAttrib0Status WhatDoesVertexAttrib0Need(); |
|
863 bool DoFakeVertexAttrib0(GLuint vertexCount); |
|
864 void UndoFakeVertexAttrib0(); |
|
865 |
|
866 static CheckedUint32 GetImageSize(GLsizei height, |
|
867 GLsizei width, |
|
868 uint32_t pixelSize, |
|
869 uint32_t alignment); |
|
870 |
|
871 // Returns x rounded to the next highest multiple of y. |
|
872 static CheckedUint32 RoundedToNextMultipleOf(CheckedUint32 x, CheckedUint32 y) { |
|
873 return ((x + y - 1) / y) * y; |
|
874 } |
|
875 |
|
876 nsRefPtr<gl::GLContext> gl; |
|
877 |
|
878 CheckedUint32 mGeneration; |
|
879 |
|
880 WebGLContextOptions mOptions; |
|
881 |
|
882 bool mInvalidated; |
|
883 bool mResetLayer; |
|
884 bool mOptionsFrozen; |
|
885 bool mMinCapability; |
|
886 bool mDisableExtensions; |
|
887 bool mHasRobustness; |
|
888 bool mIsMesa; |
|
889 bool mLoseContextOnHeapMinimize; |
|
890 bool mCanLoseContextInForeground; |
|
891 bool mShouldPresent; |
|
892 bool mBackbufferNeedsClear; |
|
893 bool mDisableFragHighP; |
|
894 |
|
895 template<typename WebGLObjectType> |
|
896 void DeleteWebGLObjectsArray(nsTArray<WebGLObjectType>& array); |
|
897 |
|
898 GLuint mActiveTexture; |
|
899 |
|
900 // glGetError sources: |
|
901 bool mEmitContextLostErrorOnce; |
|
902 GLenum mWebGLError; |
|
903 GLenum mUnderlyingGLError; |
|
904 GLenum GetAndFlushUnderlyingGLErrors(); |
|
905 |
|
906 // whether shader validation is supported |
|
907 bool mShaderValidation; |
|
908 |
|
909 // some GL constants |
|
910 int32_t mGLMaxVertexAttribs; |
|
911 int32_t mGLMaxTextureUnits; |
|
912 int32_t mGLMaxTextureSize; |
|
913 int32_t mGLMaxCubeMapTextureSize; |
|
914 int32_t mGLMaxRenderbufferSize; |
|
915 int32_t mGLMaxTextureImageUnits; |
|
916 int32_t mGLMaxVertexTextureImageUnits; |
|
917 int32_t mGLMaxVaryingVectors; |
|
918 int32_t mGLMaxFragmentUniformVectors; |
|
919 int32_t mGLMaxVertexUniformVectors; |
|
920 int32_t mGLMaxColorAttachments; |
|
921 int32_t mGLMaxDrawBuffers; |
|
922 uint32_t mGLMaxTransformFeedbackSeparateAttribs; |
|
923 |
|
924 // Represents current status of the context with respect to context loss. |
|
925 // That is, whether the context is lost, and what part of the context loss |
|
926 // process we currently are at. |
|
927 // This is used to support the WebGL spec's asyncronous nature in handling |
|
928 // context loss. |
|
929 enum ContextStatus { |
|
930 // The context is stable; there either are none or we don't know of any. |
|
931 ContextNotLost, |
|
932 // The context has been lost, but we have not yet sent an event to the |
|
933 // script informing it of this. |
|
934 ContextLostAwaitingEvent, |
|
935 // The context has been lost, and we have sent the script an event |
|
936 // informing it of this. |
|
937 ContextLost, |
|
938 // The context is lost, an event has been sent to the script, and the |
|
939 // script correctly handled the event. We are waiting for the context to |
|
940 // be restored. |
|
941 ContextLostAwaitingRestore |
|
942 }; |
|
943 |
|
944 // ------------------------------------------------------------------------- |
|
945 // WebGL extensions (implemented in WebGLContextExtensions.cpp) |
|
946 typedef EnumeratedArray<WebGLExtensionID, |
|
947 WebGLExtensionID::Max, |
|
948 nsRefPtr<WebGLExtensionBase>> ExtensionsArrayType; |
|
949 |
|
950 ExtensionsArrayType mExtensions; |
|
951 |
|
952 // enable an extension. the extension should not be enabled before. |
|
953 void EnableExtension(WebGLExtensionID ext); |
|
954 |
|
955 // returns true if the extension has been enabled by calling getExtension. |
|
956 bool IsExtensionEnabled(WebGLExtensionID ext) const; |
|
957 |
|
958 // returns true if the extension is supported for this JSContext (this decides what getSupportedExtensions exposes) |
|
959 bool IsExtensionSupported(JSContext *cx, WebGLExtensionID ext) const; |
|
960 bool IsExtensionSupported(WebGLExtensionID ext) const; |
|
961 |
|
962 static const char* GetExtensionString(WebGLExtensionID ext); |
|
963 |
|
964 nsTArray<GLenum> mCompressedTextureFormats; |
|
965 |
|
966 // ------------------------------------------------------------------------- |
|
967 // WebGL 2 specifics (implemented in WebGL2Context.cpp) |
|
968 |
|
969 virtual bool IsWebGL2() const = 0; |
|
970 |
|
971 bool InitWebGL2(); |
|
972 |
|
973 |
|
974 // ------------------------------------------------------------------------- |
|
975 // Validation functions (implemented in WebGLContextValidate.cpp) |
|
976 GLenum BaseTexFormat(GLenum internalFormat) const; |
|
977 |
|
978 bool InitAndValidateGL(); |
|
979 bool ValidateBlendEquationEnum(GLenum cap, const char *info); |
|
980 bool ValidateBlendFuncDstEnum(GLenum mode, const char *info); |
|
981 bool ValidateBlendFuncSrcEnum(GLenum mode, const char *info); |
|
982 bool ValidateBlendFuncEnumsCompatibility(GLenum sfactor, GLenum dfactor, const char *info); |
|
983 bool ValidateTextureTargetEnum(GLenum target, const char *info); |
|
984 bool ValidateComparisonEnum(GLenum target, const char *info); |
|
985 bool ValidateStencilOpEnum(GLenum action, const char *info); |
|
986 bool ValidateFaceEnum(GLenum face, const char *info); |
|
987 bool ValidateTexInputData(GLenum type, int jsArrayType, WebGLTexImageFunc func); |
|
988 bool ValidateDrawModeEnum(GLenum mode, const char *info); |
|
989 bool ValidateAttribIndex(GLuint index, const char *info); |
|
990 bool ValidateStencilParamsForDrawCall(); |
|
991 |
|
992 bool ValidateGLSLVariableName(const nsAString& name, const char *info); |
|
993 bool ValidateGLSLCharacter(char16_t c); |
|
994 bool ValidateGLSLString(const nsAString& string, const char *info); |
|
995 |
|
996 bool ValidateTexImage(GLuint dims, GLenum target, |
|
997 GLint level, GLint internalFormat, |
|
998 GLint xoffset, GLint yoffset, GLint zoffset, |
|
999 GLint width, GLint height, GLint depth, |
|
1000 GLint border, GLenum format, GLenum type, |
|
1001 WebGLTexImageFunc func); |
|
1002 bool ValidateTexImageTarget(GLuint dims, GLenum target, WebGLTexImageFunc func); |
|
1003 bool ValidateTexImageFormat(GLenum format, WebGLTexImageFunc func); |
|
1004 bool ValidateTexImageType(GLenum type, WebGLTexImageFunc func); |
|
1005 bool ValidateTexImageFormatAndType(GLenum format, GLenum type, WebGLTexImageFunc func); |
|
1006 bool ValidateTexImageSize(GLenum target, GLint level, |
|
1007 GLint width, GLint height, GLint depth, |
|
1008 WebGLTexImageFunc func); |
|
1009 bool ValidateTexSubImageSize(GLint x, GLint y, GLint z, |
|
1010 GLsizei width, GLsizei height, GLsizei depth, |
|
1011 GLsizei baseWidth, GLsizei baseHeight, GLsizei baseDepth, |
|
1012 WebGLTexImageFunc func); |
|
1013 |
|
1014 bool ValidateCompTexImageSize(GLenum target, GLint level, GLenum format, |
|
1015 GLint xoffset, GLint yoffset, |
|
1016 GLsizei width, GLsizei height, |
|
1017 GLsizei levelWidth, GLsizei levelHeight, |
|
1018 WebGLTexImageFunc func); |
|
1019 bool ValidateCompTexImageDataSize(GLint level, GLenum format, |
|
1020 GLsizei width, GLsizei height, |
|
1021 uint32_t byteLength, WebGLTexImageFunc func); |
|
1022 |
|
1023 |
|
1024 static uint32_t GetBitsPerTexel(GLenum format, GLenum type); |
|
1025 |
|
1026 void Invalidate(); |
|
1027 void DestroyResourcesAndContext(); |
|
1028 |
|
1029 void MakeContextCurrent() const; |
|
1030 |
|
1031 // helpers |
|
1032 void TexImage2D_base(GLenum target, GLint level, GLenum internalformat, |
|
1033 GLsizei width, GLsizei height, GLsizei srcStrideOrZero, GLint border, |
|
1034 GLenum format, GLenum type, |
|
1035 void *data, uint32_t byteLength, |
|
1036 int jsArrayType, |
|
1037 WebGLTexelFormat srcFormat, bool srcPremultiplied); |
|
1038 void TexSubImage2D_base(GLenum target, GLint level, |
|
1039 GLint xoffset, GLint yoffset, |
|
1040 GLsizei width, GLsizei height, GLsizei srcStrideOrZero, |
|
1041 GLenum format, GLenum type, |
|
1042 void *pixels, uint32_t byteLength, |
|
1043 int jsArrayType, |
|
1044 WebGLTexelFormat srcFormat, bool srcPremultiplied); |
|
1045 void TexParameter_base(GLenum target, GLenum pname, |
|
1046 GLint *intParamPtr, GLfloat *floatParamPtr); |
|
1047 |
|
1048 void ConvertImage(size_t width, size_t height, size_t srcStride, size_t dstStride, |
|
1049 const uint8_t* src, uint8_t *dst, |
|
1050 WebGLTexelFormat srcFormat, bool srcPremultiplied, |
|
1051 WebGLTexelFormat dstFormat, bool dstPremultiplied, |
|
1052 size_t dstTexelSize); |
|
1053 |
|
1054 template<class ElementType> |
|
1055 nsLayoutUtils::SurfaceFromElementResult SurfaceFromElement(ElementType* aElement) { |
|
1056 MOZ_ASSERT(aElement); |
|
1057 uint32_t flags = |
|
1058 nsLayoutUtils::SFE_WANT_IMAGE_SURFACE; |
|
1059 |
|
1060 if (mPixelStoreColorspaceConversion == LOCAL_GL_NONE) |
|
1061 flags |= nsLayoutUtils::SFE_NO_COLORSPACE_CONVERSION; |
|
1062 if (!mPixelStorePremultiplyAlpha) |
|
1063 flags |= nsLayoutUtils::SFE_PREFER_NO_PREMULTIPLY_ALPHA; |
|
1064 return nsLayoutUtils::SurfaceFromElement(aElement, flags); |
|
1065 } |
|
1066 template<class ElementType> |
|
1067 nsLayoutUtils::SurfaceFromElementResult SurfaceFromElement(ElementType& aElement) |
|
1068 { |
|
1069 return SurfaceFromElement(&aElement); |
|
1070 } |
|
1071 |
|
1072 nsresult SurfaceFromElementResultToImageSurface(nsLayoutUtils::SurfaceFromElementResult& res, |
|
1073 RefPtr<gfx::DataSourceSurface>& imageOut, |
|
1074 WebGLTexelFormat *format); |
|
1075 |
|
1076 void CopyTexSubImage2D_base(GLenum target, |
|
1077 GLint level, |
|
1078 GLenum internalformat, |
|
1079 GLint xoffset, |
|
1080 GLint yoffset, |
|
1081 GLint x, |
|
1082 GLint y, |
|
1083 GLsizei width, |
|
1084 GLsizei height, |
|
1085 bool sub); |
|
1086 |
|
1087 // Returns false if aObject is null or not valid |
|
1088 template<class ObjectType> |
|
1089 bool ValidateObject(const char* info, ObjectType *aObject); |
|
1090 // Returns false if aObject is not valid. Considers null to be valid. |
|
1091 template<class ObjectType> |
|
1092 bool ValidateObjectAllowNull(const char* info, ObjectType *aObject); |
|
1093 // Returns false if aObject is not valid, but considers deleted |
|
1094 // objects and null objects valid. |
|
1095 template<class ObjectType> |
|
1096 bool ValidateObjectAllowDeletedOrNull(const char* info, ObjectType *aObject); |
|
1097 // Returns false if aObject is null or not valid, but considers deleted |
|
1098 // objects valid. |
|
1099 template<class ObjectType> |
|
1100 bool ValidateObjectAllowDeleted(const char* info, ObjectType *aObject); |
|
1101 private: |
|
1102 // Like ValidateObject, but only for cases when aObject is known |
|
1103 // to not be null already. |
|
1104 template<class ObjectType> |
|
1105 bool ValidateObjectAssumeNonNull(const char* info, ObjectType *aObject); |
|
1106 |
|
1107 protected: |
|
1108 int32_t MaxTextureSizeForTarget(GLenum target) const { |
|
1109 MOZ_ASSERT(target == LOCAL_GL_TEXTURE_2D || |
|
1110 (target >= LOCAL_GL_TEXTURE_CUBE_MAP_POSITIVE_X && |
|
1111 target <= LOCAL_GL_TEXTURE_CUBE_MAP_NEGATIVE_Z), |
|
1112 "Invalid target enum"); |
|
1113 return (target == LOCAL_GL_TEXTURE_2D) ? mGLMaxTextureSize : mGLMaxCubeMapTextureSize; |
|
1114 } |
|
1115 |
|
1116 /** like glBufferData but if the call may change the buffer size, checks any GL error generated |
|
1117 * by this glBufferData call and returns it */ |
|
1118 GLenum CheckedBufferData(GLenum target, |
|
1119 GLsizeiptr size, |
|
1120 const GLvoid *data, |
|
1121 GLenum usage); |
|
1122 /** like glTexImage2D but if the call may change the texture size, checks any GL error generated |
|
1123 * by this glTexImage2D call and returns it */ |
|
1124 GLenum CheckedTexImage2D(GLenum target, |
|
1125 GLint level, |
|
1126 GLenum internalFormat, |
|
1127 GLsizei width, |
|
1128 GLsizei height, |
|
1129 GLint border, |
|
1130 GLenum format, |
|
1131 GLenum type, |
|
1132 const GLvoid *data); |
|
1133 |
|
1134 void MaybeRestoreContext(); |
|
1135 void ForceLoseContext(); |
|
1136 void ForceRestoreContext(); |
|
1137 |
|
1138 nsTArray<WebGLRefPtr<WebGLTexture> > mBound2DTextures; |
|
1139 nsTArray<WebGLRefPtr<WebGLTexture> > mBoundCubeMapTextures; |
|
1140 |
|
1141 WebGLRefPtr<WebGLProgram> mCurrentProgram; |
|
1142 |
|
1143 uint32_t mMaxFramebufferColorAttachments; |
|
1144 |
|
1145 WebGLRefPtr<WebGLFramebuffer> mBoundFramebuffer; |
|
1146 WebGLRefPtr<WebGLRenderbuffer> mBoundRenderbuffer; |
|
1147 WebGLRefPtr<WebGLVertexArray> mBoundVertexArray; |
|
1148 |
|
1149 LinkedList<WebGLTexture> mTextures; |
|
1150 LinkedList<WebGLBuffer> mBuffers; |
|
1151 LinkedList<WebGLProgram> mPrograms; |
|
1152 LinkedList<WebGLQuery> mQueries; |
|
1153 LinkedList<WebGLShader> mShaders; |
|
1154 LinkedList<WebGLRenderbuffer> mRenderbuffers; |
|
1155 LinkedList<WebGLFramebuffer> mFramebuffers; |
|
1156 LinkedList<WebGLVertexArray> mVertexArrays; |
|
1157 |
|
1158 WebGLRefPtr<WebGLVertexArray> mDefaultVertexArray; |
|
1159 |
|
1160 // PixelStore parameters |
|
1161 uint32_t mPixelStorePackAlignment, mPixelStoreUnpackAlignment, mPixelStoreColorspaceConversion; |
|
1162 bool mPixelStoreFlipY, mPixelStorePremultiplyAlpha; |
|
1163 |
|
1164 WebGLContextFakeBlackStatus mFakeBlackStatus; |
|
1165 |
|
1166 class FakeBlackTexture |
|
1167 { |
|
1168 gl::GLContext* mGL; |
|
1169 GLuint mGLName; |
|
1170 |
|
1171 public: |
|
1172 FakeBlackTexture(gl::GLContext* gl, GLenum target, GLenum format); |
|
1173 ~FakeBlackTexture(); |
|
1174 GLuint GLName() const { return mGLName; } |
|
1175 }; |
|
1176 |
|
1177 ScopedDeletePtr<FakeBlackTexture> mBlackOpaqueTexture2D, |
|
1178 mBlackOpaqueTextureCubeMap, |
|
1179 mBlackTransparentTexture2D, |
|
1180 mBlackTransparentTextureCubeMap; |
|
1181 |
|
1182 void BindFakeBlackTexturesHelper( |
|
1183 GLenum target, |
|
1184 const nsTArray<WebGLRefPtr<WebGLTexture> >& boundTexturesArray, |
|
1185 ScopedDeletePtr<FakeBlackTexture> & opaqueTextureScopedPtr, |
|
1186 ScopedDeletePtr<FakeBlackTexture> & transparentTextureScopedPtr); |
|
1187 |
|
1188 GLfloat mVertexAttrib0Vector[4]; |
|
1189 GLfloat mFakeVertexAttrib0BufferObjectVector[4]; |
|
1190 size_t mFakeVertexAttrib0BufferObjectSize; |
|
1191 GLuint mFakeVertexAttrib0BufferObject; |
|
1192 WebGLVertexAttrib0Status mFakeVertexAttrib0BufferStatus; |
|
1193 |
|
1194 GLint mStencilRefFront, mStencilRefBack; |
|
1195 GLuint mStencilValueMaskFront, mStencilValueMaskBack, |
|
1196 mStencilWriteMaskFront, mStencilWriteMaskBack; |
|
1197 realGLboolean mColorWriteMask[4]; |
|
1198 realGLboolean mDepthWriteMask; |
|
1199 GLfloat mColorClearValue[4]; |
|
1200 GLint mStencilClearValue; |
|
1201 GLfloat mDepthClearValue; |
|
1202 |
|
1203 GLint mViewportX; |
|
1204 GLint mViewportY; |
|
1205 GLsizei mViewportWidth; |
|
1206 GLsizei mViewportHeight; |
|
1207 bool mAlreadyWarnedAboutViewportLargerThanDest; |
|
1208 |
|
1209 nsCOMPtr<nsITimer> mContextRestorer; |
|
1210 bool mAllowRestore; |
|
1211 bool mContextLossTimerRunning; |
|
1212 bool mDrawSinceContextLossTimerSet; |
|
1213 ContextStatus mContextStatus; |
|
1214 bool mContextLostErrorSet; |
|
1215 |
|
1216 // Used for some hardware (particularly Tegra 2 and 4) that likes to |
|
1217 // be Flushed while doing hundreds of draw calls. |
|
1218 int mDrawCallsSinceLastFlush; |
|
1219 |
|
1220 int mAlreadyGeneratedWarnings; |
|
1221 int mMaxWarnings; |
|
1222 bool mAlreadyWarnedAboutFakeVertexAttrib0; |
|
1223 |
|
1224 bool ShouldGenerateWarnings() const; |
|
1225 |
|
1226 uint64_t mLastUseIndex; |
|
1227 |
|
1228 void LoseOldestWebGLContextIfLimitExceeded(); |
|
1229 void UpdateLastUseIndex(); |
|
1230 |
|
1231 template <typename WebGLObjectType> |
|
1232 JS::Value WebGLObjectAsJSValue(JSContext *cx, const WebGLObjectType *, ErrorResult& rv) const; |
|
1233 template <typename WebGLObjectType> |
|
1234 JSObject* WebGLObjectAsJSObject(JSContext *cx, const WebGLObjectType *, ErrorResult& rv) const; |
|
1235 |
|
1236 #ifdef XP_MACOSX |
|
1237 // see bug 713305. This RAII helper guarantees that we're on the discrete GPU, during its lifetime |
|
1238 // Debouncing note: we don't want to switch GPUs too frequently, so try to not create and destroy |
|
1239 // these objects at high frequency. Having WebGLContext's hold one such object seems fine, |
|
1240 // because WebGLContext objects only go away during GC, which shouldn't happen too frequently. |
|
1241 // If in the future GC becomes much more frequent, we may have to revisit then (maybe use a timer). |
|
1242 ForceDiscreteGPUHelperCGL mForceDiscreteGPUHelper; |
|
1243 #endif |
|
1244 |
|
1245 nsRefPtr<WebGLMemoryPressureObserver> mMemoryPressureObserver; |
|
1246 |
|
1247 public: |
|
1248 // console logging helpers |
|
1249 void GenerateWarning(const char *fmt, ...); |
|
1250 void GenerateWarning(const char *fmt, va_list ap); |
|
1251 |
|
1252 friend class WebGLTexture; |
|
1253 friend class WebGLFramebuffer; |
|
1254 friend class WebGLRenderbuffer; |
|
1255 friend class WebGLProgram; |
|
1256 friend class WebGLQuery; |
|
1257 friend class WebGLBuffer; |
|
1258 friend class WebGLShader; |
|
1259 friend class WebGLUniformLocation; |
|
1260 friend class WebGLVertexArray; |
|
1261 }; |
|
1262 |
|
1263 // used by DOM bindings in conjunction with GetParentObject |
|
1264 inline nsISupports* |
|
1265 ToSupports(WebGLContext* context) |
|
1266 { |
|
1267 return static_cast<nsIDOMWebGLRenderingContext*>(context); |
|
1268 } |
|
1269 |
|
1270 /** |
|
1271 ** Template implementations |
|
1272 **/ |
|
1273 |
|
1274 template<class ObjectType> |
|
1275 inline bool |
|
1276 WebGLContext::ValidateObjectAllowDeletedOrNull(const char* info, |
|
1277 ObjectType *aObject) |
|
1278 { |
|
1279 if (aObject && !aObject->IsCompatibleWithContext(this)) { |
|
1280 ErrorInvalidOperation("%s: object from different WebGL context " |
|
1281 "(or older generation of this one) " |
|
1282 "passed as argument", info); |
|
1283 return false; |
|
1284 } |
|
1285 |
|
1286 return true; |
|
1287 } |
|
1288 |
|
1289 template<class ObjectType> |
|
1290 inline bool |
|
1291 WebGLContext::ValidateObjectAssumeNonNull(const char* info, ObjectType *aObject) |
|
1292 { |
|
1293 MOZ_ASSERT(aObject); |
|
1294 |
|
1295 if (!ValidateObjectAllowDeletedOrNull(info, aObject)) |
|
1296 return false; |
|
1297 |
|
1298 if (aObject->IsDeleted()) { |
|
1299 ErrorInvalidValue("%s: deleted object passed as argument", info); |
|
1300 return false; |
|
1301 } |
|
1302 |
|
1303 return true; |
|
1304 } |
|
1305 |
|
1306 template<class ObjectType> |
|
1307 inline bool |
|
1308 WebGLContext::ValidateObjectAllowNull(const char* info, ObjectType *aObject) |
|
1309 { |
|
1310 if (!aObject) { |
|
1311 return true; |
|
1312 } |
|
1313 |
|
1314 return ValidateObjectAssumeNonNull(info, aObject); |
|
1315 } |
|
1316 |
|
1317 template<class ObjectType> |
|
1318 inline bool |
|
1319 WebGLContext::ValidateObjectAllowDeleted(const char* info, ObjectType *aObject) |
|
1320 { |
|
1321 if (!aObject) { |
|
1322 ErrorInvalidValue("%s: null object passed as argument", info); |
|
1323 return false; |
|
1324 } |
|
1325 |
|
1326 return ValidateObjectAllowDeletedOrNull(info, aObject); |
|
1327 } |
|
1328 |
|
1329 template<class ObjectType> |
|
1330 inline bool |
|
1331 WebGLContext::ValidateObject(const char* info, ObjectType *aObject) |
|
1332 { |
|
1333 if (!aObject) { |
|
1334 ErrorInvalidValue("%s: null object passed as argument", info); |
|
1335 return false; |
|
1336 } |
|
1337 |
|
1338 return ValidateObjectAssumeNonNull(info, aObject); |
|
1339 } |
|
1340 |
|
1341 class WebGLMemoryPressureObserver MOZ_FINAL |
|
1342 : public nsIObserver |
|
1343 { |
|
1344 public: |
|
1345 NS_DECL_ISUPPORTS |
|
1346 NS_DECL_NSIOBSERVER |
|
1347 |
|
1348 WebGLMemoryPressureObserver(WebGLContext *context) |
|
1349 : mContext(context) |
|
1350 {} |
|
1351 |
|
1352 private: |
|
1353 WebGLContext *mContext; |
|
1354 }; |
|
1355 |
|
1356 } // namespace mozilla |
|
1357 |
|
1358 #endif |