Add GLES3 support for EXT_blend_func_extended
This adds GLES3 API support for EXT_blend_func_extended. The patch
includes the API entrypoints, validation and also implementation on
the desktop GL backend.
Instead of having built-in fragment color variables, ESSL 3.00 has
custom output variables, which can now be bound to either primary or
secondary output color locations. The "index" set to a custom output
variable determines whether it's used a primary or secondary blending
source color.
The shader layout qualifier takes precedence over the bind call. This
is not specified in the EXT spec, but is specified in desktop OpenGL
specs.
BUG=angleproject:1085
TEST=angle_end2end_tests
Change-Id: Ia24e8e5dadcc165e5e8fbd7c653c7fab6217db88
Reviewed-on: https://chromium-review.googlesource.com/c/1249361
Commit-Queue: Olli Etuaho <oetuaho@nvidia.com>
Reviewed-by: Geoff Lang <geofflang@chromium.org>
diff --git a/src/libANGLE/validationES3.cpp b/src/libANGLE/validationES3.cpp
index d855b85..db9829e 100644
--- a/src/libANGLE/validationES3.cpp
+++ b/src/libANGLE/validationES3.cpp
@@ -4067,4 +4067,86 @@
nullptr);
}
+bool ValidateBindFragDataLocationIndexedEXT(Context *context,
+ GLuint program,
+ GLuint colorNumber,
+ GLuint index,
+ const char *name)
+{
+ if (!context->getExtensions().blendFuncExtended)
+ {
+ ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
+ return false;
+ }
+ if (context->getClientMajorVersion() < 3)
+ {
+ ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
+ return false;
+ }
+ if (index < 0 || index > 1)
+ {
+ // This error is not explicitly specified but the spec does say that "<index> may be zero or
+ // one to specify that the color be used as either the first or second color input to the
+ // blend equation, respectively"
+ ANGLE_VALIDATION_ERR(context, InvalidValue(), FragDataBindingIndexOutOfRange);
+ return false;
+ }
+ if (index == 1)
+ {
+ if (colorNumber >= context->getExtensions().maxDualSourceDrawBuffers)
+ {
+ ANGLE_VALIDATION_ERR(context, InvalidValue(),
+ ColorNumberGreaterThanMaxDualSourceDrawBuffers);
+ return false;
+ }
+ }
+ else
+ {
+ if (colorNumber >= context->getCaps().maxDrawBuffers)
+ {
+ ANGLE_VALIDATION_ERR(context, InvalidValue(), ColorNumberGreaterThanMaxDrawBuffers);
+ return false;
+ }
+ }
+ Program *programObject = GetValidProgram(context, program);
+ if (!programObject)
+ {
+ return false;
+ }
+ return true;
+}
+
+bool ValidateBindFragDataLocationEXT(Context *context,
+ GLuint program,
+ GLuint colorNumber,
+ const char *name)
+{
+ return ValidateBindFragDataLocationIndexedEXT(context, program, colorNumber, 0u, name);
+}
+
+bool ValidateGetFragDataIndexEXT(Context *context, GLuint program, const char *name)
+{
+ if (!context->getExtensions().blendFuncExtended)
+ {
+ ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
+ return false;
+ }
+ if (context->getClientMajorVersion() < 3)
+ {
+ ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
+ return false;
+ }
+ Program *programObject = GetValidProgram(context, program);
+ if (!programObject)
+ {
+ return false;
+ }
+ if (!programObject->isLinked())
+ {
+ ANGLE_VALIDATION_ERR(context, InvalidOperation(), ProgramNotLinked);
+ return false;
+ }
+ return true;
+}
+
} // namespace gl