Thu, 15 Jan 2015 21:03:48 +0100
Integrate friendly tips from Tor colleagues to make (or not) 4.5 alpha 3;
This includes removal of overloaded (but unused) methods, and addition of
a overlooked call to DataStruct::SetData(nsISupports, uint32_t, bool.)
michael@0 | 1 | /* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ |
michael@0 | 2 | /* This Source Code Form is subject to the terms of the Mozilla Public |
michael@0 | 3 | * License, v. 2.0. If a copy of the MPL was not distributed with this |
michael@0 | 4 | * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ |
michael@0 | 5 | |
michael@0 | 6 | #include "WebGLContext.h" |
michael@0 | 7 | #include "WebGLShader.h" |
michael@0 | 8 | #include "WebGLProgram.h" |
michael@0 | 9 | #include "mozilla/dom/WebGLRenderingContextBinding.h" |
michael@0 | 10 | #include "GLContext.h" |
michael@0 | 11 | |
michael@0 | 12 | using namespace mozilla; |
michael@0 | 13 | |
michael@0 | 14 | /** Takes an ASCII string like "foo[i]", turns it into "foo" and returns "[i]" in bracketPart |
michael@0 | 15 | * |
michael@0 | 16 | * \param string input/output: the string to split, becomes the string without the bracket part |
michael@0 | 17 | * \param bracketPart output: gets the bracket part. |
michael@0 | 18 | * |
michael@0 | 19 | * Notice that if there are multiple brackets like "foo[i].bar[j]", only the last bracket is split. |
michael@0 | 20 | */ |
michael@0 | 21 | static bool SplitLastSquareBracket(nsACString& string, nsCString& bracketPart) |
michael@0 | 22 | { |
michael@0 | 23 | MOZ_ASSERT(bracketPart.IsEmpty(), "SplitLastSquareBracket must be called with empty bracketPart string"); |
michael@0 | 24 | |
michael@0 | 25 | if (string.IsEmpty()) |
michael@0 | 26 | return false; |
michael@0 | 27 | |
michael@0 | 28 | char *string_start = string.BeginWriting(); |
michael@0 | 29 | char *s = string_start + string.Length() - 1; |
michael@0 | 30 | |
michael@0 | 31 | if (*s != ']') |
michael@0 | 32 | return false; |
michael@0 | 33 | |
michael@0 | 34 | while (*s != '[' && s != string_start) |
michael@0 | 35 | s--; |
michael@0 | 36 | |
michael@0 | 37 | if (*s != '[') |
michael@0 | 38 | return false; |
michael@0 | 39 | |
michael@0 | 40 | bracketPart.Assign(s); |
michael@0 | 41 | *s = 0; |
michael@0 | 42 | string.EndWriting(); |
michael@0 | 43 | string.SetLength(s - string_start); |
michael@0 | 44 | return true; |
michael@0 | 45 | } |
michael@0 | 46 | |
michael@0 | 47 | JSObject* |
michael@0 | 48 | WebGLProgram::WrapObject(JSContext *cx) { |
michael@0 | 49 | return dom::WebGLProgramBinding::Wrap(cx, this); |
michael@0 | 50 | } |
michael@0 | 51 | |
michael@0 | 52 | WebGLProgram::WebGLProgram(WebGLContext *context) |
michael@0 | 53 | : WebGLContextBoundObject(context) |
michael@0 | 54 | , mLinkStatus(false) |
michael@0 | 55 | , mGeneration(0) |
michael@0 | 56 | , mAttribMaxNameLength(0) |
michael@0 | 57 | { |
michael@0 | 58 | SetIsDOMBinding(); |
michael@0 | 59 | mContext->MakeContextCurrent(); |
michael@0 | 60 | mGLName = mContext->gl->fCreateProgram(); |
michael@0 | 61 | mContext->mPrograms.insertBack(this); |
michael@0 | 62 | } |
michael@0 | 63 | |
michael@0 | 64 | void |
michael@0 | 65 | WebGLProgram::Delete() { |
michael@0 | 66 | DetachShaders(); |
michael@0 | 67 | mContext->MakeContextCurrent(); |
michael@0 | 68 | mContext->gl->fDeleteProgram(mGLName); |
michael@0 | 69 | LinkedListElement<WebGLProgram>::removeFrom(mContext->mPrograms); |
michael@0 | 70 | } |
michael@0 | 71 | |
michael@0 | 72 | bool |
michael@0 | 73 | WebGLProgram::AttachShader(WebGLShader *shader) { |
michael@0 | 74 | if (ContainsShader(shader)) |
michael@0 | 75 | return false; |
michael@0 | 76 | mAttachedShaders.AppendElement(shader); |
michael@0 | 77 | |
michael@0 | 78 | mContext->MakeContextCurrent(); |
michael@0 | 79 | mContext->gl->fAttachShader(GLName(), shader->GLName()); |
michael@0 | 80 | |
michael@0 | 81 | return true; |
michael@0 | 82 | } |
michael@0 | 83 | |
michael@0 | 84 | bool |
michael@0 | 85 | WebGLProgram::DetachShader(WebGLShader *shader) { |
michael@0 | 86 | if (!mAttachedShaders.RemoveElement(shader)) |
michael@0 | 87 | return false; |
michael@0 | 88 | |
michael@0 | 89 | mContext->MakeContextCurrent(); |
michael@0 | 90 | mContext->gl->fDetachShader(GLName(), shader->GLName()); |
michael@0 | 91 | |
michael@0 | 92 | return true; |
michael@0 | 93 | } |
michael@0 | 94 | |
michael@0 | 95 | bool |
michael@0 | 96 | WebGLProgram::HasAttachedShaderOfType(GLenum shaderType) { |
michael@0 | 97 | for (uint32_t i = 0; i < mAttachedShaders.Length(); ++i) { |
michael@0 | 98 | if (mAttachedShaders[i] && mAttachedShaders[i]->ShaderType() == shaderType) { |
michael@0 | 99 | return true; |
michael@0 | 100 | } |
michael@0 | 101 | } |
michael@0 | 102 | return false; |
michael@0 | 103 | } |
michael@0 | 104 | |
michael@0 | 105 | bool |
michael@0 | 106 | WebGLProgram::HasBadShaderAttached() { |
michael@0 | 107 | for (uint32_t i = 0; i < mAttachedShaders.Length(); ++i) { |
michael@0 | 108 | if (mAttachedShaders[i] && !mAttachedShaders[i]->CompileStatus()) { |
michael@0 | 109 | return true; |
michael@0 | 110 | } |
michael@0 | 111 | } |
michael@0 | 112 | return false; |
michael@0 | 113 | } |
michael@0 | 114 | |
michael@0 | 115 | size_t |
michael@0 | 116 | WebGLProgram::UpperBoundNumSamplerUniforms() { |
michael@0 | 117 | size_t numSamplerUniforms = 0; |
michael@0 | 118 | for (size_t i = 0; i < mAttachedShaders.Length(); ++i) { |
michael@0 | 119 | const WebGLShader *shader = mAttachedShaders[i]; |
michael@0 | 120 | if (!shader) |
michael@0 | 121 | continue; |
michael@0 | 122 | for (size_t j = 0; j < shader->mUniformInfos.Length(); ++j) { |
michael@0 | 123 | WebGLUniformInfo u = shader->mUniformInfos[j]; |
michael@0 | 124 | if (u.type == SH_SAMPLER_2D || |
michael@0 | 125 | u.type == SH_SAMPLER_CUBE) |
michael@0 | 126 | { |
michael@0 | 127 | numSamplerUniforms += u.arraySize; |
michael@0 | 128 | } |
michael@0 | 129 | } |
michael@0 | 130 | } |
michael@0 | 131 | return numSamplerUniforms; |
michael@0 | 132 | } |
michael@0 | 133 | |
michael@0 | 134 | void |
michael@0 | 135 | WebGLProgram::MapIdentifier(const nsACString& name, nsCString *mappedName) { |
michael@0 | 136 | if (!mIdentifierMap) { |
michael@0 | 137 | // if the identifier map doesn't exist yet, build it now |
michael@0 | 138 | mIdentifierMap = new CStringMap; |
michael@0 | 139 | for (size_t i = 0; i < mAttachedShaders.Length(); i++) { |
michael@0 | 140 | for (size_t j = 0; j < mAttachedShaders[i]->mAttributes.Length(); j++) { |
michael@0 | 141 | const WebGLMappedIdentifier& attrib = mAttachedShaders[i]->mAttributes[j]; |
michael@0 | 142 | mIdentifierMap->Put(attrib.original, attrib.mapped); |
michael@0 | 143 | } |
michael@0 | 144 | for (size_t j = 0; j < mAttachedShaders[i]->mUniforms.Length(); j++) { |
michael@0 | 145 | const WebGLMappedIdentifier& uniform = mAttachedShaders[i]->mUniforms[j]; |
michael@0 | 146 | mIdentifierMap->Put(uniform.original, uniform.mapped); |
michael@0 | 147 | } |
michael@0 | 148 | } |
michael@0 | 149 | } |
michael@0 | 150 | |
michael@0 | 151 | nsCString mutableName(name); |
michael@0 | 152 | nsCString bracketPart; |
michael@0 | 153 | bool hadBracketPart = SplitLastSquareBracket(mutableName, bracketPart); |
michael@0 | 154 | if (hadBracketPart) |
michael@0 | 155 | mutableName.AppendLiteral("[0]"); |
michael@0 | 156 | |
michael@0 | 157 | if (mIdentifierMap->Get(mutableName, mappedName)) { |
michael@0 | 158 | if (hadBracketPart) { |
michael@0 | 159 | nsCString mappedBracketPart; |
michael@0 | 160 | bool mappedHadBracketPart = SplitLastSquareBracket(*mappedName, mappedBracketPart); |
michael@0 | 161 | if (mappedHadBracketPart) |
michael@0 | 162 | mappedName->Append(bracketPart); |
michael@0 | 163 | } |
michael@0 | 164 | return; |
michael@0 | 165 | } |
michael@0 | 166 | |
michael@0 | 167 | // not found? We might be in the situation we have a uniform array name and the GL's glGetActiveUniform |
michael@0 | 168 | // returned its name without [0], as is allowed by desktop GL but not in ES. Let's then try with [0]. |
michael@0 | 169 | mutableName.AppendLiteral("[0]"); |
michael@0 | 170 | if (mIdentifierMap->Get(mutableName, mappedName)) |
michael@0 | 171 | return; |
michael@0 | 172 | |
michael@0 | 173 | // not found? return name unchanged. This case happens e.g. on bad user input, or when |
michael@0 | 174 | // we're not using identifier mapping, or if we didn't store an identifier in the map because |
michael@0 | 175 | // e.g. its mapping is trivial (as happens for short identifiers) |
michael@0 | 176 | mappedName->Assign(name); |
michael@0 | 177 | } |
michael@0 | 178 | |
michael@0 | 179 | void |
michael@0 | 180 | WebGLProgram::ReverseMapIdentifier(const nsACString& name, nsCString *reverseMappedName) { |
michael@0 | 181 | if (!mIdentifierReverseMap) { |
michael@0 | 182 | // if the identifier reverse map doesn't exist yet, build it now |
michael@0 | 183 | mIdentifierReverseMap = new CStringMap; |
michael@0 | 184 | for (size_t i = 0; i < mAttachedShaders.Length(); i++) { |
michael@0 | 185 | for (size_t j = 0; j < mAttachedShaders[i]->mAttributes.Length(); j++) { |
michael@0 | 186 | const WebGLMappedIdentifier& attrib = mAttachedShaders[i]->mAttributes[j]; |
michael@0 | 187 | mIdentifierReverseMap->Put(attrib.mapped, attrib.original); |
michael@0 | 188 | } |
michael@0 | 189 | for (size_t j = 0; j < mAttachedShaders[i]->mUniforms.Length(); j++) { |
michael@0 | 190 | const WebGLMappedIdentifier& uniform = mAttachedShaders[i]->mUniforms[j]; |
michael@0 | 191 | mIdentifierReverseMap->Put(uniform.mapped, uniform.original); |
michael@0 | 192 | } |
michael@0 | 193 | } |
michael@0 | 194 | } |
michael@0 | 195 | |
michael@0 | 196 | nsCString mutableName(name); |
michael@0 | 197 | nsCString bracketPart; |
michael@0 | 198 | bool hadBracketPart = SplitLastSquareBracket(mutableName, bracketPart); |
michael@0 | 199 | if (hadBracketPart) |
michael@0 | 200 | mutableName.AppendLiteral("[0]"); |
michael@0 | 201 | |
michael@0 | 202 | if (mIdentifierReverseMap->Get(mutableName, reverseMappedName)) { |
michael@0 | 203 | if (hadBracketPart) { |
michael@0 | 204 | nsCString reverseMappedBracketPart; |
michael@0 | 205 | bool reverseMappedHadBracketPart = SplitLastSquareBracket(*reverseMappedName, reverseMappedBracketPart); |
michael@0 | 206 | if (reverseMappedHadBracketPart) |
michael@0 | 207 | reverseMappedName->Append(bracketPart); |
michael@0 | 208 | } |
michael@0 | 209 | return; |
michael@0 | 210 | } |
michael@0 | 211 | |
michael@0 | 212 | // not found? We might be in the situation we have a uniform array name and the GL's glGetActiveUniform |
michael@0 | 213 | // returned its name without [0], as is allowed by desktop GL but not in ES. Let's then try with [0]. |
michael@0 | 214 | mutableName.AppendLiteral("[0]"); |
michael@0 | 215 | if (mIdentifierReverseMap->Get(mutableName, reverseMappedName)) |
michael@0 | 216 | return; |
michael@0 | 217 | |
michael@0 | 218 | // not found? return name unchanged. This case happens e.g. on bad user input, or when |
michael@0 | 219 | // we're not using identifier mapping, or if we didn't store an identifier in the map because |
michael@0 | 220 | // e.g. its mapping is trivial (as happens for short identifiers) |
michael@0 | 221 | reverseMappedName->Assign(name); |
michael@0 | 222 | } |
michael@0 | 223 | |
michael@0 | 224 | WebGLUniformInfo |
michael@0 | 225 | WebGLProgram::GetUniformInfoForMappedIdentifier(const nsACString& name) { |
michael@0 | 226 | nsCString mutableName(name); |
michael@0 | 227 | nsCString bracketPart; |
michael@0 | 228 | bool hadBracketPart = SplitLastSquareBracket(mutableName, bracketPart); |
michael@0 | 229 | // if there is a bracket, we're either an array or an entry in an array. |
michael@0 | 230 | if (hadBracketPart) |
michael@0 | 231 | mutableName.AppendLiteral("[0]"); |
michael@0 | 232 | |
michael@0 | 233 | WebGLUniformInfo info; |
michael@0 | 234 | mUniformInfoMap->Get(mutableName, &info); |
michael@0 | 235 | // we don't check if that Get failed, as if it did, it left info with default values |
michael@0 | 236 | |
michael@0 | 237 | return info; |
michael@0 | 238 | } |
michael@0 | 239 | |
michael@0 | 240 | NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE_1(WebGLProgram, mAttachedShaders) |
michael@0 | 241 | |
michael@0 | 242 | NS_IMPL_CYCLE_COLLECTION_ROOT_NATIVE(WebGLProgram, AddRef) |
michael@0 | 243 | NS_IMPL_CYCLE_COLLECTION_UNROOT_NATIVE(WebGLProgram, Release) |