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