Bumping gaia.json for 1 gaia revision(s) a=gaia-bump
[gecko.git] / dom / canvas / WebGLContextUtils.cpp
blob3a5c4816e2f29d054131fd9c2c76a2200cf4deea
1 /* -*- Mode: C++; tab-width: 20; 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"
8 #include <stdarg.h>
10 #include "GLContext.h"
11 #include "jsapi.h"
12 #include "mozilla/Preferences.h"
13 #include "nsIDOMDataContainerEvent.h"
14 #include "nsIDOMEvent.h"
15 #include "nsIScriptSecurityManager.h"
16 #include "nsIVariant.h"
17 #include "nsServiceManagerUtils.h"
18 #include "prprf.h"
19 #include "WebGLBuffer.h"
20 #include "WebGLExtensions.h"
21 #include "WebGLFramebuffer.h"
22 #include "WebGLProgram.h"
23 #include "WebGLTexture.h"
24 #include "WebGLVertexArray.h"
25 #include "WebGLContextUtils.h"
27 #include "mozilla/dom/ScriptSettings.h"
29 namespace mozilla {
31 using namespace gl;
33 bool
34 IsGLDepthFormat(GLenum webGLFormat)
36 return (webGLFormat == LOCAL_GL_DEPTH_COMPONENT ||
37 webGLFormat == LOCAL_GL_DEPTH_COMPONENT16 ||
38 webGLFormat == LOCAL_GL_DEPTH_COMPONENT32);
41 bool
42 IsGLDepthStencilFormat(GLenum webGLFormat)
44 return (webGLFormat == LOCAL_GL_DEPTH_STENCIL ||
45 webGLFormat == LOCAL_GL_DEPTH24_STENCIL8);
48 bool
49 FormatHasAlpha(GLenum webGLFormat)
51 return webGLFormat == LOCAL_GL_RGBA ||
52 webGLFormat == LOCAL_GL_LUMINANCE_ALPHA ||
53 webGLFormat == LOCAL_GL_ALPHA ||
54 webGLFormat == LOCAL_GL_RGBA4 ||
55 webGLFormat == LOCAL_GL_RGB5_A1 ||
56 webGLFormat == LOCAL_GL_SRGB_ALPHA;
59 GLComponents::GLComponents(GLenum format)
61 mComponents = 0;
63 switch (format) {
64 case LOCAL_GL_RGBA:
65 case LOCAL_GL_RGBA4:
66 case LOCAL_GL_RGBA8:
67 case LOCAL_GL_RGB5_A1:
68 // Luminance + Alpha can be converted
69 // to and from RGBA
70 case LOCAL_GL_LUMINANCE_ALPHA:
71 mComponents |= Components::Alpha;
72 // Drops through
73 case LOCAL_GL_RGB:
74 case LOCAL_GL_RGB565:
75 // Luminance can be converted to and from RGB
76 case LOCAL_GL_LUMINANCE:
77 mComponents |= Components::Red | Components::Green | Components::Blue;
78 break;
79 case LOCAL_GL_ALPHA:
80 mComponents |= Components::Alpha;
81 break;
82 case LOCAL_GL_DEPTH_COMPONENT:
83 mComponents |= Components::Depth;
84 break;
85 case LOCAL_GL_DEPTH_STENCIL:
86 mComponents |= Components::Stencil;
87 break;
88 default:
89 MOZ_ASSERT(false, "Unhandled case - GLComponents");
90 break;
94 bool
95 GLComponents::IsSubsetOf(const GLComponents& other) const
97 return (mComponents | other.mComponents) == other.mComponents;
101 * Convert WebGL/ES format and type into GL format and GL internal
102 * format valid for underlying driver.
104 void
105 DriverFormatsFromFormatAndType(GLContext* gl, GLenum webGLFormat, GLenum webGLType,
106 GLenum* out_driverInternalFormat, GLenum* out_driverFormat)
108 MOZ_ASSERT(out_driverInternalFormat, "out_driverInternalFormat can't be nullptr.");
109 MOZ_ASSERT(out_driverFormat, "out_driverFormat can't be nullptr.");
110 if (!out_driverInternalFormat || !out_driverFormat)
111 return;
113 // ES2 requires that format == internalformat; floating-point is
114 // indicated purely by the type that's loaded. For desktop GL, we
115 // have to specify a floating point internal format.
116 if (gl->IsGLES()) {
117 *out_driverInternalFormat = webGLFormat;
118 *out_driverFormat = webGLFormat;
120 return;
123 GLenum format = webGLFormat;
124 GLenum internalFormat = LOCAL_GL_NONE;
126 if (format == LOCAL_GL_DEPTH_COMPONENT) {
127 if (webGLType == LOCAL_GL_UNSIGNED_SHORT)
128 internalFormat = LOCAL_GL_DEPTH_COMPONENT16;
129 else if (webGLType == LOCAL_GL_UNSIGNED_INT)
130 internalFormat = LOCAL_GL_DEPTH_COMPONENT32;
131 } else if (format == LOCAL_GL_DEPTH_STENCIL) {
132 if (webGLType == LOCAL_GL_UNSIGNED_INT_24_8_EXT)
133 internalFormat = LOCAL_GL_DEPTH24_STENCIL8;
134 } else {
135 switch (webGLType) {
136 case LOCAL_GL_UNSIGNED_BYTE:
137 case LOCAL_GL_UNSIGNED_SHORT_4_4_4_4:
138 case LOCAL_GL_UNSIGNED_SHORT_5_5_5_1:
139 case LOCAL_GL_UNSIGNED_SHORT_5_6_5:
140 internalFormat = format;
141 break;
143 case LOCAL_GL_FLOAT:
144 switch (format) {
145 case LOCAL_GL_RGBA:
146 internalFormat = LOCAL_GL_RGBA32F;
147 break;
149 case LOCAL_GL_RGB:
150 internalFormat = LOCAL_GL_RGB32F;
151 break;
153 case LOCAL_GL_ALPHA:
154 internalFormat = LOCAL_GL_ALPHA32F_ARB;
155 break;
157 case LOCAL_GL_LUMINANCE:
158 internalFormat = LOCAL_GL_LUMINANCE32F_ARB;
159 break;
161 case LOCAL_GL_LUMINANCE_ALPHA:
162 internalFormat = LOCAL_GL_LUMINANCE_ALPHA32F_ARB;
163 break;
165 break;
167 case LOCAL_GL_HALF_FLOAT_OES:
168 switch (format) {
169 case LOCAL_GL_RGBA:
170 internalFormat = LOCAL_GL_RGBA16F;
171 break;
173 case LOCAL_GL_RGB:
174 internalFormat = LOCAL_GL_RGB16F;
175 break;
177 case LOCAL_GL_ALPHA:
178 internalFormat = LOCAL_GL_ALPHA16F_ARB;
179 break;
181 case LOCAL_GL_LUMINANCE:
182 internalFormat = LOCAL_GL_LUMINANCE16F_ARB;
183 break;
185 case LOCAL_GL_LUMINANCE_ALPHA:
186 internalFormat = LOCAL_GL_LUMINANCE_ALPHA16F_ARB;
187 break;
189 break;
191 default:
192 break;
195 // Handle ES2 and GL differences when supporting sRGB internal formats. GL ES
196 // requires that format == internalformat, but GL will fail in this case.
197 // GL requires:
198 // format -> internalformat
199 // GL_RGB GL_SRGB_EXT
200 // GL_RGBA GL_SRGB_ALPHA_EXT
201 switch (format) {
202 case LOCAL_GL_SRGB:
203 internalFormat = format;
204 format = LOCAL_GL_RGB;
205 break;
207 case LOCAL_GL_SRGB_ALPHA:
208 internalFormat = format;
209 format = LOCAL_GL_RGBA;
210 break;
214 MOZ_ASSERT(format != LOCAL_GL_NONE && internalFormat != LOCAL_GL_NONE,
215 "Coding mistake -- bad format/type passed?");
217 *out_driverInternalFormat = internalFormat;
218 *out_driverFormat = format;
221 GLenum
222 DriverTypeFromType(GLContext* gl, GLenum webGLType)
224 if (gl->IsGLES())
225 return webGLType;
227 // convert type for half float if not on GLES2
228 GLenum type = webGLType;
229 if (type == LOCAL_GL_HALF_FLOAT_OES) {
230 if (gl->IsSupported(gl::GLFeature::texture_half_float)) {
231 return LOCAL_GL_HALF_FLOAT;
232 } else {
233 MOZ_ASSERT(gl->IsExtensionSupported(gl::GLContext::OES_texture_half_float));
237 return webGLType;
240 void
241 WebGLContext::GenerateWarning(const char *fmt, ...)
243 va_list ap;
244 va_start(ap, fmt);
246 GenerateWarning(fmt, ap);
248 va_end(ap);
251 void
252 WebGLContext::GenerateWarning(const char *fmt, va_list ap)
254 if (!ShouldGenerateWarnings())
255 return;
257 mAlreadyGeneratedWarnings++;
259 char buf[1024];
260 PR_vsnprintf(buf, 1024, fmt, ap);
262 // no need to print to stderr, as JS_ReportWarning takes care of this for us.
264 AutoJSContext cx;
265 JS_ReportWarning(cx, "WebGL: %s", buf);
266 if (!ShouldGenerateWarnings()) {
267 JS_ReportWarning(cx,
268 "WebGL: No further warnings will be reported for this WebGL context "
269 "(already reported %d warnings)", mAlreadyGeneratedWarnings);
273 bool
274 WebGLContext::ShouldGenerateWarnings() const
276 if (mMaxWarnings == -1) {
277 return true;
280 return mAlreadyGeneratedWarnings < mMaxWarnings;
283 CheckedUint32
284 WebGLContext::GetImageSize(GLsizei height,
285 GLsizei width,
286 uint32_t pixelSize,
287 uint32_t packOrUnpackAlignment)
289 CheckedUint32 checked_plainRowSize = CheckedUint32(width) * pixelSize;
291 // alignedRowSize = row size rounded up to next multiple of packAlignment
292 CheckedUint32 checked_alignedRowSize = RoundedToNextMultipleOf(checked_plainRowSize, packOrUnpackAlignment);
294 // if height is 0, we don't need any memory to store this; without this check, we'll get an overflow
295 CheckedUint32 checked_neededByteLength
296 = height <= 0 ? 0 : (height-1) * checked_alignedRowSize + checked_plainRowSize;
298 return checked_neededByteLength;
301 void
302 WebGLContext::SynthesizeGLError(GLenum err)
304 /* ES2 section 2.5 "GL Errors" states that implementations can have
305 * multiple 'flags', as errors might be caught in different parts of
306 * a distributed implementation.
307 * We're signing up as a distributed implementation here, with
308 * separate flags for WebGL and the underlying GLContext.
310 if (!mWebGLError)
311 mWebGLError = err;
314 void
315 WebGLContext::SynthesizeGLError(GLenum err, const char *fmt, ...)
317 va_list va;
318 va_start(va, fmt);
319 GenerateWarning(fmt, va);
320 va_end(va);
322 return SynthesizeGLError(err);
325 void
326 WebGLContext::ErrorInvalidEnum(const char *fmt, ...)
328 va_list va;
329 va_start(va, fmt);
330 GenerateWarning(fmt, va);
331 va_end(va);
333 return SynthesizeGLError(LOCAL_GL_INVALID_ENUM);
336 void
337 WebGLContext::ErrorInvalidEnumInfo(const char *info, GLenum enumvalue)
339 return ErrorInvalidEnum("%s: invalid enum value 0x%x", info, enumvalue);
342 void
343 WebGLContext::ErrorInvalidOperation(const char *fmt, ...)
345 va_list va;
346 va_start(va, fmt);
347 GenerateWarning(fmt, va);
348 va_end(va);
350 return SynthesizeGLError(LOCAL_GL_INVALID_OPERATION);
353 void
354 WebGLContext::ErrorInvalidValue(const char *fmt, ...)
356 va_list va;
357 va_start(va, fmt);
358 GenerateWarning(fmt, va);
359 va_end(va);
361 return SynthesizeGLError(LOCAL_GL_INVALID_VALUE);
364 void
365 WebGLContext::ErrorInvalidFramebufferOperation(const char *fmt, ...)
367 va_list va;
368 va_start(va, fmt);
369 GenerateWarning(fmt, va);
370 va_end(va);
372 return SynthesizeGLError(LOCAL_GL_INVALID_FRAMEBUFFER_OPERATION);
375 void
376 WebGLContext::ErrorOutOfMemory(const char *fmt, ...)
378 va_list va;
379 va_start(va, fmt);
380 GenerateWarning(fmt, va);
381 va_end(va);
383 return SynthesizeGLError(LOCAL_GL_OUT_OF_MEMORY);
386 const char *
387 WebGLContext::ErrorName(GLenum error)
389 switch(error) {
390 case LOCAL_GL_INVALID_ENUM:
391 return "INVALID_ENUM";
392 case LOCAL_GL_INVALID_OPERATION:
393 return "INVALID_OPERATION";
394 case LOCAL_GL_INVALID_VALUE:
395 return "INVALID_VALUE";
396 case LOCAL_GL_OUT_OF_MEMORY:
397 return "OUT_OF_MEMORY";
398 case LOCAL_GL_INVALID_FRAMEBUFFER_OPERATION:
399 return "INVALID_FRAMEBUFFER_OPERATION";
400 case LOCAL_GL_NO_ERROR:
401 return "NO_ERROR";
402 default:
403 MOZ_ASSERT(false);
404 return "[unknown WebGL error!]";
408 const char*
409 WebGLContext::EnumName(GLenum glenum)
411 switch (glenum) {
412 #define XX(x) case LOCAL_GL_##x: return #x
413 XX(ALPHA);
414 XX(ATC_RGB);
415 XX(ATC_RGBA_EXPLICIT_ALPHA);
416 XX(ATC_RGBA_INTERPOLATED_ALPHA);
417 XX(COMPRESSED_RGBA_PVRTC_2BPPV1);
418 XX(COMPRESSED_RGBA_PVRTC_4BPPV1);
419 XX(COMPRESSED_RGBA_S3TC_DXT1_EXT);
420 XX(COMPRESSED_RGBA_S3TC_DXT3_EXT);
421 XX(COMPRESSED_RGBA_S3TC_DXT5_EXT);
422 XX(COMPRESSED_RGB_PVRTC_2BPPV1);
423 XX(COMPRESSED_RGB_PVRTC_4BPPV1);
424 XX(COMPRESSED_RGB_S3TC_DXT1_EXT);
425 XX(DEPTH_COMPONENT);
426 XX(DEPTH_COMPONENT16);
427 XX(DEPTH_COMPONENT32);
428 XX(DEPTH_STENCIL);
429 XX(DEPTH24_STENCIL8);
430 XX(ETC1_RGB8_OES);
431 XX(FLOAT);
432 XX(HALF_FLOAT);
433 XX(LUMINANCE);
434 XX(LUMINANCE_ALPHA);
435 XX(RGB);
436 XX(RGB16F);
437 XX(RGB32F);
438 XX(RGBA);
439 XX(RGBA16F);
440 XX(RGBA32F);
441 XX(SRGB);
442 XX(SRGB_ALPHA);
443 XX(TEXTURE_2D);
444 XX(TEXTURE_3D);
445 XX(TEXTURE_CUBE_MAP);
446 XX(TEXTURE_CUBE_MAP_NEGATIVE_X);
447 XX(TEXTURE_CUBE_MAP_NEGATIVE_Y);
448 XX(TEXTURE_CUBE_MAP_NEGATIVE_Z);
449 XX(TEXTURE_CUBE_MAP_POSITIVE_X);
450 XX(TEXTURE_CUBE_MAP_POSITIVE_Y);
451 XX(TEXTURE_CUBE_MAP_POSITIVE_Z);
452 XX(UNSIGNED_BYTE);
453 XX(UNSIGNED_INT);
454 XX(UNSIGNED_INT_24_8);
455 XX(UNSIGNED_SHORT);
456 XX(UNSIGNED_SHORT_4_4_4_4);
457 XX(UNSIGNED_SHORT_5_5_5_1);
458 XX(UNSIGNED_SHORT_5_6_5);
459 #undef XX
462 return "[Unknown enum name]";
466 bool
467 WebGLContext::IsTextureFormatCompressed(GLenum format)
469 switch (format) {
470 case LOCAL_GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
471 case LOCAL_GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
472 case LOCAL_GL_COMPRESSED_RGBA_S3TC_DXT3_EXT:
473 case LOCAL_GL_COMPRESSED_RGBA_S3TC_DXT5_EXT:
474 case LOCAL_GL_ATC_RGB:
475 case LOCAL_GL_ATC_RGBA_EXPLICIT_ALPHA:
476 case LOCAL_GL_ATC_RGBA_INTERPOLATED_ALPHA:
477 case LOCAL_GL_COMPRESSED_RGB_PVRTC_4BPPV1:
478 case LOCAL_GL_COMPRESSED_RGB_PVRTC_2BPPV1:
479 case LOCAL_GL_COMPRESSED_RGBA_PVRTC_4BPPV1:
480 case LOCAL_GL_COMPRESSED_RGBA_PVRTC_2BPPV1:
481 case LOCAL_GL_ETC1_RGB8_OES:
482 return true;
483 default:
484 return false;
488 GLenum
489 WebGLContext::GetAndFlushUnderlyingGLErrors()
491 // Get and clear GL error in ALL cases.
492 GLenum error = gl->GetAndClearError();
494 // Only store in mUnderlyingGLError if is hasn't already recorded an
495 // error.
496 if (!mUnderlyingGLError)
497 mUnderlyingGLError = error;
499 return error;
502 #ifdef DEBUG
503 // For NaNs, etc.
504 static bool
505 IsCacheCorrect(float cached, float actual)
507 if (IsNaN(cached)) {
508 // GL is allowed to do anything it wants for NaNs, so if we're shadowing
509 // a NaN, then whatever `actual` is might be correct.
510 return true;
513 return cached == actual;
516 void
517 AssertUintParamCorrect(gl::GLContext* gl, GLenum pname, GLuint shadow)
519 GLuint val = 0;
520 gl->GetUIntegerv(pname, &val);
521 if (val != shadow) {
522 printf_stderr("Failed 0x%04x shadow: Cached 0x%x/%u, should be 0x%x/%u.\n",
523 pname, shadow, shadow, val, val);
524 MOZ_ASSERT(false, "Bad cached value.");
527 #else
528 void
529 AssertUintParamCorrect(gl::GLContext*, GLenum, GLuint)
532 #endif
534 void
535 WebGLContext::AssertCachedBindings()
537 #ifdef DEBUG
538 MakeContextCurrent();
540 GetAndFlushUnderlyingGLErrors();
542 if (IsExtensionEnabled(WebGLExtensionID::OES_vertex_array_object)) {
543 GLuint bound = mBoundVertexArray ? mBoundVertexArray->GLName() : 0;
544 AssertUintParamCorrect(gl, LOCAL_GL_VERTEX_ARRAY_BINDING, bound);
547 // Bound object state
548 GLuint bound = mBoundFramebuffer ? mBoundFramebuffer->GLName() : 0;
549 AssertUintParamCorrect(gl, LOCAL_GL_FRAMEBUFFER_BINDING, bound);
551 bound = mCurrentProgram ? mCurrentProgram->GLName() : 0;
552 AssertUintParamCorrect(gl, LOCAL_GL_CURRENT_PROGRAM, bound);
554 // Textures
555 GLenum activeTexture = mActiveTexture + LOCAL_GL_TEXTURE0;
556 AssertUintParamCorrect(gl, LOCAL_GL_ACTIVE_TEXTURE, activeTexture);
558 WebGLTexture* curTex = activeBoundTextureForTarget(LOCAL_GL_TEXTURE_2D);
559 bound = curTex ? curTex->GLName() : 0;
560 AssertUintParamCorrect(gl, LOCAL_GL_TEXTURE_BINDING_2D, bound);
562 curTex = activeBoundTextureForTarget(LOCAL_GL_TEXTURE_CUBE_MAP);
563 bound = curTex ? curTex->GLName() : 0;
564 AssertUintParamCorrect(gl, LOCAL_GL_TEXTURE_BINDING_CUBE_MAP, bound);
566 // Buffers
567 bound = mBoundArrayBuffer ? mBoundArrayBuffer->GLName() : 0;
568 AssertUintParamCorrect(gl, LOCAL_GL_ARRAY_BUFFER_BINDING, bound);
570 MOZ_ASSERT(mBoundVertexArray);
571 WebGLBuffer* curBuff = mBoundVertexArray->mElementArrayBuffer;
572 bound = curBuff ? curBuff->GLName() : 0;
573 AssertUintParamCorrect(gl, LOCAL_GL_ELEMENT_ARRAY_BUFFER_BINDING, bound);
575 MOZ_ASSERT(!GetAndFlushUnderlyingGLErrors());
576 #endif
579 void
580 WebGLContext::AssertCachedState()
582 #ifdef DEBUG
583 MakeContextCurrent();
585 GetAndFlushUnderlyingGLErrors();
587 // extensions
588 if (IsExtensionEnabled(WebGLExtensionID::WEBGL_draw_buffers)) {
589 AssertUintParamCorrect(gl, LOCAL_GL_MAX_COLOR_ATTACHMENTS, mGLMaxColorAttachments);
590 AssertUintParamCorrect(gl, LOCAL_GL_MAX_DRAW_BUFFERS, mGLMaxDrawBuffers);
593 // Draw state
594 MOZ_ASSERT(gl->fIsEnabled(LOCAL_GL_SCISSOR_TEST) == mScissorTestEnabled);
595 MOZ_ASSERT(gl->fIsEnabled(LOCAL_GL_DITHER) == mDitherEnabled);
596 MOZ_ASSERT_IF(IsWebGL2(),
597 gl->fIsEnabled(LOCAL_GL_RASTERIZER_DISCARD) == mRasterizerDiscardEnabled);
600 realGLboolean colorWriteMask[4] = {0, 0, 0, 0};
601 gl->fGetBooleanv(LOCAL_GL_COLOR_WRITEMASK, colorWriteMask);
602 MOZ_ASSERT(colorWriteMask[0] == mColorWriteMask[0] &&
603 colorWriteMask[1] == mColorWriteMask[1] &&
604 colorWriteMask[2] == mColorWriteMask[2] &&
605 colorWriteMask[3] == mColorWriteMask[3]);
607 GLfloat colorClearValue[4] = {0.0f, 0.0f, 0.0f, 0.0f};
608 gl->fGetFloatv(LOCAL_GL_COLOR_CLEAR_VALUE, colorClearValue);
609 MOZ_ASSERT(IsCacheCorrect(mColorClearValue[0], colorClearValue[0]) &&
610 IsCacheCorrect(mColorClearValue[1], colorClearValue[1]) &&
611 IsCacheCorrect(mColorClearValue[2], colorClearValue[2]) &&
612 IsCacheCorrect(mColorClearValue[3], colorClearValue[3]));
614 realGLboolean depthWriteMask = 0;
615 gl->fGetBooleanv(LOCAL_GL_DEPTH_WRITEMASK, &depthWriteMask);
616 MOZ_ASSERT(depthWriteMask == mDepthWriteMask);
618 GLfloat depthClearValue = 0.0f;
619 gl->fGetFloatv(LOCAL_GL_DEPTH_CLEAR_VALUE, &depthClearValue);
620 MOZ_ASSERT(IsCacheCorrect(mDepthClearValue, depthClearValue));
622 AssertUintParamCorrect(gl, LOCAL_GL_STENCIL_CLEAR_VALUE, mStencilClearValue);
624 AssertUintParamCorrect(gl, LOCAL_GL_STENCIL_REF, mStencilRefFront);
625 AssertUintParamCorrect(gl, LOCAL_GL_STENCIL_BACK_REF, mStencilRefBack);
627 AssertUintParamCorrect(gl, LOCAL_GL_STENCIL_VALUE_MASK, mStencilValueMaskFront);
628 AssertUintParamCorrect(gl, LOCAL_GL_STENCIL_BACK_VALUE_MASK, mStencilValueMaskBack);
630 AssertUintParamCorrect(gl, LOCAL_GL_STENCIL_WRITEMASK, mStencilWriteMaskFront);
631 AssertUintParamCorrect(gl, LOCAL_GL_STENCIL_BACK_WRITEMASK, mStencilWriteMaskBack);
633 // Viewport
634 GLint int4[4] = {0, 0, 0, 0};
635 gl->fGetIntegerv(LOCAL_GL_VIEWPORT, int4);
636 MOZ_ASSERT(int4[0] == mViewportX &&
637 int4[1] == mViewportY &&
638 int4[2] == mViewportWidth &&
639 int4[3] == mViewportHeight);
641 AssertUintParamCorrect(gl, LOCAL_GL_PACK_ALIGNMENT, mPixelStorePackAlignment);
642 AssertUintParamCorrect(gl, LOCAL_GL_UNPACK_ALIGNMENT, mPixelStoreUnpackAlignment);
644 MOZ_ASSERT(!GetAndFlushUnderlyingGLErrors());
645 #endif
648 } // namespace mozilla