2009-09-02 17:47:49 -07:00
|
|
|
/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
|
2012-05-21 04:12:37 -07:00
|
|
|
/* This Source Code Form is subject to the terms of the Mozilla Public
|
|
|
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
|
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
2009-09-17 23:01:12 -07:00
|
|
|
|
2009-09-02 17:47:49 -07:00
|
|
|
#include "WebGLContext.h"
|
|
|
|
|
2011-07-06 19:00:02 -07:00
|
|
|
#include "mozilla/Preferences.h"
|
2012-05-14 12:50:20 -07:00
|
|
|
#include "mozilla/CheckedInt.h"
|
2010-07-03 15:32:19 -07:00
|
|
|
|
2012-01-14 09:43:00 -08:00
|
|
|
#include "jsfriendapi.h"
|
2011-05-20 12:53:53 -07:00
|
|
|
|
2010-08-09 23:51:56 -07:00
|
|
|
#if defined(USE_ANGLE)
|
2010-07-14 20:52:34 -07:00
|
|
|
#include "angle/ShaderLang.h"
|
|
|
|
#endif
|
|
|
|
|
2012-03-02 12:42:49 -08:00
|
|
|
#include <algorithm>
|
|
|
|
|
2012-04-21 13:48:22 -07:00
|
|
|
#include "nsIObserverService.h"
|
|
|
|
|
2009-09-02 17:47:49 -07:00
|
|
|
using namespace mozilla;
|
|
|
|
|
2010-06-10 10:45:00 -07:00
|
|
|
/*
|
2012-03-02 12:42:49 -08:00
|
|
|
* Pull data out of the program, post-linking
|
2010-06-10 10:45:00 -07:00
|
|
|
*/
|
2011-09-28 23:19:26 -07:00
|
|
|
bool
|
2012-03-02 12:42:49 -08:00
|
|
|
WebGLProgram::UpdateInfo()
|
2010-06-10 10:45:00 -07:00
|
|
|
{
|
2012-03-02 12:42:49 -08:00
|
|
|
mIdentifierMap = nsnull;
|
|
|
|
mIdentifierReverseMap = nsnull;
|
2012-04-16 12:56:12 -07:00
|
|
|
mUniformInfoMap = nsnull;
|
2012-03-02 12:42:49 -08:00
|
|
|
|
|
|
|
mAttribMaxNameLength = 0;
|
|
|
|
|
|
|
|
for (size_t i = 0; i < mAttachedShaders.Length(); i++)
|
|
|
|
mAttribMaxNameLength = NS_MAX(mAttribMaxNameLength, mAttachedShaders[i]->mAttribMaxNameLength);
|
|
|
|
|
|
|
|
GLint attribCount;
|
|
|
|
mContext->gl->fGetProgramiv(mGLName, LOCAL_GL_ACTIVE_ATTRIBUTES, &attribCount);
|
|
|
|
|
|
|
|
mAttribsInUse.resize(mContext->mGLMaxVertexAttribs);
|
|
|
|
std::fill(mAttribsInUse.begin(), mAttribsInUse.end(), false);
|
2010-06-10 10:45:00 -07:00
|
|
|
|
|
|
|
nsAutoArrayPtr<char> nameBuf(new char[mAttribMaxNameLength]);
|
|
|
|
|
2012-03-02 12:42:49 -08:00
|
|
|
for (int i = 0; i < attribCount; ++i) {
|
2010-06-10 10:45:00 -07:00
|
|
|
GLint attrnamelen;
|
|
|
|
GLint attrsize;
|
|
|
|
GLenum attrtype;
|
2012-03-02 12:42:49 -08:00
|
|
|
mContext->gl->fGetActiveAttrib(mGLName, i, mAttribMaxNameLength, &attrnamelen, &attrsize, &attrtype, nameBuf);
|
2010-06-10 10:45:00 -07:00
|
|
|
if (attrnamelen > 0) {
|
2012-03-02 12:42:49 -08:00
|
|
|
GLint loc = mContext->gl->fGetAttribLocation(mGLName, nameBuf);
|
|
|
|
NS_ABORT_IF_FALSE(loc >= 0, "major oops in managing the attributes of a WebGL program");
|
|
|
|
if (loc < mContext->mGLMaxVertexAttribs) {
|
|
|
|
mAttribsInUse[loc] = true;
|
|
|
|
} else {
|
2012-05-29 11:44:31 -07:00
|
|
|
mContext->GenerateWarning("program exceeds MAX_VERTEX_ATTRIBS");
|
2012-03-02 12:42:49 -08:00
|
|
|
return false;
|
|
|
|
}
|
2010-06-10 10:45:00 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2011-10-17 07:59:28 -07:00
|
|
|
return true;
|
2010-06-10 10:45:00 -07:00
|
|
|
}
|
|
|
|
|
2009-09-02 17:47:49 -07:00
|
|
|
/*
|
2011-01-25 19:19:46 -08:00
|
|
|
* Verify that state is consistent for drawing, and compute max number of elements (maxAllowedCount)
|
|
|
|
* that will be legal to be read from bound VBOs.
|
2009-09-02 17:47:49 -07:00
|
|
|
*/
|
|
|
|
|
2011-09-28 23:19:26 -07:00
|
|
|
bool
|
2012-05-23 09:07:01 -07:00
|
|
|
WebGLContext::ValidateBuffers(int32_t *maxAllowedCount, const char *info)
|
2009-09-02 17:47:49 -07:00
|
|
|
{
|
2010-06-10 10:45:00 -07:00
|
|
|
#ifdef DEBUG
|
2011-06-27 10:27:04 -07:00
|
|
|
GLint currentProgram = 0;
|
2009-09-02 17:47:49 -07:00
|
|
|
MakeContextCurrent();
|
2011-06-27 10:27:04 -07:00
|
|
|
gl->fGetIntegerv(LOCAL_GL_CURRENT_PROGRAM, ¤tProgram);
|
|
|
|
NS_ASSERTION(GLuint(currentProgram) == mCurrentProgram->GLName(),
|
2010-06-10 10:45:00 -07:00
|
|
|
"WebGL: current program doesn't agree with GL state");
|
2011-06-27 10:27:04 -07:00
|
|
|
if (GLuint(currentProgram) != mCurrentProgram->GLName())
|
2011-10-17 07:59:28 -07:00
|
|
|
return false;
|
2010-06-10 10:45:00 -07:00
|
|
|
#endif
|
2009-09-02 17:47:49 -07:00
|
|
|
|
2011-01-25 19:19:46 -08:00
|
|
|
*maxAllowedCount = -1;
|
|
|
|
|
2012-05-23 09:07:01 -07:00
|
|
|
uint32_t attribs = mAttribBuffers.Length();
|
|
|
|
for (uint32_t i = 0; i < attribs; ++i) {
|
2010-06-10 10:45:00 -07:00
|
|
|
const WebGLVertexAttribData& vd = mAttribBuffers[i];
|
2010-06-04 12:03:33 -07:00
|
|
|
|
2010-06-10 10:45:00 -07:00
|
|
|
// If the attrib array isn't enabled, there's nothing to check;
|
|
|
|
// it's a static value.
|
|
|
|
if (!vd.enabled)
|
|
|
|
continue;
|
2009-09-02 17:47:49 -07:00
|
|
|
|
2010-06-10 10:45:00 -07:00
|
|
|
if (vd.buf == nsnull) {
|
2011-01-25 19:19:46 -08:00
|
|
|
ErrorInvalidOperation("%s: no VBO bound to enabled vertex attrib index %d!", info, i);
|
2011-10-17 07:59:28 -07:00
|
|
|
return false;
|
2010-06-10 10:45:00 -07:00
|
|
|
}
|
2009-09-02 17:47:49 -07:00
|
|
|
|
2010-06-10 10:45:00 -07:00
|
|
|
// If the attrib is not in use, then we don't have to validate
|
|
|
|
// it, just need to make sure that the binding is non-null.
|
|
|
|
if (!mCurrentProgram->IsAttribInUse(i))
|
|
|
|
continue;
|
2009-09-02 17:47:49 -07:00
|
|
|
|
2011-01-25 19:19:46 -08:00
|
|
|
// the base offset
|
2011-01-29 19:31:20 -08:00
|
|
|
CheckedInt32 checked_byteLength
|
|
|
|
= CheckedInt32(vd.buf->ByteLength()) - vd.byteOffset;
|
|
|
|
CheckedInt32 checked_sizeOfLastElement
|
|
|
|
= CheckedInt32(vd.componentSize()) * vd.size;
|
2011-01-25 19:19:46 -08:00
|
|
|
|
2012-05-14 12:50:20 -07:00
|
|
|
if (!checked_byteLength.isValid() ||
|
|
|
|
!checked_sizeOfLastElement.isValid())
|
2011-01-25 19:19:46 -08:00
|
|
|
{
|
|
|
|
ErrorInvalidOperation("%s: integer overflow occured while checking vertex attrib %d", info, i);
|
2011-10-17 07:59:28 -07:00
|
|
|
return false;
|
2010-07-03 15:32:19 -07:00
|
|
|
}
|
2010-06-08 15:14:43 -07:00
|
|
|
|
2011-01-25 19:19:46 -08:00
|
|
|
if (checked_byteLength.value() < checked_sizeOfLastElement.value()) {
|
|
|
|
*maxAllowedCount = 0;
|
|
|
|
} else {
|
2011-01-29 19:31:20 -08:00
|
|
|
CheckedInt32 checked_maxAllowedCount
|
2011-01-25 19:19:46 -08:00
|
|
|
= ((checked_byteLength - checked_sizeOfLastElement) / vd.actualStride()) + 1;
|
|
|
|
|
2012-05-14 12:50:20 -07:00
|
|
|
if (!checked_maxAllowedCount.isValid()) {
|
2011-01-25 19:19:46 -08:00
|
|
|
ErrorInvalidOperation("%s: integer overflow occured while checking vertex attrib %d", info, i);
|
2011-10-17 07:59:28 -07:00
|
|
|
return false;
|
2011-01-25 19:19:46 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
if (*maxAllowedCount == -1 || *maxAllowedCount > checked_maxAllowedCount.value())
|
|
|
|
*maxAllowedCount = checked_maxAllowedCount.value();
|
2010-06-10 10:45:00 -07:00
|
|
|
}
|
2009-09-02 17:47:49 -07:00
|
|
|
}
|
|
|
|
|
2011-10-17 07:59:28 -07:00
|
|
|
return true;
|
2009-09-02 17:47:49 -07:00
|
|
|
}
|
2010-06-01 23:09:18 -07:00
|
|
|
|
2011-09-28 23:19:26 -07:00
|
|
|
bool WebGLContext::ValidateCapabilityEnum(WebGLenum cap, const char *info)
|
2010-06-08 11:45:23 -07:00
|
|
|
{
|
|
|
|
switch (cap) {
|
|
|
|
case LOCAL_GL_BLEND:
|
|
|
|
case LOCAL_GL_CULL_FACE:
|
|
|
|
case LOCAL_GL_DEPTH_TEST:
|
|
|
|
case LOCAL_GL_DITHER:
|
|
|
|
case LOCAL_GL_POLYGON_OFFSET_FILL:
|
|
|
|
case LOCAL_GL_SAMPLE_ALPHA_TO_COVERAGE:
|
|
|
|
case LOCAL_GL_SAMPLE_COVERAGE:
|
|
|
|
case LOCAL_GL_SCISSOR_TEST:
|
|
|
|
case LOCAL_GL_STENCIL_TEST:
|
2011-10-17 07:59:28 -07:00
|
|
|
return true;
|
2010-06-08 11:45:23 -07:00
|
|
|
default:
|
2010-07-16 07:31:48 -07:00
|
|
|
ErrorInvalidEnumInfo(info, cap);
|
2011-10-17 07:59:28 -07:00
|
|
|
return false;
|
2010-06-08 11:45:23 -07:00
|
|
|
}
|
|
|
|
}
|
2010-06-10 10:45:00 -07:00
|
|
|
|
2011-09-28 23:19:26 -07:00
|
|
|
bool WebGLContext::ValidateBlendEquationEnum(WebGLenum mode, const char *info)
|
2010-06-19 07:48:44 -07:00
|
|
|
{
|
|
|
|
switch (mode) {
|
|
|
|
case LOCAL_GL_FUNC_ADD:
|
|
|
|
case LOCAL_GL_FUNC_SUBTRACT:
|
|
|
|
case LOCAL_GL_FUNC_REVERSE_SUBTRACT:
|
2011-10-17 07:59:28 -07:00
|
|
|
return true;
|
2010-06-19 07:48:44 -07:00
|
|
|
default:
|
2010-07-16 07:31:48 -07:00
|
|
|
ErrorInvalidEnumInfo(info, mode);
|
2011-10-17 07:59:28 -07:00
|
|
|
return false;
|
2010-06-19 07:48:44 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2011-09-28 23:19:26 -07:00
|
|
|
bool WebGLContext::ValidateBlendFuncDstEnum(WebGLenum factor, const char *info)
|
2010-06-19 07:48:44 -07:00
|
|
|
{
|
|
|
|
switch (factor) {
|
|
|
|
case LOCAL_GL_ZERO:
|
|
|
|
case LOCAL_GL_ONE:
|
|
|
|
case LOCAL_GL_SRC_COLOR:
|
|
|
|
case LOCAL_GL_ONE_MINUS_SRC_COLOR:
|
|
|
|
case LOCAL_GL_DST_COLOR:
|
|
|
|
case LOCAL_GL_ONE_MINUS_DST_COLOR:
|
|
|
|
case LOCAL_GL_SRC_ALPHA:
|
|
|
|
case LOCAL_GL_ONE_MINUS_SRC_ALPHA:
|
|
|
|
case LOCAL_GL_DST_ALPHA:
|
|
|
|
case LOCAL_GL_ONE_MINUS_DST_ALPHA:
|
|
|
|
case LOCAL_GL_CONSTANT_COLOR:
|
|
|
|
case LOCAL_GL_ONE_MINUS_CONSTANT_COLOR:
|
|
|
|
case LOCAL_GL_CONSTANT_ALPHA:
|
|
|
|
case LOCAL_GL_ONE_MINUS_CONSTANT_ALPHA:
|
2011-10-17 07:59:28 -07:00
|
|
|
return true;
|
2010-06-19 07:48:44 -07:00
|
|
|
default:
|
2010-07-16 07:31:48 -07:00
|
|
|
ErrorInvalidEnumInfo(info, factor);
|
2011-10-17 07:59:28 -07:00
|
|
|
return false;
|
2010-06-19 07:48:44 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2011-09-28 23:19:26 -07:00
|
|
|
bool WebGLContext::ValidateBlendFuncSrcEnum(WebGLenum factor, const char *info)
|
2010-06-19 07:48:44 -07:00
|
|
|
{
|
2010-06-30 08:49:59 -07:00
|
|
|
if (factor == LOCAL_GL_SRC_ALPHA_SATURATE)
|
2011-10-17 07:59:28 -07:00
|
|
|
return true;
|
2010-06-19 07:48:44 -07:00
|
|
|
else
|
2010-06-30 08:49:59 -07:00
|
|
|
return ValidateBlendFuncDstEnum(factor, info);
|
2010-06-19 07:48:44 -07:00
|
|
|
}
|
|
|
|
|
2011-09-28 23:19:26 -07:00
|
|
|
bool WebGLContext::ValidateBlendFuncEnumsCompatibility(WebGLenum sfactor, WebGLenum dfactor, const char *info)
|
2010-12-06 03:34:35 -08:00
|
|
|
{
|
2011-09-28 23:19:26 -07:00
|
|
|
bool sfactorIsConstantColor = sfactor == LOCAL_GL_CONSTANT_COLOR ||
|
2010-12-06 03:34:35 -08:00
|
|
|
sfactor == LOCAL_GL_ONE_MINUS_CONSTANT_COLOR;
|
2011-09-28 23:19:26 -07:00
|
|
|
bool sfactorIsConstantAlpha = sfactor == LOCAL_GL_CONSTANT_ALPHA ||
|
2010-12-06 03:34:35 -08:00
|
|
|
sfactor == LOCAL_GL_ONE_MINUS_CONSTANT_ALPHA;
|
2011-09-28 23:19:26 -07:00
|
|
|
bool dfactorIsConstantColor = dfactor == LOCAL_GL_CONSTANT_COLOR ||
|
2010-12-06 03:34:35 -08:00
|
|
|
dfactor == LOCAL_GL_ONE_MINUS_CONSTANT_COLOR;
|
2011-09-28 23:19:26 -07:00
|
|
|
bool dfactorIsConstantAlpha = dfactor == LOCAL_GL_CONSTANT_ALPHA ||
|
2010-12-06 03:34:35 -08:00
|
|
|
dfactor == LOCAL_GL_ONE_MINUS_CONSTANT_ALPHA;
|
|
|
|
if ( (sfactorIsConstantColor && dfactorIsConstantAlpha) ||
|
|
|
|
(dfactorIsConstantColor && sfactorIsConstantAlpha) ) {
|
|
|
|
ErrorInvalidOperation("%s are mutually incompatible, see section 6.8 in the WebGL 1.0 spec", info);
|
2011-10-17 07:59:28 -07:00
|
|
|
return false;
|
2010-12-06 03:34:35 -08:00
|
|
|
} else {
|
2011-10-17 07:59:28 -07:00
|
|
|
return true;
|
2010-12-06 03:34:35 -08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2011-09-28 23:19:26 -07:00
|
|
|
bool WebGLContext::ValidateTextureTargetEnum(WebGLenum target, const char *info)
|
2010-06-30 08:48:30 -07:00
|
|
|
{
|
|
|
|
switch (target) {
|
|
|
|
case LOCAL_GL_TEXTURE_2D:
|
|
|
|
case LOCAL_GL_TEXTURE_CUBE_MAP:
|
2011-10-17 07:59:28 -07:00
|
|
|
return true;
|
2010-06-30 08:48:30 -07:00
|
|
|
default:
|
2010-07-16 07:31:48 -07:00
|
|
|
ErrorInvalidEnumInfo(info, target);
|
2011-10-17 07:59:28 -07:00
|
|
|
return false;
|
2010-06-30 08:48:30 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2011-09-28 23:19:26 -07:00
|
|
|
bool WebGLContext::ValidateComparisonEnum(WebGLenum target, const char *info)
|
2010-06-30 08:48:30 -07:00
|
|
|
{
|
|
|
|
switch (target) {
|
|
|
|
case LOCAL_GL_NEVER:
|
|
|
|
case LOCAL_GL_LESS:
|
|
|
|
case LOCAL_GL_LEQUAL:
|
|
|
|
case LOCAL_GL_GREATER:
|
|
|
|
case LOCAL_GL_GEQUAL:
|
|
|
|
case LOCAL_GL_EQUAL:
|
|
|
|
case LOCAL_GL_NOTEQUAL:
|
|
|
|
case LOCAL_GL_ALWAYS:
|
2011-10-17 07:59:28 -07:00
|
|
|
return true;
|
2010-06-30 08:48:30 -07:00
|
|
|
default:
|
2010-07-16 07:31:48 -07:00
|
|
|
ErrorInvalidEnumInfo(info, target);
|
2011-10-17 07:59:28 -07:00
|
|
|
return false;
|
2010-06-30 08:48:30 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2011-09-28 23:19:26 -07:00
|
|
|
bool WebGLContext::ValidateStencilOpEnum(WebGLenum action, const char *info)
|
2010-06-30 08:48:30 -07:00
|
|
|
{
|
|
|
|
switch (action) {
|
|
|
|
case LOCAL_GL_KEEP:
|
|
|
|
case LOCAL_GL_ZERO:
|
|
|
|
case LOCAL_GL_REPLACE:
|
|
|
|
case LOCAL_GL_INCR:
|
|
|
|
case LOCAL_GL_INCR_WRAP:
|
|
|
|
case LOCAL_GL_DECR:
|
|
|
|
case LOCAL_GL_DECR_WRAP:
|
|
|
|
case LOCAL_GL_INVERT:
|
2011-10-17 07:59:28 -07:00
|
|
|
return true;
|
2010-06-30 08:48:30 -07:00
|
|
|
default:
|
2010-07-16 07:31:48 -07:00
|
|
|
ErrorInvalidEnumInfo(info, action);
|
2011-10-17 07:59:28 -07:00
|
|
|
return false;
|
2010-06-30 08:48:30 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2011-09-28 23:19:26 -07:00
|
|
|
bool WebGLContext::ValidateFaceEnum(WebGLenum face, const char *info)
|
2010-06-30 08:48:30 -07:00
|
|
|
{
|
2010-07-16 07:31:48 -07:00
|
|
|
switch (face) {
|
2010-06-30 08:48:30 -07:00
|
|
|
case LOCAL_GL_FRONT:
|
|
|
|
case LOCAL_GL_BACK:
|
|
|
|
case LOCAL_GL_FRONT_AND_BACK:
|
2011-10-17 07:59:28 -07:00
|
|
|
return true;
|
2010-06-30 08:48:30 -07:00
|
|
|
default:
|
2010-07-16 07:31:48 -07:00
|
|
|
ErrorInvalidEnumInfo(info, face);
|
2011-10-17 07:59:28 -07:00
|
|
|
return false;
|
2010-06-30 08:48:30 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2011-09-28 23:19:26 -07:00
|
|
|
bool WebGLContext::ValidateBufferUsageEnum(WebGLenum target, const char *info)
|
2010-07-03 15:34:07 -07:00
|
|
|
{
|
|
|
|
switch (target) {
|
|
|
|
case LOCAL_GL_STREAM_DRAW:
|
|
|
|
case LOCAL_GL_STATIC_DRAW:
|
|
|
|
case LOCAL_GL_DYNAMIC_DRAW:
|
2011-10-17 07:59:28 -07:00
|
|
|
return true;
|
2010-07-03 15:34:07 -07:00
|
|
|
default:
|
2010-07-16 07:31:48 -07:00
|
|
|
ErrorInvalidEnumInfo(info, target);
|
2011-10-17 07:59:28 -07:00
|
|
|
return false;
|
2010-07-16 07:31:48 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2011-09-28 23:19:26 -07:00
|
|
|
bool WebGLContext::ValidateDrawModeEnum(WebGLenum mode, const char *info)
|
2010-07-16 07:31:48 -07:00
|
|
|
{
|
|
|
|
switch (mode) {
|
|
|
|
case LOCAL_GL_TRIANGLES:
|
|
|
|
case LOCAL_GL_TRIANGLE_STRIP:
|
|
|
|
case LOCAL_GL_TRIANGLE_FAN:
|
|
|
|
case LOCAL_GL_POINTS:
|
|
|
|
case LOCAL_GL_LINE_STRIP:
|
|
|
|
case LOCAL_GL_LINE_LOOP:
|
|
|
|
case LOCAL_GL_LINES:
|
2011-10-17 07:59:28 -07:00
|
|
|
return true;
|
2010-07-16 07:31:48 -07:00
|
|
|
default:
|
|
|
|
ErrorInvalidEnumInfo(info, mode);
|
2011-10-17 07:59:28 -07:00
|
|
|
return false;
|
2010-07-03 15:34:07 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2011-09-07 14:17:44 -07:00
|
|
|
bool WebGLContext::ValidateGLSLVariableName(const nsAString& name, const char *info)
|
2011-07-28 14:12:31 -07:00
|
|
|
{
|
2012-05-23 09:07:01 -07:00
|
|
|
const uint32_t maxSize = 256;
|
2011-07-28 14:12:31 -07:00
|
|
|
if (name.Length() > maxSize) {
|
|
|
|
ErrorInvalidValue("%s: identifier is %d characters long, exceeds the maximum allowed length of %d characters",
|
|
|
|
info, name.Length(), maxSize);
|
|
|
|
return false;
|
|
|
|
}
|
2011-09-07 14:17:44 -07:00
|
|
|
|
|
|
|
if (!ValidateGLSLString(name, info)) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool WebGLContext::ValidateGLSLString(const nsAString& string, const char *info)
|
|
|
|
{
|
2012-05-23 09:07:01 -07:00
|
|
|
for (uint32_t i = 0; i < string.Length(); ++i) {
|
2011-09-07 14:17:44 -07:00
|
|
|
if (!ValidateGLSLCharacter(string.CharAt(i))) {
|
|
|
|
ErrorInvalidValue("%s: string contains the illegal character '%d'", info, string.CharAt(i));
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2011-07-28 14:12:31 -07:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2012-05-08 10:29:31 -07:00
|
|
|
bool WebGLContext::ValidateTexImage2DTarget(WebGLenum target, WebGLsizei width, WebGLsizei height,
|
|
|
|
const char* info)
|
|
|
|
{
|
|
|
|
switch (target) {
|
|
|
|
case LOCAL_GL_TEXTURE_2D:
|
|
|
|
break;
|
|
|
|
case LOCAL_GL_TEXTURE_CUBE_MAP_POSITIVE_X:
|
|
|
|
case LOCAL_GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
|
|
|
|
case LOCAL_GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
|
|
|
|
case LOCAL_GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
|
|
|
|
case LOCAL_GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
|
|
|
|
case LOCAL_GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
|
|
|
|
if (width != height) {
|
|
|
|
ErrorInvalidValue("%s: with cube map targets, width and height must be equal", info);
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
ErrorInvalidEnum("%s: invalid target enum 0x%x", info, target);
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool WebGLContext::ValidateCompressedTextureSize(WebGLint level, WebGLenum format, WebGLsizei width,
|
|
|
|
WebGLsizei height, uint32_t byteLength, const char* info)
|
|
|
|
{
|
|
|
|
CheckedUint32 calculated_byteLength = 0;
|
|
|
|
CheckedUint32 checked_byteLength = byteLength;
|
2012-05-14 12:50:20 -07:00
|
|
|
if (!checked_byteLength.isValid()) {
|
2012-05-08 10:29:31 -07:00
|
|
|
ErrorInvalidValue("%s: data length out of bounds", info);
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
switch (format) {
|
|
|
|
case LOCAL_GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
|
|
|
|
case LOCAL_GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
|
|
|
|
{
|
|
|
|
calculated_byteLength = ((CheckedUint32(width) + 3) / 4) * ((CheckedUint32(height) + 3) / 4) * 8;
|
2012-05-14 12:50:20 -07:00
|
|
|
if (!calculated_byteLength.isValid() || !(checked_byteLength == calculated_byteLength)) {
|
2012-05-08 10:29:31 -07:00
|
|
|
ErrorInvalidValue("%s: data size does not match dimensions", info);
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case LOCAL_GL_COMPRESSED_RGBA_S3TC_DXT3_EXT:
|
|
|
|
case LOCAL_GL_COMPRESSED_RGBA_S3TC_DXT5_EXT:
|
|
|
|
{
|
|
|
|
calculated_byteLength = ((CheckedUint32(width) + 3) / 4) * ((CheckedUint32(height) + 3) / 4) * 16;
|
2012-05-14 12:50:20 -07:00
|
|
|
if (!calculated_byteLength.isValid() || !(checked_byteLength == calculated_byteLength)) {
|
2012-05-08 10:29:31 -07:00
|
|
|
ErrorInvalidValue("%s: data size does not match dimensions", info);
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
switch (format) {
|
|
|
|
case LOCAL_GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
|
|
|
|
case LOCAL_GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
|
|
|
|
case LOCAL_GL_COMPRESSED_RGBA_S3TC_DXT3_EXT:
|
|
|
|
case LOCAL_GL_COMPRESSED_RGBA_S3TC_DXT5_EXT:
|
|
|
|
{
|
|
|
|
if (level == 0 && width % 4 == 0 && height % 4 == 0) {
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
if (level > 0
|
|
|
|
&& (width == 0 || width == 1 || width == 2 || width % 4 == 0)
|
|
|
|
&& (height == 0 || height == 1 || height == 2 || height % 4 == 0))
|
|
|
|
{
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
ErrorInvalidOperation("%s: level parameter does not match width and height", info);
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool WebGLContext::ValidateLevelWidthHeightForTarget(WebGLenum target, WebGLint level, WebGLsizei width,
|
|
|
|
WebGLsizei height, const char* info)
|
|
|
|
{
|
|
|
|
WebGLsizei maxTextureSize = MaxTextureSizeForTarget(target);
|
|
|
|
|
|
|
|
if (level < 0) {
|
|
|
|
ErrorInvalidValue("%s: level must be >= 0", info);
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!(maxTextureSize >> level)) {
|
2012-05-23 15:05:48 -07:00
|
|
|
ErrorInvalidValue("%s: 2^level exceeds maximum texture size", info);
|
2012-05-08 10:29:31 -07:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (width < 0 || height < 0) {
|
2012-05-23 15:05:48 -07:00
|
|
|
ErrorInvalidValue("%s: width and height must be >= 0", info);
|
2012-05-08 10:29:31 -07:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (width > maxTextureSize || height > maxTextureSize) {
|
2012-05-23 15:05:48 -07:00
|
|
|
ErrorInvalidValue("%s: width or height exceeds maximum texture size", info);
|
2012-05-08 10:29:31 -07:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2012-05-23 09:07:01 -07:00
|
|
|
uint32_t WebGLContext::GetBitsPerTexel(WebGLenum format, WebGLenum type)
|
2011-07-07 17:01:12 -07:00
|
|
|
{
|
|
|
|
if (type == LOCAL_GL_UNSIGNED_BYTE || type == LOCAL_GL_FLOAT) {
|
2012-05-08 10:29:31 -07:00
|
|
|
int multiplier = type == LOCAL_GL_FLOAT ? 32 : 8;
|
2011-07-07 17:01:12 -07:00
|
|
|
switch (format) {
|
|
|
|
case LOCAL_GL_ALPHA:
|
|
|
|
case LOCAL_GL_LUMINANCE:
|
|
|
|
return 1 * multiplier;
|
|
|
|
case LOCAL_GL_LUMINANCE_ALPHA:
|
|
|
|
return 2 * multiplier;
|
|
|
|
case LOCAL_GL_RGB:
|
|
|
|
return 3 * multiplier;
|
|
|
|
case LOCAL_GL_RGBA:
|
|
|
|
return 4 * multiplier;
|
2012-05-08 10:29:31 -07:00
|
|
|
case LOCAL_GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
|
|
|
|
case LOCAL_GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
|
|
|
|
return 4;
|
|
|
|
case LOCAL_GL_COMPRESSED_RGBA_S3TC_DXT3_EXT:
|
|
|
|
case LOCAL_GL_COMPRESSED_RGBA_S3TC_DXT5_EXT:
|
|
|
|
return 8;
|
2011-07-07 17:01:12 -07:00
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
} else if (type == LOCAL_GL_UNSIGNED_SHORT_4_4_4_4 ||
|
|
|
|
type == LOCAL_GL_UNSIGNED_SHORT_5_5_5_1 ||
|
|
|
|
type == LOCAL_GL_UNSIGNED_SHORT_5_6_5)
|
|
|
|
{
|
2012-05-08 10:29:31 -07:00
|
|
|
return 16;
|
2011-07-07 17:01:12 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
NS_ABORT();
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2011-09-28 23:19:26 -07:00
|
|
|
bool WebGLContext::ValidateTexFormatAndType(WebGLenum format, WebGLenum type, int jsArrayType,
|
2012-05-23 09:07:01 -07:00
|
|
|
uint32_t *texelSize, const char *info)
|
2010-06-30 08:49:59 -07:00
|
|
|
{
|
2011-05-20 12:53:53 -07:00
|
|
|
if (type == LOCAL_GL_UNSIGNED_BYTE ||
|
|
|
|
(IsExtensionEnabled(WebGL_OES_texture_float) && type == LOCAL_GL_FLOAT))
|
2010-06-30 08:49:59 -07:00
|
|
|
{
|
2011-05-20 12:53:53 -07:00
|
|
|
if (jsArrayType != -1) {
|
2012-01-14 09:43:00 -08:00
|
|
|
if ((type == LOCAL_GL_UNSIGNED_BYTE && jsArrayType != js::ArrayBufferView::TYPE_UINT8) ||
|
|
|
|
(type == LOCAL_GL_FLOAT && jsArrayType != js::ArrayBufferView::TYPE_FLOAT32))
|
2011-05-20 12:53:53 -07:00
|
|
|
{
|
2012-01-14 09:43:00 -08:00
|
|
|
ErrorInvalidOperation("%s: invalid typed array type for given texture data type", info);
|
2011-10-17 07:59:28 -07:00
|
|
|
return false;
|
2011-05-20 12:53:53 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
int texMultiplier = type == LOCAL_GL_FLOAT ? 4 : 1;
|
2010-06-30 08:49:59 -07:00
|
|
|
switch (format) {
|
|
|
|
case LOCAL_GL_ALPHA:
|
|
|
|
case LOCAL_GL_LUMINANCE:
|
2011-05-20 12:53:53 -07:00
|
|
|
*texelSize = 1 * texMultiplier;
|
2011-10-17 07:59:28 -07:00
|
|
|
return true;
|
2010-06-30 08:49:59 -07:00
|
|
|
case LOCAL_GL_LUMINANCE_ALPHA:
|
2011-05-20 12:53:53 -07:00
|
|
|
*texelSize = 2 * texMultiplier;
|
2011-10-17 07:59:28 -07:00
|
|
|
return true;
|
2010-06-30 08:49:59 -07:00
|
|
|
case LOCAL_GL_RGB:
|
2011-05-20 12:53:53 -07:00
|
|
|
*texelSize = 3 * texMultiplier;
|
2011-10-17 07:59:28 -07:00
|
|
|
return true;
|
2010-06-30 08:49:59 -07:00
|
|
|
case LOCAL_GL_RGBA:
|
2011-05-20 12:53:53 -07:00
|
|
|
*texelSize = 4 * texMultiplier;
|
2011-10-17 07:59:28 -07:00
|
|
|
return true;
|
2010-06-30 08:49:59 -07:00
|
|
|
default:
|
2011-05-20 12:53:53 -07:00
|
|
|
break;
|
2010-06-30 08:49:59 -07:00
|
|
|
}
|
2011-05-20 12:53:53 -07:00
|
|
|
|
|
|
|
ErrorInvalidEnum("%s: invalid format 0x%x", info, format);
|
2011-10-17 07:59:28 -07:00
|
|
|
return false;
|
2011-05-20 12:53:53 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
switch (type) {
|
|
|
|
case LOCAL_GL_UNSIGNED_SHORT_4_4_4_4:
|
|
|
|
case LOCAL_GL_UNSIGNED_SHORT_5_5_5_1:
|
2012-01-14 09:43:00 -08:00
|
|
|
if (jsArrayType != -1 && jsArrayType != js::ArrayBufferView::TYPE_UINT16) {
|
|
|
|
ErrorInvalidOperation("%s: invalid typed array type for given texture data type", info);
|
2011-10-17 07:59:28 -07:00
|
|
|
return false;
|
2011-05-20 12:53:53 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
if (format == LOCAL_GL_RGBA) {
|
|
|
|
*texelSize = 2;
|
2011-10-17 07:59:28 -07:00
|
|
|
return true;
|
2011-05-20 12:53:53 -07:00
|
|
|
}
|
|
|
|
ErrorInvalidOperation("%s: mutually incompatible format and type", info);
|
2011-10-17 07:59:28 -07:00
|
|
|
return false;
|
2011-05-20 12:53:53 -07:00
|
|
|
|
|
|
|
case LOCAL_GL_UNSIGNED_SHORT_5_6_5:
|
2012-01-14 09:43:00 -08:00
|
|
|
if (jsArrayType != -1 && jsArrayType != js::ArrayBufferView::TYPE_UINT16) {
|
|
|
|
ErrorInvalidOperation("%s: invalid typed array type for given texture data type", info);
|
2011-10-17 07:59:28 -07:00
|
|
|
return false;
|
2011-05-20 12:53:53 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
if (format == LOCAL_GL_RGB) {
|
|
|
|
*texelSize = 2;
|
2011-10-17 07:59:28 -07:00
|
|
|
return true;
|
2011-05-20 12:53:53 -07:00
|
|
|
}
|
|
|
|
ErrorInvalidOperation("%s: mutually incompatible format and type", info);
|
2011-10-17 07:59:28 -07:00
|
|
|
return false;
|
2011-05-20 12:53:53 -07:00
|
|
|
|
|
|
|
default:
|
|
|
|
break;
|
2010-06-30 08:49:59 -07:00
|
|
|
}
|
2011-05-20 12:53:53 -07:00
|
|
|
|
|
|
|
ErrorInvalidEnum("%s: invalid type 0x%x", info, type);
|
2011-10-17 07:59:28 -07:00
|
|
|
return false;
|
2010-06-30 08:49:59 -07:00
|
|
|
}
|
|
|
|
|
2011-09-28 23:19:26 -07:00
|
|
|
bool WebGLContext::ValidateAttribIndex(WebGLuint index, const char *info)
|
2011-02-24 14:17:34 -08:00
|
|
|
{
|
2011-03-03 08:02:35 -08:00
|
|
|
if (index >= mAttribBuffers.Length()) {
|
2011-02-24 14:17:34 -08:00
|
|
|
if (index == WebGLuint(-1)) {
|
2011-03-03 08:02:35 -08:00
|
|
|
ErrorInvalidValue("%s: index -1 is invalid. That probably comes from a getAttribLocation() call, "
|
2011-02-24 14:17:34 -08:00
|
|
|
"where this return value -1 means that the passed name didn't correspond to an active attribute in "
|
|
|
|
"the specified program.", info);
|
|
|
|
} else {
|
|
|
|
ErrorInvalidValue("%s: index %d is out of range", info, index);
|
|
|
|
}
|
2011-10-17 07:59:28 -07:00
|
|
|
return false;
|
2011-02-24 14:17:34 -08:00
|
|
|
} else {
|
2011-10-17 07:59:28 -07:00
|
|
|
return true;
|
2011-02-24 14:17:34 -08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2011-09-28 23:19:26 -07:00
|
|
|
bool WebGLContext::ValidateStencilParamsForDrawCall()
|
2011-05-20 12:53:53 -07:00
|
|
|
{
|
|
|
|
const char *msg = "%s set different front and back stencil %s. Drawing in this configuration is not allowed.";
|
|
|
|
if (mStencilRefFront != mStencilRefBack) {
|
|
|
|
ErrorInvalidOperation(msg, "stencilFuncSeparate", "reference values");
|
2011-10-17 07:59:28 -07:00
|
|
|
return false;
|
2011-05-20 12:53:53 -07:00
|
|
|
}
|
|
|
|
if (mStencilValueMaskFront != mStencilValueMaskBack) {
|
|
|
|
ErrorInvalidOperation(msg, "stencilFuncSeparate", "value masks");
|
2011-10-17 07:59:28 -07:00
|
|
|
return false;
|
2011-05-20 12:53:53 -07:00
|
|
|
}
|
|
|
|
if (mStencilWriteMaskFront != mStencilWriteMaskBack) {
|
|
|
|
ErrorInvalidOperation(msg, "stencilMaskSeparate", "write masks");
|
2011-10-17 07:59:28 -07:00
|
|
|
return false;
|
2011-05-20 12:53:53 -07:00
|
|
|
}
|
2011-10-17 07:59:28 -07:00
|
|
|
return true;
|
2011-05-20 12:53:53 -07:00
|
|
|
}
|
|
|
|
|
2011-09-28 23:19:26 -07:00
|
|
|
bool
|
2010-06-14 11:44:12 -07:00
|
|
|
WebGLContext::InitAndValidateGL()
|
2010-06-10 10:45:00 -07:00
|
|
|
{
|
2011-10-17 07:59:28 -07:00
|
|
|
if (!gl) return false;
|
2010-06-14 11:44:12 -07:00
|
|
|
|
2011-02-11 15:11:30 -08:00
|
|
|
GLenum error = gl->fGetError();
|
|
|
|
if (error != LOCAL_GL_NO_ERROR) {
|
2012-05-23 09:07:29 -07:00
|
|
|
GenerateWarning("GL error 0x%x occurred during OpenGL context initialization, before WebGL initialization!", error);
|
2011-10-17 07:59:28 -07:00
|
|
|
return false;
|
2011-02-11 15:11:30 -08:00
|
|
|
}
|
|
|
|
|
2012-06-05 20:33:59 -07:00
|
|
|
#ifdef MOZ_JAVA_COMPOSITOR
|
2012-06-02 13:28:18 -07:00
|
|
|
// bug 736123, blacklist WebGL on Adreno
|
|
|
|
bool forceEnabled = Preferences::GetBool("webgl.force-enabled", false);
|
|
|
|
if (!forceEnabled) {
|
|
|
|
int renderer = gl->Renderer();
|
|
|
|
if (renderer == gl::GLContext::RendererAdreno200 ||
|
|
|
|
renderer == gl::GLContext::RendererAdreno205)
|
|
|
|
{
|
|
|
|
GenerateWarning("WebGL blocked on this Adreno driver!");
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2011-10-13 05:09:22 -07:00
|
|
|
mMinCapability = Preferences::GetBool("webgl.min_capability_mode", false);
|
|
|
|
mDisableExtensions = Preferences::GetBool("webgl.disable-extensions", false);
|
|
|
|
|
2010-06-14 11:44:12 -07:00
|
|
|
mActiveTexture = 0;
|
2011-07-07 17:01:16 -07:00
|
|
|
mWebGLError = LOCAL_GL_NO_ERROR;
|
2010-06-14 11:44:12 -07:00
|
|
|
|
|
|
|
mAttribBuffers.Clear();
|
|
|
|
|
|
|
|
mBound2DTextures.Clear();
|
|
|
|
mBoundCubeMapTextures.Clear();
|
|
|
|
|
|
|
|
mBoundArrayBuffer = nsnull;
|
|
|
|
mBoundElementArrayBuffer = nsnull;
|
|
|
|
mCurrentProgram = nsnull;
|
|
|
|
|
|
|
|
mBoundFramebuffer = nsnull;
|
|
|
|
mBoundRenderbuffer = nsnull;
|
|
|
|
|
2010-07-18 22:01:14 -07:00
|
|
|
MakeContextCurrent();
|
2010-06-10 10:45:00 -07:00
|
|
|
|
2010-09-02 07:34:08 -07:00
|
|
|
// on desktop OpenGL, we always keep vertex attrib 0 array enabled
|
|
|
|
if (!gl->IsGLES2()) {
|
|
|
|
gl->fEnableVertexAttribArray(0);
|
|
|
|
}
|
|
|
|
|
2011-10-13 05:09:22 -07:00
|
|
|
if (MinCapabilityMode()) {
|
|
|
|
mGLMaxVertexAttribs = MINVALUE_GL_MAX_VERTEX_ATTRIBS;
|
|
|
|
} else {
|
|
|
|
gl->fGetIntegerv(LOCAL_GL_MAX_VERTEX_ATTRIBS, &mGLMaxVertexAttribs);
|
|
|
|
}
|
2010-07-14 20:52:34 -07:00
|
|
|
if (mGLMaxVertexAttribs < 8) {
|
2012-05-23 09:07:29 -07:00
|
|
|
GenerateWarning("GL_MAX_VERTEX_ATTRIBS: %d is < 8!", mGLMaxVertexAttribs);
|
2011-10-13 05:09:22 -07:00
|
|
|
return false;
|
2010-06-10 10:45:00 -07:00
|
|
|
}
|
|
|
|
|
2010-07-14 20:52:34 -07:00
|
|
|
mAttribBuffers.SetLength(mGLMaxVertexAttribs);
|
2010-06-10 10:45:00 -07:00
|
|
|
|
|
|
|
// Note: GL_MAX_TEXTURE_UNITS is fixed at 4 for most desktop hardware,
|
|
|
|
// even though the hardware supports much more. The
|
2010-07-14 20:52:34 -07:00
|
|
|
// GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS value is the accurate value.
|
2011-10-13 05:09:22 -07:00
|
|
|
if (MinCapabilityMode()) {
|
|
|
|
mGLMaxTextureUnits = MINVALUE_GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS;
|
|
|
|
} else {
|
|
|
|
gl->fGetIntegerv(LOCAL_GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS, &mGLMaxTextureUnits);
|
|
|
|
}
|
2010-07-14 20:52:34 -07:00
|
|
|
if (mGLMaxTextureUnits < 8) {
|
2012-05-23 09:07:29 -07:00
|
|
|
GenerateWarning("GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS: %d is < 8!", mGLMaxTextureUnits);
|
2011-10-13 05:09:22 -07:00
|
|
|
return false;
|
2010-06-10 10:45:00 -07:00
|
|
|
}
|
|
|
|
|
2010-07-14 20:52:34 -07:00
|
|
|
mBound2DTextures.SetLength(mGLMaxTextureUnits);
|
|
|
|
mBoundCubeMapTextures.SetLength(mGLMaxTextureUnits);
|
|
|
|
|
2011-10-13 05:09:22 -07:00
|
|
|
if (MinCapabilityMode()) {
|
|
|
|
mGLMaxTextureSize = MINVALUE_GL_MAX_TEXTURE_SIZE;
|
|
|
|
mGLMaxCubeMapTextureSize = MINVALUE_GL_MAX_CUBE_MAP_TEXTURE_SIZE;
|
|
|
|
mGLMaxTextureImageUnits = MINVALUE_GL_MAX_TEXTURE_IMAGE_UNITS;
|
|
|
|
mGLMaxVertexTextureImageUnits = MINVALUE_GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS;
|
|
|
|
} else {
|
|
|
|
gl->fGetIntegerv(LOCAL_GL_MAX_TEXTURE_SIZE, &mGLMaxTextureSize);
|
|
|
|
gl->fGetIntegerv(LOCAL_GL_MAX_CUBE_MAP_TEXTURE_SIZE, &mGLMaxCubeMapTextureSize);
|
|
|
|
gl->fGetIntegerv(LOCAL_GL_MAX_TEXTURE_IMAGE_UNITS, &mGLMaxTextureImageUnits);
|
|
|
|
gl->fGetIntegerv(LOCAL_GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS, &mGLMaxVertexTextureImageUnits);
|
|
|
|
}
|
2010-07-14 20:52:34 -07:00
|
|
|
|
2011-10-13 05:09:22 -07:00
|
|
|
if (MinCapabilityMode()) {
|
|
|
|
mGLMaxFragmentUniformVectors = MINVALUE_GL_MAX_FRAGMENT_UNIFORM_VECTORS;
|
|
|
|
mGLMaxVertexUniformVectors = MINVALUE_GL_MAX_VERTEX_UNIFORM_VECTORS;
|
|
|
|
mGLMaxVaryingVectors = MINVALUE_GL_MAX_VARYING_VECTORS;
|
2010-07-28 14:24:09 -07:00
|
|
|
} else {
|
2011-10-13 05:09:22 -07:00
|
|
|
if (gl->HasES2Compatibility()) {
|
|
|
|
gl->fGetIntegerv(LOCAL_GL_MAX_FRAGMENT_UNIFORM_VECTORS, &mGLMaxFragmentUniformVectors);
|
|
|
|
gl->fGetIntegerv(LOCAL_GL_MAX_VERTEX_UNIFORM_VECTORS, &mGLMaxVertexUniformVectors);
|
|
|
|
gl->fGetIntegerv(LOCAL_GL_MAX_VARYING_VECTORS, &mGLMaxVaryingVectors);
|
|
|
|
} else {
|
|
|
|
gl->fGetIntegerv(LOCAL_GL_MAX_FRAGMENT_UNIFORM_COMPONENTS, &mGLMaxFragmentUniformVectors);
|
|
|
|
mGLMaxFragmentUniformVectors /= 4;
|
|
|
|
gl->fGetIntegerv(LOCAL_GL_MAX_VERTEX_UNIFORM_COMPONENTS, &mGLMaxVertexUniformVectors);
|
|
|
|
mGLMaxVertexUniformVectors /= 4;
|
|
|
|
|
|
|
|
// we are now going to try to read GL_MAX_VERTEX_OUTPUT_COMPONENTS and GL_MAX_FRAGMENT_INPUT_COMPONENTS,
|
|
|
|
// however these constants only entered the OpenGL standard at OpenGL 3.2. So we will try reading,
|
|
|
|
// and check OpenGL error for INVALID_ENUM.
|
|
|
|
|
|
|
|
// before we start, we check that no error already occurred, to prevent hiding it in our subsequent error handling
|
|
|
|
error = gl->GetAndClearError();
|
|
|
|
if (error != LOCAL_GL_NO_ERROR) {
|
2012-05-23 09:07:29 -07:00
|
|
|
GenerateWarning("GL error 0x%x occurred during WebGL context initialization!", error);
|
2011-10-13 05:09:22 -07:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
// On the public_webgl list, "problematic GetParameter pnames" thread, the following formula was given:
|
|
|
|
// mGLMaxVaryingVectors = min (GL_MAX_VERTEX_OUTPUT_COMPONENTS, GL_MAX_FRAGMENT_INPUT_COMPONENTS) / 4
|
|
|
|
GLint maxVertexOutputComponents,
|
|
|
|
minFragmentInputComponents;
|
|
|
|
gl->fGetIntegerv(LOCAL_GL_MAX_VERTEX_OUTPUT_COMPONENTS, &maxVertexOutputComponents);
|
|
|
|
gl->fGetIntegerv(LOCAL_GL_MAX_FRAGMENT_INPUT_COMPONENTS, &minFragmentInputComponents);
|
|
|
|
|
|
|
|
error = gl->GetAndClearError();
|
|
|
|
switch (error) {
|
|
|
|
case LOCAL_GL_NO_ERROR:
|
|
|
|
mGLMaxVaryingVectors = NS_MIN(maxVertexOutputComponents, minFragmentInputComponents) / 4;
|
|
|
|
break;
|
|
|
|
case LOCAL_GL_INVALID_ENUM:
|
|
|
|
mGLMaxVaryingVectors = 16; // = 64/4, 64 is the min value for maxVertexOutputComponents in OpenGL 3.2 spec
|
|
|
|
break;
|
|
|
|
default:
|
2012-05-23 09:07:29 -07:00
|
|
|
GenerateWarning("GL error 0x%x occurred during WebGL context initialization!", error);
|
2011-10-13 05:09:22 -07:00
|
|
|
return false;
|
|
|
|
}
|
2011-02-11 15:11:30 -08:00
|
|
|
}
|
2010-07-28 14:24:09 -07:00
|
|
|
}
|
2010-06-10 10:45:00 -07:00
|
|
|
|
2010-07-28 14:24:09 -07:00
|
|
|
// Always 1 for GLES2
|
2011-06-27 10:27:04 -07:00
|
|
|
mMaxFramebufferColorAttachments = 1;
|
2010-06-10 10:45:00 -07:00
|
|
|
|
2010-07-28 14:24:09 -07:00
|
|
|
if (!gl->IsGLES2()) {
|
|
|
|
// gl_PointSize is always available in ES2 GLSL, but has to be
|
|
|
|
// specifically enabled on desktop GLSL.
|
|
|
|
gl->fEnable(LOCAL_GL_VERTEX_PROGRAM_POINT_SIZE);
|
2010-09-27 13:20:15 -07:00
|
|
|
|
2010-10-06 13:43:21 -07:00
|
|
|
// we don't do the following glEnable(GL_POINT_SPRITE) on ATI cards on Windows, because bug 602183 shows that it causes
|
|
|
|
// crashes in the ATI/Windows driver; and point sprites on ATI seem like a lost cause anyway, see
|
|
|
|
// http://www.gamedev.net/community/forums/topic.asp?topic_id=525643
|
|
|
|
// Also, if the ATI/Windows driver implements a recent GL spec version, this shouldn't be needed anyway.
|
|
|
|
#ifdef XP_WIN
|
2012-04-10 08:49:10 -07:00
|
|
|
if (!(gl->WorkAroundDriverBugs() &&
|
|
|
|
gl->Vendor() == gl::GLContext::VendorATI))
|
2010-10-06 13:43:21 -07:00
|
|
|
#else
|
|
|
|
if (true)
|
|
|
|
#endif
|
|
|
|
{
|
|
|
|
// gl_PointCoord is always available in ES2 GLSL and in newer desktop GLSL versions, but apparently
|
|
|
|
// not in OpenGL 2 and apparently not (due to a driver bug) on certain NVIDIA setups. See:
|
|
|
|
// http://www.opengl.org/discussion_boards/ubbthreads.php?ubb=showflat&Number=261472
|
|
|
|
gl->fEnable(LOCAL_GL_POINT_SPRITE);
|
|
|
|
}
|
2010-07-28 14:24:09 -07:00
|
|
|
}
|
2010-07-14 20:52:34 -07:00
|
|
|
|
2010-08-19 19:50:38 -07:00
|
|
|
// Check the shader validator pref
|
2011-10-17 07:59:28 -07:00
|
|
|
NS_ENSURE_TRUE(Preferences::GetRootBranch(), false);
|
2010-08-09 23:51:56 -07:00
|
|
|
|
2011-07-06 19:00:02 -07:00
|
|
|
mShaderValidation =
|
|
|
|
Preferences::GetBool("webgl.shader_validator", mShaderValidation);
|
2010-08-09 23:51:56 -07:00
|
|
|
|
|
|
|
#if defined(USE_ANGLE)
|
2010-08-19 19:50:38 -07:00
|
|
|
// initialize shader translator
|
|
|
|
if (mShaderValidation) {
|
|
|
|
if (!ShInitialize()) {
|
2012-05-23 09:07:29 -07:00
|
|
|
GenerateWarning("GLSL translator initialization failed!");
|
2011-10-17 07:59:28 -07:00
|
|
|
return false;
|
2010-07-14 20:52:34 -07:00
|
|
|
}
|
2010-08-09 23:51:56 -07:00
|
|
|
}
|
2010-08-19 19:50:38 -07:00
|
|
|
#endif
|
2010-08-09 23:51:56 -07:00
|
|
|
|
2011-07-07 17:01:16 -07:00
|
|
|
// notice that the point of calling GetAndClearError here is not only to check for error,
|
|
|
|
// it is also to reset the error flags so that a subsequent WebGL getError call will give the correct result.
|
|
|
|
error = gl->GetAndClearError();
|
2010-09-16 09:45:01 -07:00
|
|
|
if (error != LOCAL_GL_NO_ERROR) {
|
2012-05-23 09:07:29 -07:00
|
|
|
GenerateWarning("GL error 0x%x occurred during WebGL context initialization!", error);
|
2011-10-17 07:59:28 -07:00
|
|
|
return false;
|
2010-09-16 09:45:01 -07:00
|
|
|
}
|
|
|
|
|
2012-04-21 13:48:22 -07:00
|
|
|
mMemoryPressureObserver
|
|
|
|
= new WebGLMemoryPressureObserver(this);
|
|
|
|
nsCOMPtr<nsIObserverService> observerService
|
|
|
|
= mozilla::services::GetObserverService();
|
|
|
|
if (observerService) {
|
|
|
|
observerService->AddObserver(mMemoryPressureObserver,
|
|
|
|
"memory-pressure",
|
|
|
|
false);
|
|
|
|
}
|
|
|
|
|
2011-10-17 07:59:28 -07:00
|
|
|
return true;
|
2010-06-10 10:45:00 -07:00
|
|
|
}
|