mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
dc257cd65c
Backed out changeset 7f68752ffe1e (bug 965022) Backed out changeset 24251d4da019 (bug 965022) Backed out changeset a34ae046c947 (bug 965022) Backed out changeset f747fd154739 (bug 965022) Backed out changeset f076faf3c282 (bug 965022)
244 lines
7.8 KiB
C++
244 lines
7.8 KiB
C++
/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
|
|
/* 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/. */
|
|
|
|
#include "WebGLContext.h"
|
|
#include "WebGLShader.h"
|
|
#include "WebGLProgram.h"
|
|
#include "mozilla/dom/WebGLRenderingContextBinding.h"
|
|
#include "GLContext.h"
|
|
|
|
#include "MurmurHash3.h"
|
|
|
|
using namespace mozilla;
|
|
|
|
/** Takes an ASCII string like "foo[i]", turns it into "foo" and returns "[i]" in bracketPart
|
|
*
|
|
* \param string input/output: the string to split, becomes the string without the bracket part
|
|
* \param bracketPart output: gets the bracket part.
|
|
*
|
|
* Notice that if there are multiple brackets like "foo[i].bar[j]", only the last bracket is split.
|
|
*/
|
|
static bool SplitLastSquareBracket(nsACString& string, nsCString& bracketPart)
|
|
{
|
|
MOZ_ASSERT(bracketPart.IsEmpty(), "SplitLastSquareBracket must be called with empty bracketPart string");
|
|
|
|
if (string.IsEmpty())
|
|
return false;
|
|
|
|
char *string_start = string.BeginWriting();
|
|
char *s = string_start + string.Length() - 1;
|
|
|
|
if (*s != ']')
|
|
return false;
|
|
|
|
while (*s != '[' && s != string_start)
|
|
s--;
|
|
|
|
if (*s != '[')
|
|
return false;
|
|
|
|
bracketPart.Assign(s);
|
|
*s = 0;
|
|
string.EndWriting();
|
|
string.SetLength(s - string_start);
|
|
return true;
|
|
}
|
|
|
|
JSObject*
|
|
WebGLProgram::WrapObject(JSContext *cx) {
|
|
return dom::WebGLProgramBinding::Wrap(cx, this);
|
|
}
|
|
|
|
WebGLProgram::WebGLProgram(WebGLContext *context)
|
|
: WebGLContextBoundObject(context)
|
|
, mLinkStatus(false)
|
|
, mGeneration(0)
|
|
, mIdentifierMap(new CStringMap)
|
|
, mIdentifierReverseMap(new CStringMap)
|
|
, mUniformInfoMap(new CStringToUniformInfoMap)
|
|
, mAttribMaxNameLength(0)
|
|
{
|
|
SetIsDOMBinding();
|
|
mContext->MakeContextCurrent();
|
|
mGLName = mContext->gl->fCreateProgram();
|
|
mContext->mPrograms.insertBack(this);
|
|
}
|
|
|
|
void
|
|
WebGLProgram::Delete() {
|
|
DetachShaders();
|
|
mContext->MakeContextCurrent();
|
|
mContext->gl->fDeleteProgram(mGLName);
|
|
LinkedListElement<WebGLProgram>::removeFrom(mContext->mPrograms);
|
|
}
|
|
|
|
bool
|
|
WebGLProgram::AttachShader(WebGLShader *shader) {
|
|
if (ContainsShader(shader))
|
|
return false;
|
|
mAttachedShaders.AppendElement(shader);
|
|
|
|
mContext->MakeContextCurrent();
|
|
mContext->gl->fAttachShader(GLName(), shader->GLName());
|
|
|
|
return true;
|
|
}
|
|
|
|
bool
|
|
WebGLProgram::DetachShader(WebGLShader *shader) {
|
|
if (!mAttachedShaders.RemoveElement(shader))
|
|
return false;
|
|
|
|
mContext->MakeContextCurrent();
|
|
mContext->gl->fDetachShader(GLName(), shader->GLName());
|
|
|
|
return true;
|
|
}
|
|
|
|
bool
|
|
WebGLProgram::HasAttachedShaderOfType(GLenum shaderType) {
|
|
for (uint32_t i = 0; i < mAttachedShaders.Length(); ++i) {
|
|
if (mAttachedShaders[i] && mAttachedShaders[i]->ShaderType() == shaderType) {
|
|
return true;
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
bool
|
|
WebGLProgram::HasBadShaderAttached() {
|
|
for (uint32_t i = 0; i < mAttachedShaders.Length(); ++i) {
|
|
if (mAttachedShaders[i] && !mAttachedShaders[i]->CompileStatus()) {
|
|
return true;
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
size_t
|
|
WebGLProgram::UpperBoundNumSamplerUniforms() {
|
|
size_t numSamplerUniforms = 0;
|
|
for (size_t i = 0; i < mAttachedShaders.Length(); ++i) {
|
|
const WebGLShader *shader = mAttachedShaders[i];
|
|
if (!shader)
|
|
continue;
|
|
for (size_t j = 0; j < shader->mUniformInfos.Length(); ++j) {
|
|
WebGLUniformInfo u = shader->mUniformInfos[j];
|
|
if (u.type == SH_SAMPLER_2D ||
|
|
u.type == SH_SAMPLER_CUBE)
|
|
{
|
|
numSamplerUniforms += u.arraySize;
|
|
}
|
|
}
|
|
}
|
|
return numSamplerUniforms;
|
|
}
|
|
|
|
void
|
|
WebGLProgram::MapIdentifier(const nsACString& name, nsCString *mappedName) {
|
|
MOZ_ASSERT(mIdentifierMap);
|
|
|
|
nsCString mutableName(name);
|
|
nsCString bracketPart;
|
|
bool hadBracketPart = SplitLastSquareBracket(mutableName, bracketPart);
|
|
if (hadBracketPart)
|
|
mutableName.AppendLiteral("[0]");
|
|
|
|
if (mIdentifierMap->Get(mutableName, mappedName)) {
|
|
if (hadBracketPart) {
|
|
nsCString mappedBracketPart;
|
|
bool mappedHadBracketPart = SplitLastSquareBracket(*mappedName, mappedBracketPart);
|
|
if (mappedHadBracketPart)
|
|
mappedName->Append(bracketPart);
|
|
}
|
|
return;
|
|
}
|
|
|
|
// not found? We might be in the situation we have a uniform array name and the GL's glGetActiveUniform
|
|
// returned its name without [0], as is allowed by desktop GL but not in ES. Let's then try with [0].
|
|
mutableName.AppendLiteral("[0]");
|
|
if (mIdentifierMap->Get(mutableName, mappedName))
|
|
return;
|
|
|
|
// not found? return name unchanged. This case happens e.g. on bad user input, or when
|
|
// we're not using identifier mapping, or if we didn't store an identifier in the map because
|
|
// e.g. its mapping is trivial (as happens for short identifiers)
|
|
mappedName->Assign(name);
|
|
}
|
|
|
|
void
|
|
WebGLProgram::ReverseMapIdentifier(const nsACString& name, nsCString *reverseMappedName) {
|
|
MOZ_ASSERT(mIdentifierReverseMap);
|
|
|
|
nsCString mutableName(name);
|
|
nsCString bracketPart;
|
|
bool hadBracketPart = SplitLastSquareBracket(mutableName, bracketPart);
|
|
if (hadBracketPart)
|
|
mutableName.AppendLiteral("[0]");
|
|
|
|
if (mIdentifierReverseMap->Get(mutableName, reverseMappedName)) {
|
|
if (hadBracketPart) {
|
|
nsCString reverseMappedBracketPart;
|
|
bool reverseMappedHadBracketPart = SplitLastSquareBracket(*reverseMappedName, reverseMappedBracketPart);
|
|
if (reverseMappedHadBracketPart)
|
|
reverseMappedName->Append(bracketPart);
|
|
}
|
|
return;
|
|
}
|
|
|
|
// not found? We might be in the situation we have a uniform array name and the GL's glGetActiveUniform
|
|
// returned its name without [0], as is allowed by desktop GL but not in ES. Let's then try with [0].
|
|
mutableName.AppendLiteral("[0]");
|
|
if (mIdentifierReverseMap->Get(mutableName, reverseMappedName))
|
|
return;
|
|
|
|
// not found? return name unchanged. This case happens e.g. on bad user input, or when
|
|
// we're not using identifier mapping, or if we didn't store an identifier in the map because
|
|
// e.g. its mapping is trivial (as happens for short identifiers)
|
|
reverseMappedName->Assign(name);
|
|
}
|
|
|
|
WebGLUniformInfo
|
|
WebGLProgram::GetUniformInfoForMappedIdentifier(const nsACString& name) {
|
|
MOZ_ASSERT(mUniformInfoMap);
|
|
|
|
nsCString mutableName(name);
|
|
nsCString bracketPart;
|
|
bool hadBracketPart = SplitLastSquareBracket(mutableName, bracketPart);
|
|
// if there is a bracket, we're either an array or an entry in an array.
|
|
if (hadBracketPart)
|
|
mutableName.AppendLiteral("[0]");
|
|
|
|
WebGLUniformInfo info;
|
|
mUniformInfoMap->Get(mutableName, &info);
|
|
// we don't check if that Get failed, as if it did, it left info with default values
|
|
|
|
return info;
|
|
}
|
|
|
|
/* static */ uint64_t
|
|
WebGLProgram::IdentifierHashFunction(const char *ident, size_t size)
|
|
{
|
|
uint64_t outhash[2];
|
|
// NB: we use the x86 function everywhere, even though it's suboptimal perf
|
|
// on x64. They return different results; not sure if that's a requirement.
|
|
MurmurHash3_x86_128(ident, size, 0, &outhash[0]);
|
|
return outhash[0];
|
|
}
|
|
|
|
/* static */ void
|
|
WebGLProgram::HashMapIdentifier(const nsACString& name, nsCString *hashedName)
|
|
{
|
|
uint64_t hash = IdentifierHashFunction(name.BeginReading(), name.Length());
|
|
hashedName->Truncate();
|
|
// This MUST MATCH angle/src/compiler/translator/HashNames.h HASHED_NAME_PREFIX
|
|
hashedName->AppendPrintf("webgl_%llx", hash);
|
|
}
|
|
|
|
NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE(WebGLProgram, mAttachedShaders)
|
|
|
|
NS_IMPL_CYCLE_COLLECTION_ROOT_NATIVE(WebGLProgram, AddRef)
|
|
NS_IMPL_CYCLE_COLLECTION_UNROOT_NATIVE(WebGLProgram, Release)
|