LCOV - code coverage report
Current view: directory - content/canvas/src - WebGLContextValidate.cpp (source / functions) Found Hit Coverage
Test: app.info Lines: 281 0 0.0 %
Date: 2012-06-02 Functions: 20 0 0.0 %

       1                 : /* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
       2                 : /* ***** BEGIN LICENSE BLOCK *****
       3                 :  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
       4                 :  *
       5                 :  * The contents of this file are subject to the Mozilla Public License Version
       6                 :  * 1.1 (the "License"); you may not use this file except in compliance with
       7                 :  * the License. You may obtain a copy of the License at
       8                 :  * http://www.mozilla.org/MPL/
       9                 :  *
      10                 :  * Software distributed under the License is distributed on an "AS IS" basis,
      11                 :  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
      12                 :  * for the specific language governing rights and limitations under the
      13                 :  * License.
      14                 :  *
      15                 :  * The Original Code is mozilla.org code.
      16                 :  *
      17                 :  * The Initial Developer of the Original Code is
      18                 :  *   Mozilla Corporation.
      19                 :  * Portions created by the Initial Developer are Copyright (C) 2009
      20                 :  * the Initial Developer. All Rights Reserved.
      21                 :  *
      22                 :  * Contributor(s):
      23                 :  *   Vladimir Vukicevic <vladimir@pobox.com> (original author)
      24                 :  *   Mark Steele <mwsteele@gmail.com>
      25                 :  *
      26                 :  * Alternatively, the contents of this file may be used under the terms of
      27                 :  * either the GNU General Public License Version 2 or later (the "GPL"), or
      28                 :  * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
      29                 :  * in which case the provisions of the GPL or the LGPL are applicable instead
      30                 :  * of those above. If you wish to allow use of your version of this file only
      31                 :  * under the terms of either the GPL or the LGPL, and not to allow others to
      32                 :  * use your version of this file under the terms of the MPL, indicate your
      33                 :  * decision by deleting the provisions above and replace them with the notice
      34                 :  * and other provisions required by the GPL or the LGPL. If you do not delete
      35                 :  * the provisions above, a recipient may use your version of this file under
      36                 :  * the terms of any one of the MPL, the GPL or the LGPL.
      37                 :  *
      38                 :  * ***** END LICENSE BLOCK ***** */
      39                 : 
      40                 : #include "WebGLContext.h"
      41                 : 
      42                 : #include "mozilla/Preferences.h"
      43                 : 
      44                 : #include "CheckedInt.h"
      45                 : 
      46                 : #include "jstypedarray.h"
      47                 : 
      48                 : #if defined(USE_ANGLE)
      49                 : #include "angle/ShaderLang.h"
      50                 : #endif
      51                 : 
      52                 : #include <algorithm>
      53                 : 
      54                 : using namespace mozilla;
      55                 : 
      56                 : /*
      57                 :  * Pull data out of the program, post-linking
      58                 :  */
      59                 : bool
      60               0 : WebGLProgram::UpdateInfo()
      61                 : {
      62               0 :     mIdentifierMap = nsnull;
      63               0 :     mIdentifierReverseMap = nsnull;
      64                 : 
      65               0 :     mAttribMaxNameLength = 0;
      66                 : 
      67               0 :     for (size_t i = 0; i < mAttachedShaders.Length(); i++)
      68               0 :         mAttribMaxNameLength = NS_MAX(mAttribMaxNameLength, mAttachedShaders[i]->mAttribMaxNameLength);
      69                 : 
      70                 :     GLint attribCount;
      71               0 :     mContext->gl->fGetProgramiv(mGLName, LOCAL_GL_ACTIVE_ATTRIBUTES, &attribCount);
      72                 : 
      73               0 :     mAttribsInUse.resize(mContext->mGLMaxVertexAttribs);
      74               0 :     std::fill(mAttribsInUse.begin(), mAttribsInUse.end(), false);
      75                 : 
      76               0 :     nsAutoArrayPtr<char> nameBuf(new char[mAttribMaxNameLength]);
      77                 : 
      78               0 :     for (int i = 0; i < attribCount; ++i) {
      79                 :         GLint attrnamelen;
      80                 :         GLint attrsize;
      81                 :         GLenum attrtype;
      82               0 :         mContext->gl->fGetActiveAttrib(mGLName, i, mAttribMaxNameLength, &attrnamelen, &attrsize, &attrtype, nameBuf);
      83               0 :         if (attrnamelen > 0) {
      84               0 :             GLint loc = mContext->gl->fGetAttribLocation(mGLName, nameBuf);
      85               0 :             NS_ABORT_IF_FALSE(loc >= 0, "major oops in managing the attributes of a WebGL program");
      86               0 :             if (loc < mContext->mGLMaxVertexAttribs) {
      87               0 :                 mAttribsInUse[loc] = true;
      88                 :             } else {
      89               0 :                 mContext->ErrorInvalidOperation("program exceeds MAX_VERTEX_ATTRIBS");
      90               0 :                 return false;
      91                 :             }
      92                 :         }
      93                 :     }
      94                 : 
      95               0 :     return true;
      96                 : }
      97                 : 
      98                 : /*
      99                 :  * Verify that state is consistent for drawing, and compute max number of elements (maxAllowedCount)
     100                 :  * that will be legal to be read from bound VBOs.
     101                 :  */
     102                 : 
     103                 : bool
     104               0 : WebGLContext::ValidateBuffers(PRInt32 *maxAllowedCount, const char *info)
     105                 : {
     106                 : #ifdef DEBUG
     107               0 :     GLint currentProgram = 0;
     108               0 :     MakeContextCurrent();
     109               0 :     gl->fGetIntegerv(LOCAL_GL_CURRENT_PROGRAM, &currentProgram);
     110               0 :     NS_ASSERTION(GLuint(currentProgram) == mCurrentProgram->GLName(),
     111                 :                  "WebGL: current program doesn't agree with GL state");
     112               0 :     if (GLuint(currentProgram) != mCurrentProgram->GLName())
     113               0 :         return false;
     114                 : #endif
     115                 : 
     116               0 :     *maxAllowedCount = -1;
     117                 : 
     118               0 :     PRUint32 attribs = mAttribBuffers.Length();
     119               0 :     for (PRUint32 i = 0; i < attribs; ++i) {
     120               0 :         const WebGLVertexAttribData& vd = mAttribBuffers[i];
     121                 : 
     122                 :         // If the attrib array isn't enabled, there's nothing to check;
     123                 :         // it's a static value.
     124               0 :         if (!vd.enabled)
     125               0 :             continue;
     126                 : 
     127               0 :         if (vd.buf == nsnull) {
     128               0 :             ErrorInvalidOperation("%s: no VBO bound to enabled vertex attrib index %d!", info, i);
     129               0 :             return false;
     130                 :         }
     131                 : 
     132                 :         // If the attrib is not in use, then we don't have to validate
     133                 :         // it, just need to make sure that the binding is non-null.
     134               0 :         if (!mCurrentProgram->IsAttribInUse(i))
     135               0 :             continue;
     136                 : 
     137                 :         // the base offset
     138                 :         CheckedInt32 checked_byteLength
     139               0 :           = CheckedInt32(vd.buf->ByteLength()) - vd.byteOffset;
     140                 :         CheckedInt32 checked_sizeOfLastElement
     141               0 :           = CheckedInt32(vd.componentSize()) * vd.size;
     142                 : 
     143               0 :         if (!checked_byteLength.valid() ||
     144               0 :             !checked_sizeOfLastElement.valid())
     145                 :         {
     146               0 :           ErrorInvalidOperation("%s: integer overflow occured while checking vertex attrib %d", info, i);
     147               0 :           return false;
     148                 :         }
     149                 : 
     150               0 :         if (checked_byteLength.value() < checked_sizeOfLastElement.value()) {
     151               0 :           *maxAllowedCount = 0;
     152                 :         } else {
     153                 :           CheckedInt32 checked_maxAllowedCount
     154               0 :             = ((checked_byteLength - checked_sizeOfLastElement) / vd.actualStride()) + 1;
     155                 : 
     156               0 :           if (!checked_maxAllowedCount.valid()) {
     157               0 :             ErrorInvalidOperation("%s: integer overflow occured while checking vertex attrib %d", info, i);
     158               0 :             return false;
     159                 :           }
     160                 : 
     161               0 :           if (*maxAllowedCount == -1 || *maxAllowedCount > checked_maxAllowedCount.value())
     162               0 :               *maxAllowedCount = checked_maxAllowedCount.value();
     163                 :         }
     164                 :     }
     165                 : 
     166               0 :     return true;
     167                 : }
     168                 : 
     169               0 : bool WebGLContext::ValidateCapabilityEnum(WebGLenum cap, const char *info)
     170                 : {
     171               0 :     switch (cap) {
     172                 :         case LOCAL_GL_BLEND:
     173                 :         case LOCAL_GL_CULL_FACE:
     174                 :         case LOCAL_GL_DEPTH_TEST:
     175                 :         case LOCAL_GL_DITHER:
     176                 :         case LOCAL_GL_POLYGON_OFFSET_FILL:
     177                 :         case LOCAL_GL_SAMPLE_ALPHA_TO_COVERAGE:
     178                 :         case LOCAL_GL_SAMPLE_COVERAGE:
     179                 :         case LOCAL_GL_SCISSOR_TEST:
     180                 :         case LOCAL_GL_STENCIL_TEST:
     181               0 :             return true;
     182                 :         default:
     183               0 :             ErrorInvalidEnumInfo(info, cap);
     184               0 :             return false;
     185                 :     }
     186                 : }
     187                 : 
     188               0 : bool WebGLContext::ValidateBlendEquationEnum(WebGLenum mode, const char *info)
     189                 : {
     190               0 :     switch (mode) {
     191                 :         case LOCAL_GL_FUNC_ADD:
     192                 :         case LOCAL_GL_FUNC_SUBTRACT:
     193                 :         case LOCAL_GL_FUNC_REVERSE_SUBTRACT:
     194               0 :             return true;
     195                 :         default:
     196               0 :             ErrorInvalidEnumInfo(info, mode);
     197               0 :             return false;
     198                 :     }
     199                 : }
     200                 : 
     201               0 : bool WebGLContext::ValidateBlendFuncDstEnum(WebGLenum factor, const char *info)
     202                 : {
     203               0 :     switch (factor) {
     204                 :         case LOCAL_GL_ZERO:
     205                 :         case LOCAL_GL_ONE:
     206                 :         case LOCAL_GL_SRC_COLOR:
     207                 :         case LOCAL_GL_ONE_MINUS_SRC_COLOR:
     208                 :         case LOCAL_GL_DST_COLOR:
     209                 :         case LOCAL_GL_ONE_MINUS_DST_COLOR:
     210                 :         case LOCAL_GL_SRC_ALPHA:
     211                 :         case LOCAL_GL_ONE_MINUS_SRC_ALPHA:
     212                 :         case LOCAL_GL_DST_ALPHA:
     213                 :         case LOCAL_GL_ONE_MINUS_DST_ALPHA:
     214                 :         case LOCAL_GL_CONSTANT_COLOR:
     215                 :         case LOCAL_GL_ONE_MINUS_CONSTANT_COLOR:
     216                 :         case LOCAL_GL_CONSTANT_ALPHA:
     217                 :         case LOCAL_GL_ONE_MINUS_CONSTANT_ALPHA:
     218               0 :             return true;
     219                 :         default:
     220               0 :             ErrorInvalidEnumInfo(info, factor);
     221               0 :             return false;
     222                 :     }
     223                 : }
     224                 : 
     225               0 : bool WebGLContext::ValidateBlendFuncSrcEnum(WebGLenum factor, const char *info)
     226                 : {
     227               0 :     if (factor == LOCAL_GL_SRC_ALPHA_SATURATE)
     228               0 :         return true;
     229                 :     else
     230               0 :         return ValidateBlendFuncDstEnum(factor, info);
     231                 : }
     232                 : 
     233               0 : bool WebGLContext::ValidateBlendFuncEnumsCompatibility(WebGLenum sfactor, WebGLenum dfactor, const char *info)
     234                 : {
     235                 :     bool sfactorIsConstantColor = sfactor == LOCAL_GL_CONSTANT_COLOR ||
     236               0 :                                     sfactor == LOCAL_GL_ONE_MINUS_CONSTANT_COLOR;
     237                 :     bool sfactorIsConstantAlpha = sfactor == LOCAL_GL_CONSTANT_ALPHA ||
     238               0 :                                     sfactor == LOCAL_GL_ONE_MINUS_CONSTANT_ALPHA;
     239                 :     bool dfactorIsConstantColor = dfactor == LOCAL_GL_CONSTANT_COLOR ||
     240               0 :                                     dfactor == LOCAL_GL_ONE_MINUS_CONSTANT_COLOR;
     241                 :     bool dfactorIsConstantAlpha = dfactor == LOCAL_GL_CONSTANT_ALPHA ||
     242               0 :                                     dfactor == LOCAL_GL_ONE_MINUS_CONSTANT_ALPHA;
     243               0 :     if ( (sfactorIsConstantColor && dfactorIsConstantAlpha) ||
     244                 :          (dfactorIsConstantColor && sfactorIsConstantAlpha) ) {
     245               0 :         ErrorInvalidOperation("%s are mutually incompatible, see section 6.8 in the WebGL 1.0 spec", info);
     246               0 :         return false;
     247                 :     } else {
     248               0 :         return true;
     249                 :     }
     250                 : }
     251                 : 
     252               0 : bool WebGLContext::ValidateTextureTargetEnum(WebGLenum target, const char *info)
     253                 : {
     254               0 :     switch (target) {
     255                 :         case LOCAL_GL_TEXTURE_2D:
     256                 :         case LOCAL_GL_TEXTURE_CUBE_MAP:
     257               0 :             return true;
     258                 :         default:
     259               0 :             ErrorInvalidEnumInfo(info, target);
     260               0 :             return false;
     261                 :     }
     262                 : }
     263                 : 
     264               0 : bool WebGLContext::ValidateComparisonEnum(WebGLenum target, const char *info)
     265                 : {
     266               0 :     switch (target) {
     267                 :         case LOCAL_GL_NEVER:
     268                 :         case LOCAL_GL_LESS:
     269                 :         case LOCAL_GL_LEQUAL:
     270                 :         case LOCAL_GL_GREATER:
     271                 :         case LOCAL_GL_GEQUAL:
     272                 :         case LOCAL_GL_EQUAL:
     273                 :         case LOCAL_GL_NOTEQUAL:
     274                 :         case LOCAL_GL_ALWAYS:
     275               0 :             return true;
     276                 :         default:
     277               0 :             ErrorInvalidEnumInfo(info, target);
     278               0 :             return false;
     279                 :     }
     280                 : }
     281                 : 
     282               0 : bool WebGLContext::ValidateStencilOpEnum(WebGLenum action, const char *info)
     283                 : {
     284               0 :     switch (action) {
     285                 :         case LOCAL_GL_KEEP:
     286                 :         case LOCAL_GL_ZERO:
     287                 :         case LOCAL_GL_REPLACE:
     288                 :         case LOCAL_GL_INCR:
     289                 :         case LOCAL_GL_INCR_WRAP:
     290                 :         case LOCAL_GL_DECR:
     291                 :         case LOCAL_GL_DECR_WRAP:
     292                 :         case LOCAL_GL_INVERT:
     293               0 :             return true;
     294                 :         default:
     295               0 :             ErrorInvalidEnumInfo(info, action);
     296               0 :             return false;
     297                 :     }
     298                 : }
     299                 : 
     300               0 : bool WebGLContext::ValidateFaceEnum(WebGLenum face, const char *info)
     301                 : {
     302               0 :     switch (face) {
     303                 :         case LOCAL_GL_FRONT:
     304                 :         case LOCAL_GL_BACK:
     305                 :         case LOCAL_GL_FRONT_AND_BACK:
     306               0 :             return true;
     307                 :         default:
     308               0 :             ErrorInvalidEnumInfo(info, face);
     309               0 :             return false;
     310                 :     }
     311                 : }
     312                 : 
     313               0 : bool WebGLContext::ValidateBufferUsageEnum(WebGLenum target, const char *info)
     314                 : {
     315               0 :     switch (target) {
     316                 :         case LOCAL_GL_STREAM_DRAW:
     317                 :         case LOCAL_GL_STATIC_DRAW:
     318                 :         case LOCAL_GL_DYNAMIC_DRAW:
     319               0 :             return true;
     320                 :         default:
     321               0 :             ErrorInvalidEnumInfo(info, target);
     322               0 :             return false;
     323                 :     }
     324                 : }
     325                 : 
     326               0 : bool WebGLContext::ValidateDrawModeEnum(WebGLenum mode, const char *info)
     327                 : {
     328               0 :     switch (mode) {
     329                 :         case LOCAL_GL_TRIANGLES:
     330                 :         case LOCAL_GL_TRIANGLE_STRIP:
     331                 :         case LOCAL_GL_TRIANGLE_FAN:
     332                 :         case LOCAL_GL_POINTS:
     333                 :         case LOCAL_GL_LINE_STRIP:
     334                 :         case LOCAL_GL_LINE_LOOP:
     335                 :         case LOCAL_GL_LINES:
     336               0 :             return true;
     337                 :         default:
     338               0 :             ErrorInvalidEnumInfo(info, mode);
     339               0 :             return false;
     340                 :     }
     341                 : }
     342                 : 
     343               0 : bool WebGLContext::ValidateGLSLVariableName(const nsAString& name, const char *info)
     344                 : {
     345               0 :     const PRUint32 maxSize = 256;
     346               0 :     if (name.Length() > maxSize) {
     347                 :         ErrorInvalidValue("%s: identifier is %d characters long, exceeds the maximum allowed length of %d characters",
     348               0 :                           info, name.Length(), maxSize);
     349               0 :         return false;
     350                 :     }
     351                 : 
     352               0 :     if (!ValidateGLSLString(name, info)) {
     353               0 :         return false;
     354                 :     }
     355                 : 
     356               0 :     return true;
     357                 : }
     358                 : 
     359               0 : bool WebGLContext::ValidateGLSLString(const nsAString& string, const char *info)
     360                 : {
     361               0 :     for (PRUint32 i = 0; i < string.Length(); ++i) {
     362               0 :         if (!ValidateGLSLCharacter(string.CharAt(i))) {
     363               0 :              ErrorInvalidValue("%s: string contains the illegal character '%d'", info, string.CharAt(i));
     364               0 :              return false;
     365                 :         }
     366                 :     }
     367                 : 
     368               0 :     return true;
     369                 : }
     370                 : 
     371               0 : PRUint32 WebGLContext::GetTexelSize(WebGLenum format, WebGLenum type)
     372                 : {
     373               0 :     if (type == LOCAL_GL_UNSIGNED_BYTE || type == LOCAL_GL_FLOAT) {
     374               0 :         int multiplier = type == LOCAL_GL_FLOAT ? 4 : 1;
     375               0 :         switch (format) {
     376                 :             case LOCAL_GL_ALPHA:
     377                 :             case LOCAL_GL_LUMINANCE:
     378               0 :                 return 1 * multiplier;
     379                 :             case LOCAL_GL_LUMINANCE_ALPHA:
     380               0 :                 return 2 * multiplier;
     381                 :             case LOCAL_GL_RGB:
     382               0 :                 return 3 * multiplier;
     383                 :             case LOCAL_GL_RGBA:
     384               0 :                 return 4 * multiplier;
     385                 :             default:
     386                 :                 break;
     387               0 :         }
     388               0 :     } else if (type == LOCAL_GL_UNSIGNED_SHORT_4_4_4_4 ||
     389                 :                type == LOCAL_GL_UNSIGNED_SHORT_5_5_5_1 ||
     390                 :                type == LOCAL_GL_UNSIGNED_SHORT_5_6_5)
     391                 :     {
     392               0 :         return 2;
     393                 :     }
     394                 : 
     395               0 :     NS_ABORT();
     396               0 :     return 0;
     397                 : }
     398                 : 
     399               0 : bool WebGLContext::ValidateTexFormatAndType(WebGLenum format, WebGLenum type, int jsArrayType,
     400                 :                                               PRUint32 *texelSize, const char *info)
     401                 : {
     402               0 :     if (type == LOCAL_GL_UNSIGNED_BYTE ||
     403               0 :         (IsExtensionEnabled(WebGL_OES_texture_float) && type == LOCAL_GL_FLOAT))
     404                 :     {
     405               0 :         if (jsArrayType != -1) {
     406               0 :             if ((type == LOCAL_GL_UNSIGNED_BYTE && jsArrayType != js::TypedArray::TYPE_UINT8) ||
     407                 :                 (type == LOCAL_GL_FLOAT && jsArrayType != js::TypedArray::TYPE_FLOAT32))
     408                 :             {
     409               0 :                 ErrorInvalidOperation("%s: invalid typed array type for given format", info);
     410               0 :                 return false;
     411                 :             }
     412                 :         }
     413                 : 
     414               0 :         int texMultiplier = type == LOCAL_GL_FLOAT ? 4 : 1;
     415               0 :         switch (format) {
     416                 :             case LOCAL_GL_ALPHA:
     417                 :             case LOCAL_GL_LUMINANCE:
     418               0 :                 *texelSize = 1 * texMultiplier;
     419               0 :                 return true;
     420                 :             case LOCAL_GL_LUMINANCE_ALPHA:
     421               0 :                 *texelSize = 2 * texMultiplier;
     422               0 :                 return true;
     423                 :             case LOCAL_GL_RGB:
     424               0 :                 *texelSize = 3 * texMultiplier;
     425               0 :                 return true;
     426                 :             case LOCAL_GL_RGBA:
     427               0 :                 *texelSize = 4 * texMultiplier;
     428               0 :                 return true;
     429                 :             default:
     430                 :                 break;
     431                 :         }
     432                 : 
     433               0 :         ErrorInvalidEnum("%s: invalid format 0x%x", info, format);
     434               0 :         return false;
     435                 :     }
     436                 : 
     437               0 :     switch (type) {
     438                 :         case LOCAL_GL_UNSIGNED_SHORT_4_4_4_4:
     439                 :         case LOCAL_GL_UNSIGNED_SHORT_5_5_5_1:
     440               0 :             if (jsArrayType != -1 && jsArrayType != js::TypedArray::TYPE_UINT16) {
     441               0 :                 ErrorInvalidOperation("%s: invalid typed array type for given format", info);
     442               0 :                 return false;
     443                 :             }
     444                 : 
     445               0 :             if (format == LOCAL_GL_RGBA) {
     446               0 :                 *texelSize = 2;
     447               0 :                 return true;
     448                 :             }
     449               0 :             ErrorInvalidOperation("%s: mutually incompatible format and type", info);
     450               0 :             return false;
     451                 : 
     452                 :         case LOCAL_GL_UNSIGNED_SHORT_5_6_5:
     453               0 :             if (jsArrayType != -1 && jsArrayType != js::TypedArray::TYPE_UINT16) {
     454               0 :                 ErrorInvalidOperation("%s: invalid typed array type for given format", info);
     455               0 :                 return false;
     456                 :             }
     457                 : 
     458               0 :             if (format == LOCAL_GL_RGB) {
     459               0 :                 *texelSize = 2;
     460               0 :                 return true;
     461                 :             }
     462               0 :             ErrorInvalidOperation("%s: mutually incompatible format and type", info);
     463               0 :             return false;
     464                 : 
     465                 :         default:
     466                 :             break;
     467                 :         }
     468                 : 
     469               0 :     ErrorInvalidEnum("%s: invalid type 0x%x", info, type);
     470               0 :     return false;
     471                 : }
     472                 : 
     473               0 : bool WebGLContext::ValidateAttribIndex(WebGLuint index, const char *info)
     474                 : {
     475               0 :     if (index >= mAttribBuffers.Length()) {
     476               0 :         if (index == WebGLuint(-1)) {
     477                 :              ErrorInvalidValue("%s: index -1 is invalid. That probably comes from a getAttribLocation() call, "
     478                 :                                "where this return value -1 means that the passed name didn't correspond to an active attribute in "
     479               0 :                                "the specified program.", info);
     480                 :         } else {
     481               0 :              ErrorInvalidValue("%s: index %d is out of range", info, index);
     482                 :         }
     483               0 :         return false;
     484                 :     } else {
     485               0 :         return true;
     486                 :     }
     487                 : }
     488                 : 
     489               0 : bool WebGLContext::ValidateStencilParamsForDrawCall()
     490                 : {
     491               0 :   const char *msg = "%s set different front and back stencil %s. Drawing in this configuration is not allowed.";
     492               0 :   if (mStencilRefFront != mStencilRefBack) {
     493               0 :       ErrorInvalidOperation(msg, "stencilFuncSeparate", "reference values");
     494               0 :       return false;
     495                 :   }
     496               0 :   if (mStencilValueMaskFront != mStencilValueMaskBack) {
     497               0 :       ErrorInvalidOperation(msg, "stencilFuncSeparate", "value masks");
     498               0 :       return false;
     499                 :   }
     500               0 :   if (mStencilWriteMaskFront != mStencilWriteMaskBack) {
     501               0 :       ErrorInvalidOperation(msg, "stencilMaskSeparate", "write masks");
     502               0 :       return false;
     503                 :   }
     504               0 :   return true;
     505                 : }
     506                 : 
     507                 : bool
     508               0 : WebGLContext::InitAndValidateGL()
     509                 : {
     510               0 :     if (!gl) return false;
     511                 : 
     512               0 :     GLenum error = gl->fGetError();
     513               0 :     if (error != LOCAL_GL_NO_ERROR) {
     514               0 :         LogMessage("GL error 0x%x occurred during OpenGL context initialization, before WebGL initialization!", error);
     515               0 :         return false;
     516                 :     }
     517                 : 
     518               0 :     mMinCapability = Preferences::GetBool("webgl.min_capability_mode", false);
     519               0 :     mDisableExtensions = Preferences::GetBool("webgl.disable-extensions", false);
     520                 : 
     521               0 :     mActiveTexture = 0;
     522               0 :     mWebGLError = LOCAL_GL_NO_ERROR;
     523                 : 
     524               0 :     mAttribBuffers.Clear();
     525                 : 
     526               0 :     mBound2DTextures.Clear();
     527               0 :     mBoundCubeMapTextures.Clear();
     528                 : 
     529               0 :     mBoundArrayBuffer = nsnull;
     530               0 :     mBoundElementArrayBuffer = nsnull;
     531               0 :     mCurrentProgram = nsnull;
     532                 : 
     533               0 :     mBoundFramebuffer = nsnull;
     534               0 :     mBoundRenderbuffer = nsnull;
     535                 : 
     536               0 :     MakeContextCurrent();
     537                 : 
     538                 :     // on desktop OpenGL, we always keep vertex attrib 0 array enabled
     539               0 :     if (!gl->IsGLES2()) {
     540               0 :         gl->fEnableVertexAttribArray(0);
     541                 :     }
     542                 : 
     543               0 :     if (MinCapabilityMode()) {
     544               0 :         mGLMaxVertexAttribs = MINVALUE_GL_MAX_VERTEX_ATTRIBS;
     545                 :     } else {
     546               0 :         gl->fGetIntegerv(LOCAL_GL_MAX_VERTEX_ATTRIBS, &mGLMaxVertexAttribs);
     547                 :     }
     548               0 :     if (mGLMaxVertexAttribs < 8) {
     549               0 :         LogMessage("GL_MAX_VERTEX_ATTRIBS: %d is < 8!", mGLMaxVertexAttribs);
     550               0 :         return false;
     551                 :     }
     552                 : 
     553               0 :     mAttribBuffers.SetLength(mGLMaxVertexAttribs);
     554                 : 
     555                 :     // Note: GL_MAX_TEXTURE_UNITS is fixed at 4 for most desktop hardware,
     556                 :     // even though the hardware supports much more.  The
     557                 :     // GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS value is the accurate value.
     558               0 :     if (MinCapabilityMode()) {
     559               0 :         mGLMaxTextureUnits = MINVALUE_GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS;
     560                 :     } else {
     561               0 :         gl->fGetIntegerv(LOCAL_GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS, &mGLMaxTextureUnits);
     562                 :     }
     563               0 :     if (mGLMaxTextureUnits < 8) {
     564               0 :         LogMessage("GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS: %d is < 8!", mGLMaxTextureUnits);
     565               0 :         return false;
     566                 :     }
     567                 : 
     568               0 :     mBound2DTextures.SetLength(mGLMaxTextureUnits);
     569               0 :     mBoundCubeMapTextures.SetLength(mGLMaxTextureUnits);
     570                 : 
     571               0 :     if (MinCapabilityMode()) {
     572               0 :         mGLMaxTextureSize = MINVALUE_GL_MAX_TEXTURE_SIZE;
     573               0 :         mGLMaxCubeMapTextureSize = MINVALUE_GL_MAX_CUBE_MAP_TEXTURE_SIZE;
     574               0 :         mGLMaxTextureImageUnits = MINVALUE_GL_MAX_TEXTURE_IMAGE_UNITS;
     575               0 :         mGLMaxVertexTextureImageUnits = MINVALUE_GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS;
     576                 :     } else {
     577               0 :         gl->fGetIntegerv(LOCAL_GL_MAX_TEXTURE_SIZE, &mGLMaxTextureSize);
     578               0 :         gl->fGetIntegerv(LOCAL_GL_MAX_CUBE_MAP_TEXTURE_SIZE, &mGLMaxCubeMapTextureSize);
     579               0 :         gl->fGetIntegerv(LOCAL_GL_MAX_TEXTURE_IMAGE_UNITS, &mGLMaxTextureImageUnits);
     580               0 :         gl->fGetIntegerv(LOCAL_GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS, &mGLMaxVertexTextureImageUnits);
     581                 :     }
     582                 :     
     583                 : #ifdef XP_MACOSX
     584                 :     if (gl->Vendor() == gl::GLContext::VendorIntel) {
     585                 :         // bug 684882, corruption in large cube maps on Intel Mac driver.
     586                 :         // Is reported to only affect Mac OS < 10.7.2 but don't want to rely on that yet.
     587                 :         mGLMaxCubeMapTextureSize = NS_MIN(mGLMaxCubeMapTextureSize, 512);
     588                 :     }
     589                 : #endif
     590                 : 
     591               0 :     if (MinCapabilityMode()) {
     592               0 :         mGLMaxFragmentUniformVectors = MINVALUE_GL_MAX_FRAGMENT_UNIFORM_VECTORS;
     593               0 :         mGLMaxVertexUniformVectors = MINVALUE_GL_MAX_VERTEX_UNIFORM_VECTORS;
     594               0 :         mGLMaxVaryingVectors = MINVALUE_GL_MAX_VARYING_VECTORS;
     595                 :     } else {
     596               0 :         if (gl->HasES2Compatibility()) {
     597               0 :             gl->fGetIntegerv(LOCAL_GL_MAX_FRAGMENT_UNIFORM_VECTORS, &mGLMaxFragmentUniformVectors);
     598               0 :             gl->fGetIntegerv(LOCAL_GL_MAX_VERTEX_UNIFORM_VECTORS, &mGLMaxVertexUniformVectors);
     599               0 :             gl->fGetIntegerv(LOCAL_GL_MAX_VARYING_VECTORS, &mGLMaxVaryingVectors);
     600                 :         } else {
     601               0 :             gl->fGetIntegerv(LOCAL_GL_MAX_FRAGMENT_UNIFORM_COMPONENTS, &mGLMaxFragmentUniformVectors);
     602               0 :             mGLMaxFragmentUniformVectors /= 4;
     603               0 :             gl->fGetIntegerv(LOCAL_GL_MAX_VERTEX_UNIFORM_COMPONENTS, &mGLMaxVertexUniformVectors);
     604               0 :             mGLMaxVertexUniformVectors /= 4;
     605                 : 
     606                 :             // we are now going to try to read GL_MAX_VERTEX_OUTPUT_COMPONENTS and GL_MAX_FRAGMENT_INPUT_COMPONENTS,
     607                 :             // however these constants only entered the OpenGL standard at OpenGL 3.2. So we will try reading,
     608                 :             // and check OpenGL error for INVALID_ENUM.
     609                 : 
     610                 :             // before we start, we check that no error already occurred, to prevent hiding it in our subsequent error handling
     611               0 :             error = gl->GetAndClearError();
     612               0 :             if (error != LOCAL_GL_NO_ERROR) {
     613               0 :                 LogMessage("GL error 0x%x occurred during WebGL context initialization!", error);
     614               0 :                 return false;
     615                 :             }
     616                 : 
     617                 :             // On the public_webgl list, "problematic GetParameter pnames" thread, the following formula was given:
     618                 :             //   mGLMaxVaryingVectors = min (GL_MAX_VERTEX_OUTPUT_COMPONENTS, GL_MAX_FRAGMENT_INPUT_COMPONENTS) / 4
     619                 :             GLint maxVertexOutputComponents,
     620                 :                   minFragmentInputComponents;
     621               0 :             gl->fGetIntegerv(LOCAL_GL_MAX_VERTEX_OUTPUT_COMPONENTS, &maxVertexOutputComponents);
     622               0 :             gl->fGetIntegerv(LOCAL_GL_MAX_FRAGMENT_INPUT_COMPONENTS, &minFragmentInputComponents);
     623                 : 
     624               0 :             error = gl->GetAndClearError();
     625               0 :             switch (error) {
     626                 :                 case LOCAL_GL_NO_ERROR:
     627               0 :                     mGLMaxVaryingVectors = NS_MIN(maxVertexOutputComponents, minFragmentInputComponents) / 4;
     628               0 :                     break;
     629                 :                 case LOCAL_GL_INVALID_ENUM:
     630               0 :                     mGLMaxVaryingVectors = 16; // = 64/4, 64 is the min value for maxVertexOutputComponents in OpenGL 3.2 spec
     631               0 :                     break;
     632                 :                 default:
     633               0 :                     LogMessage("GL error 0x%x occurred during WebGL context initialization!", error);
     634               0 :                     return false;
     635                 :             }   
     636                 :         }
     637                 :     }
     638                 : 
     639                 :     // Always 1 for GLES2
     640               0 :     mMaxFramebufferColorAttachments = 1;
     641                 : 
     642               0 :     if (!gl->IsGLES2()) {
     643                 :         // gl_PointSize is always available in ES2 GLSL, but has to be
     644                 :         // specifically enabled on desktop GLSL.
     645               0 :         gl->fEnable(LOCAL_GL_VERTEX_PROGRAM_POINT_SIZE);
     646                 : 
     647                 :         // we don't do the following glEnable(GL_POINT_SPRITE) on ATI cards on Windows, because bug 602183 shows that it causes
     648                 :         // crashes in the ATI/Windows driver; and point sprites on ATI seem like a lost cause anyway, see
     649                 :         //    http://www.gamedev.net/community/forums/topic.asp?topic_id=525643
     650                 :         // Also, if the ATI/Windows driver implements a recent GL spec version, this shouldn't be needed anyway.
     651                 : #ifdef XP_WIN
     652                 :         if (gl->Vendor() != gl::GLContext::VendorATI)
     653                 : #else
     654                 :         if (true)
     655                 : #endif
     656                 :         {
     657                 :             // gl_PointCoord is always available in ES2 GLSL and in newer desktop GLSL versions, but apparently
     658                 :             // not in OpenGL 2 and apparently not (due to a driver bug) on certain NVIDIA setups. See:
     659                 :             //   http://www.opengl.org/discussion_boards/ubbthreads.php?ubb=showflat&Number=261472
     660               0 :             gl->fEnable(LOCAL_GL_POINT_SPRITE);
     661                 :         }
     662                 :     }
     663                 : 
     664                 :     // Check the shader validator pref
     665               0 :     NS_ENSURE_TRUE(Preferences::GetRootBranch(), false);
     666                 : 
     667                 :     mShaderValidation =
     668               0 :         Preferences::GetBool("webgl.shader_validator", mShaderValidation);
     669                 : 
     670                 : #if defined(USE_ANGLE)
     671                 :     // initialize shader translator
     672               0 :     if (mShaderValidation) {
     673               0 :         if (!ShInitialize()) {
     674               0 :             LogMessage("GLSL translator initialization failed!");
     675               0 :             return false;
     676                 :         }
     677                 :     }
     678                 : #endif
     679                 : 
     680                 :     // notice that the point of calling GetAndClearError here is not only to check for error,
     681                 :     // it is also to reset the error flags so that a subsequent WebGL getError call will give the correct result.
     682               0 :     error = gl->GetAndClearError();
     683               0 :     if (error != LOCAL_GL_NO_ERROR) {
     684               0 :         LogMessage("GL error 0x%x occurred during WebGL context initialization!", error);
     685               0 :         return false;
     686                 :     }
     687                 : 
     688               0 :     return true;
     689                 : }

Generated by: LCOV version 1.7