Support CHROMIUM_path_rendering fragment operations
This brings two new APIs, BindFragmentInputLocation and
ProgramPathFragmentInputGen that together dictate how the
fragment shader varyings are used.
BUG=angleproject:1382
Change-Id: I4b52fd8a3555235a73aecd4f3dba2d500789cbb0
Reviewed-on: https://chromium-review.googlesource.com/357071
Reviewed-by: Geoff Lang <geofflang@chromium.org>
Reviewed-by: Sami Väisänen <svaisanen@nvidia.com>
Commit-Queue: Sami Väisänen <svaisanen@nvidia.com>
diff --git a/src/libANGLE/renderer/gl/ProgramGL.cpp b/src/libANGLE/renderer/gl/ProgramGL.cpp
index 69479b6..6fd1f1d 100644
--- a/src/libANGLE/renderer/gl/ProgramGL.cpp
+++ b/src/libANGLE/renderer/gl/ProgramGL.cpp
@@ -8,7 +8,9 @@
#include "libANGLE/renderer/gl/ProgramGL.h"
+#include "common/angleutils.h"
#include "common/debug.h"
+#include "common/string_utils.h"
#include "common/utilities.h"
#include "libANGLE/renderer/gl/FunctionsGL.h"
#include "libANGLE/renderer/gl/ShaderGL.h"
@@ -23,11 +25,13 @@
ProgramGL::ProgramGL(const gl::ProgramState &data,
const FunctionsGL *functions,
const WorkaroundsGL &workarounds,
- StateManagerGL *stateManager)
+ StateManagerGL *stateManager,
+ bool enablePathRendering)
: ProgramImpl(data),
mFunctions(functions),
mWorkarounds(workarounds),
mStateManager(stateManager),
+ mEnablePathRendering(enablePathRendering),
mProgramID(0)
{
ASSERT(mFunctions);
@@ -382,6 +386,26 @@
return true;
}
+void ProgramGL::setPathFragmentInputGen(const std::string &inputName,
+ GLenum genMode,
+ GLint components,
+ const GLfloat *coeffs)
+{
+ ASSERT(mEnablePathRendering);
+
+ for (const auto &input : mPathRenderingFragmentInputs)
+ {
+ if (input.name == inputName)
+ {
+ mFunctions->programPathFragmentInputGenNV(mProgramID, input.location, genMode,
+ components, coeffs);
+ ASSERT(mFunctions->getError() == GL_NO_ERROR);
+ return;
+ }
+ }
+
+}
+
void ProgramGL::preLink()
{
// Reset the program state
@@ -389,6 +413,7 @@
mUniformBlockRealLocationMap.clear();
mSamplerBindings.clear();
mUniformIndexToSamplerIndex.clear();
+ mPathRenderingFragmentInputs.clear();
}
bool ProgramGL::checkLinkStatus(gl::InfoLog &infoLog)
@@ -478,6 +503,70 @@
samplerBinding.boundTextureUnits.resize(linkedUniform.elementCount(), 0);
mSamplerBindings.push_back(samplerBinding);
}
+
+ // Discover CHROMIUM_path_rendering fragment inputs if enabled.
+ if (!mEnablePathRendering)
+ return;
+
+ GLint numFragmentInputs = 0;
+ mFunctions->getProgramInterfaceiv(mProgramID, GL_FRAGMENT_INPUT_NV, GL_ACTIVE_RESOURCES,
+ &numFragmentInputs);
+ if (numFragmentInputs <= 0)
+ return;
+
+ GLint maxNameLength = 0;
+ mFunctions->getProgramInterfaceiv(mProgramID, GL_FRAGMENT_INPUT_NV, GL_MAX_NAME_LENGTH,
+ &maxNameLength);
+ ASSERT(maxNameLength);
+
+ for (GLint i = 0; i < numFragmentInputs; ++i)
+ {
+ std::string name;
+ name.resize(maxNameLength);
+
+ GLsizei nameLen = 0;
+ mFunctions->getProgramResourceName(mProgramID, GL_FRAGMENT_INPUT_NV, i, maxNameLength,
+ &nameLen, &name[0]);
+ name.resize(nameLen);
+
+ // Ignore built-ins
+ if (angle::BeginsWith(name, "gl_"))
+ continue;
+
+ const GLenum kQueryProperties[] = {GL_LOCATION, GL_ARRAY_SIZE};
+ GLint queryResults[ArraySize(kQueryProperties)];
+ GLsizei queryLength = 0;
+
+ mFunctions->getProgramResourceiv(mProgramID, GL_FRAGMENT_INPUT_NV, i,
+ ArraySize(kQueryProperties), kQueryProperties,
+ ArraySize(queryResults), &queryLength, queryResults);
+
+ ASSERT(queryLength == ArraySize(kQueryProperties));
+
+ PathRenderingFragmentInput input;
+ input.name = name;
+ input.location = queryResults[0];
+ mPathRenderingFragmentInputs.push_back(std::move(input));
+
+ // If the input is an array it's denoted by [0] suffix on the variable
+ // name. We'll then create an entry per each array index where index > 0
+ if (angle::EndsWith(name, "[0]"))
+ {
+ // drop the suffix
+ name.resize(name.size() - 3);
+
+ const auto arraySize = queryResults[1];
+ const auto baseLocation = queryResults[0];
+
+ for (GLint i = 1; i < arraySize; ++i)
+ {
+ PathRenderingFragmentInput input;
+ input.name = name + "[" + std::to_string(i) + "]";
+ input.location = baseLocation + i;
+ mPathRenderingFragmentInputs.push_back(std::move(input));
+ }
+ }
+ }
}
} // namespace rx