mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Bug 1048724 - Sort out Transform Feedback Varyings. r=jgilbert
This commit is contained in:
parent
7a67faf4c4
commit
63ce88f24d
@ -205,18 +205,7 @@ WebGL2Context::TransformFeedbackVaryings(WebGLProgram* program,
|
||||
if (!ValidateObject("transformFeedbackVaryings: program", program))
|
||||
return;
|
||||
|
||||
GLsizei count = varyings.Length();
|
||||
GLchar** tmpVaryings = (GLchar**) moz_xmalloc(count * sizeof(GLchar*));
|
||||
|
||||
for (GLsizei n = 0; n < count; n++) {
|
||||
tmpVaryings[n] = (GLchar*) ToNewCString(varyings[n]);
|
||||
}
|
||||
|
||||
GLuint progname = program->mGLName;
|
||||
MakeContextCurrent();
|
||||
gl->fTransformFeedbackVaryings(progname, count, tmpVaryings, bufferMode);
|
||||
|
||||
NS_FREE_XPCOM_ALLOCATED_POINTER_ARRAY(count, tmpVaryings);
|
||||
program->TransformFeedbackVaryings(varyings, bufferMode);
|
||||
}
|
||||
|
||||
already_AddRefed<WebGLActiveInfo>
|
||||
@ -228,29 +217,5 @@ WebGL2Context::GetTransformFeedbackVarying(WebGLProgram* program, GLuint index)
|
||||
if (!ValidateObject("getTransformFeedbackVarying: program", program))
|
||||
return nullptr;
|
||||
|
||||
MakeContextCurrent();
|
||||
|
||||
GLint len = 0;
|
||||
GLuint progname = program->mGLName;
|
||||
gl->fGetProgramiv(progname, LOCAL_GL_TRANSFORM_FEEDBACK_VARYING_MAX_LENGTH, &len);
|
||||
if (!len)
|
||||
return nullptr;
|
||||
|
||||
UniquePtr<char[]> name(new char[len]);
|
||||
GLint tfsize = 0;
|
||||
GLuint tftype = 0;
|
||||
|
||||
gl->fGetTransformFeedbackVarying(progname, index, len, &len, &tfsize, &tftype, name.get());
|
||||
if (len == 0 || tfsize == 0 || tftype == 0)
|
||||
return nullptr;
|
||||
|
||||
MOZ_CRASH("todo");
|
||||
/*
|
||||
// Reverse lookup of name
|
||||
nsCString reverseMappedName;
|
||||
prog->ReverveMapIdentifier(nsDependentCString(name), &reverseMappedName);
|
||||
|
||||
nsRefPtr<WebGLActiveInfo> result = new WebGLActiveInfo(tfsize, tftype, nsDependentCString(name.get()));
|
||||
return result.forget();
|
||||
*/
|
||||
return program->GetTransformFeedbackVarying(index);
|
||||
}
|
||||
|
@ -93,11 +93,13 @@ WebGLContext::BindBufferBase(GLenum target, GLuint index, WebGLBuffer* buffer)
|
||||
if (index >= mGLMaxTransformFeedbackSeparateAttribs)
|
||||
return ErrorInvalidValue("bindBufferBase: index should be less than "
|
||||
"MAX_TRANSFORM_FEEDBACK_SEPARATE_ATTRIBS");
|
||||
break;
|
||||
|
||||
case LOCAL_GL_UNIFORM_BUFFER:
|
||||
if (index >= mGLMaxUniformBufferBindings)
|
||||
return ErrorInvalidValue("bindBufferBase: index should be less than "
|
||||
"MAX_UNIFORM_BUFFER_BINDINGS");
|
||||
break;
|
||||
|
||||
default:
|
||||
return ErrorInvalidEnumInfo("bindBufferBase: target", target);
|
||||
@ -131,11 +133,14 @@ WebGLContext::BindBufferRange(GLenum target, GLuint index, WebGLBuffer* buffer,
|
||||
if (index >= mGLMaxTransformFeedbackSeparateAttribs)
|
||||
return ErrorInvalidValue("bindBufferRange: index should be less than "
|
||||
"MAX_TRANSFORM_FEEDBACK_SEPARATE_ATTRIBS");
|
||||
break;
|
||||
|
||||
case LOCAL_GL_UNIFORM_BUFFER:
|
||||
if (index >= mGLMaxUniformBufferBindings)
|
||||
return ErrorInvalidValue("bindBufferRange: index should be less than "
|
||||
"MAX_UNIFORM_BUFFER_BINDINGS");
|
||||
break;
|
||||
|
||||
default:
|
||||
return ErrorInvalidEnumInfo("bindBufferRange: target", target);
|
||||
}
|
||||
@ -495,6 +500,7 @@ WebGLContext::GetBufferSlotByTargetIndexed(GLenum target, GLuint index)
|
||||
case LOCAL_GL_TRANSFORM_FEEDBACK_BUFFER:
|
||||
MOZ_ASSERT(index < mGLMaxTransformFeedbackSeparateAttribs);
|
||||
return mBoundTransformFeedbackBuffers[index];
|
||||
|
||||
case LOCAL_GL_UNIFORM_BUFFER:
|
||||
MOZ_ASSERT(index < mGLMaxUniformBufferBindings);
|
||||
return mBoundUniformBuffers[index];
|
||||
|
@ -230,7 +230,7 @@ QueryProgramInfo(WebGLProgram* prog, gl::GLContext* gl)
|
||||
gl->fGetProgramiv(prog->mGLName, LOCAL_GL_ACTIVE_UNIFORM_BLOCKS,
|
||||
(GLint*)&numActiveUniformBlocks);
|
||||
|
||||
for (GLuint i = 0; i < numActiveAttribs; i++) {
|
||||
for (GLuint i = 0; i < numActiveUniformBlocks; i++) {
|
||||
nsAutoCString mappedName;
|
||||
mappedName.SetLength(maxUniformBlockLenWithNull - 1);
|
||||
|
||||
@ -295,6 +295,7 @@ CreateProgram(gl::GLContext* gl)
|
||||
WebGLProgram::WebGLProgram(WebGLContext* webgl)
|
||||
: WebGLContextBoundObject(webgl)
|
||||
, mGLName(CreateProgram(webgl->GL()))
|
||||
, mTransformFeedbackBufferMode(LOCAL_GL_NONE)
|
||||
{
|
||||
mContext->mPrograms.insertBack(this);
|
||||
}
|
||||
@ -432,6 +433,7 @@ already_AddRefed<WebGLActiveInfo>
|
||||
WebGLProgram::GetActiveUniform(GLuint index) const
|
||||
{
|
||||
if (!mMostRecentLinkInfo) {
|
||||
// According to the spec, this can return null.
|
||||
nsRefPtr<WebGLActiveInfo> ret = WebGLActiveInfo::CreateInvalid(mContext);
|
||||
return ret.forget();
|
||||
}
|
||||
@ -532,9 +534,11 @@ WebGLProgram::GetProgramParameter(GLenum pname) const
|
||||
switch (pname) {
|
||||
case LOCAL_GL_ACTIVE_UNIFORM_BLOCKS:
|
||||
return JS::Int32Value(GetProgramiv(gl, mGLName, pname));
|
||||
}
|
||||
}
|
||||
|
||||
case LOCAL_GL_TRANSFORM_FEEDBACK_VARYINGS:
|
||||
return JS::Int32Value(mTransformFeedbackVaryings.size());
|
||||
}
|
||||
}
|
||||
|
||||
switch (pname) {
|
||||
case LOCAL_GL_ATTACHED_SHADERS:
|
||||
@ -819,6 +823,15 @@ WebGLProgram::LinkProgram()
|
||||
mVertShader->BindAttribLocation(mGLName, name, index);
|
||||
}
|
||||
|
||||
if (!mTransformFeedbackVaryings.empty()) {
|
||||
// Bind the transform feedback varyings.
|
||||
// This can't be done trivially, because we have to deal with mapped names too.
|
||||
mVertShader->ApplyTransformFeedbackVaryings(mGLName,
|
||||
mTransformFeedbackVaryings,
|
||||
mTransformFeedbackBufferMode,
|
||||
&mTempMappedVaryings);
|
||||
}
|
||||
|
||||
if (LinkAndUpdate())
|
||||
return true;
|
||||
|
||||
@ -896,6 +909,11 @@ WebGLProgram::LinkAndUpdate()
|
||||
mLinkLog.SetLength(0);
|
||||
}
|
||||
|
||||
// Post link, temporary mapped varying names for transform feedback can be discarded.
|
||||
// The memory can only be deleted after log is queried or the link status will fail.
|
||||
std::vector<std::string> empty;
|
||||
empty.swap(mTempMappedVaryings);
|
||||
|
||||
GLint ok = 0;
|
||||
gl->fGetProgramiv(mGLName, LOCAL_GL_LINK_STATUS, &ok);
|
||||
if (!ok)
|
||||
@ -934,6 +952,71 @@ WebGLProgram::FindUniformByMappedName(const nsACString& mappedName,
|
||||
return false;
|
||||
}
|
||||
|
||||
void
|
||||
WebGLProgram::TransformFeedbackVaryings(const dom::Sequence<nsString>& varyings,
|
||||
GLenum bufferMode)
|
||||
{
|
||||
if (bufferMode != LOCAL_GL_INTERLEAVED_ATTRIBS &&
|
||||
bufferMode != LOCAL_GL_SEPARATE_ATTRIBS)
|
||||
{
|
||||
mContext->ErrorInvalidEnum("transformFeedbackVaryings: `bufferMode` %s is "
|
||||
"invalid. Must be one of gl.INTERLEAVED_ATTRIBS or "
|
||||
"gl.SEPARATE_ATTRIBS.",
|
||||
mContext->EnumName(bufferMode));
|
||||
return;
|
||||
}
|
||||
|
||||
size_t varyingsCount = varyings.Length();
|
||||
if (bufferMode == LOCAL_GL_SEPARATE_ATTRIBS &&
|
||||
varyingsCount >= mContext->mGLMaxTransformFeedbackSeparateAttribs)
|
||||
{
|
||||
mContext->ErrorInvalidValue("transformFeedbackVaryings: Number of `varyings` exc"
|
||||
"eeds gl.MAX_TRANSFORM_FEEDBACK_SEPARATE_ATTRIBS.");
|
||||
return;
|
||||
}
|
||||
|
||||
std::vector<nsCString> asciiVaryings;
|
||||
for (size_t i = 0; i < varyingsCount; i++) {
|
||||
if (!ValidateGLSLVariableName(varyings[i], mContext, "transformFeedbackVaryings"))
|
||||
return;
|
||||
|
||||
NS_LossyConvertUTF16toASCII asciiName(varyings[i]);
|
||||
asciiVaryings.push_back(asciiName);
|
||||
}
|
||||
|
||||
// All validated. Translate the strings and store them until
|
||||
// program linking.
|
||||
mTransformFeedbackBufferMode = bufferMode;
|
||||
mTransformFeedbackVaryings.swap(asciiVaryings);
|
||||
}
|
||||
|
||||
already_AddRefed<WebGLActiveInfo>
|
||||
WebGLProgram::GetTransformFeedbackVarying(GLuint index)
|
||||
{
|
||||
// No docs in the WebGL 2 spec for this function. Taking the language for
|
||||
// getActiveAttrib, which states that the function returns null on any error.
|
||||
if (!IsLinked()) {
|
||||
mContext->ErrorInvalidOperation("getTransformFeedbackVarying: `program` must be "
|
||||
"linked.");
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
if (index >= mTransformFeedbackVaryings.size()) {
|
||||
mContext->ErrorInvalidValue("getTransformFeedbackVarying: `index` is greater or "
|
||||
"equal to TRANSFORM_FEEDBACK_VARYINGS.");
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
const nsCString& varyingUserName = mTransformFeedbackVaryings[index];
|
||||
|
||||
WebGLActiveInfo* info;
|
||||
LinkInfo()->FindAttrib(varyingUserName, (const WebGLActiveInfo**) &info);
|
||||
MOZ_ASSERT(info);
|
||||
|
||||
nsRefPtr<WebGLActiveInfo> ret(info);
|
||||
return ret.forget();
|
||||
}
|
||||
|
||||
bool
|
||||
WebGLProgram::FindUniformBlockByMappedName(const nsACString& mappedName,
|
||||
nsCString* const out_userName,
|
||||
|
@ -173,6 +173,10 @@ public:
|
||||
nsCString* const out_userName,
|
||||
bool* const out_isArray) const;
|
||||
|
||||
void TransformFeedbackVaryings(const dom::Sequence<nsString>& varyings,
|
||||
GLenum bufferMode);
|
||||
already_AddRefed<WebGLActiveInfo> GetTransformFeedbackVarying(GLuint index);
|
||||
|
||||
bool IsLinked() const { return mMostRecentLinkInfo; }
|
||||
|
||||
const webgl::LinkedProgramInfo* LinkInfo() const {
|
||||
@ -199,8 +203,13 @@ private:
|
||||
WebGLRefPtr<WebGLShader> mVertShader;
|
||||
WebGLRefPtr<WebGLShader> mFragShader;
|
||||
std::map<nsCString, GLuint> mBoundAttribLocs;
|
||||
std::vector<nsCString> mTransformFeedbackVaryings;
|
||||
GLenum mTransformFeedbackBufferMode;
|
||||
nsCString mLinkLog;
|
||||
RefPtr<const webgl::LinkedProgramInfo> mMostRecentLinkInfo;
|
||||
// Storage for transform feedback varyings before link.
|
||||
// (Work around for bug seen on nVidia drivers.)
|
||||
std::vector<std::string> mTempMappedVaryings;
|
||||
};
|
||||
|
||||
} // namespace mozilla
|
||||
|
@ -354,6 +354,44 @@ WebGLShader::FindUniformBlockByMappedName(const nsACString& mappedName,
|
||||
return false;
|
||||
}
|
||||
|
||||
void
|
||||
WebGLShader::ApplyTransformFeedbackVaryings(GLuint prog,
|
||||
const std::vector<nsCString>& varyings,
|
||||
GLenum bufferMode,
|
||||
std::vector<std::string>* out_mappedVaryings) const
|
||||
{
|
||||
MOZ_ASSERT(mType == LOCAL_GL_VERTEX_SHADER);
|
||||
MOZ_ASSERT(!varyings.empty());
|
||||
MOZ_ASSERT(out_mappedVaryings);
|
||||
|
||||
const size_t varyingsCount = varyings.size();
|
||||
std::vector<std::string> mappedVaryings;
|
||||
|
||||
for (size_t i = 0; i < varyingsCount; i++) {
|
||||
const nsCString& userName = varyings[i];
|
||||
std::string userNameStr(userName.BeginReading());
|
||||
|
||||
const std::string* mappedNameStr = &userNameStr;
|
||||
// TODO: Are vertex->fragment shader varyings listed under attribs?
|
||||
if (mValidator)
|
||||
mValidator->FindAttribMappedNameByUserName(userNameStr, &mappedNameStr);
|
||||
|
||||
mappedVaryings.push_back(*mappedNameStr);
|
||||
}
|
||||
|
||||
// Temporary, tight packed array of string pointers into mappedVaryings.
|
||||
std::vector<const GLchar*> strings;
|
||||
strings.resize(varyingsCount);
|
||||
for (size_t i = 0; i < varyingsCount; i++) {
|
||||
strings[i] = mappedVaryings[i].c_str();
|
||||
}
|
||||
|
||||
mContext->MakeContextCurrent();
|
||||
mContext->gl->fTransformFeedbackVaryings(prog, varyingsCount, &strings[0], bufferMode);
|
||||
|
||||
out_mappedVaryings->swap(mappedVaryings);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// Boilerplate
|
||||
|
||||
|
@ -59,6 +59,11 @@ public:
|
||||
return mTranslationSuccessful && mCompilationSuccessful;
|
||||
}
|
||||
|
||||
void ApplyTransformFeedbackVaryings(GLuint prog,
|
||||
const std::vector<nsCString>& varyings,
|
||||
GLenum bufferMode,
|
||||
std::vector<std::string>* out_mappedVaryings) const;
|
||||
|
||||
// Other funcs
|
||||
size_t SizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf) const;
|
||||
void Delete();
|
||||
|
Loading…
Reference in New Issue
Block a user