content/canvas/src/WebGLProgram.cpp

Wed, 31 Dec 2014 06:09:35 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 06:09:35 +0100
changeset 0
6474c204b198
permissions
-rw-r--r--

Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.

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)

mercurial