|
@@ -26,6 +26,7 @@
|
|
|
|
|
|
// C++
|
|
|
#include <algorithm>
|
|
|
+#include <limits>
|
|
|
|
|
|
namespace love
|
|
|
{
|
|
@@ -50,7 +51,7 @@ namespace
|
|
|
~TemporaryAttacher()
|
|
|
{
|
|
|
if (prevShader != nullptr)
|
|
|
- prevShader->attach();
|
|
|
+ prevShader->attach(true);
|
|
|
else
|
|
|
curShader->detach();
|
|
|
}
|
|
@@ -217,7 +218,12 @@ bool Shader::loadVolatile()
|
|
|
lastCanvas = (Canvas *) -1;
|
|
|
lastViewport = OpenGL::Viewport();
|
|
|
|
|
|
- lastPointSize = 0.0f;
|
|
|
+ lastPointSize = -1.0f;
|
|
|
+
|
|
|
+ // Invalidate the cached matrices by setting some elements to NaN.
|
|
|
+ float nan = std::numeric_limits<float>::quiet_NaN();
|
|
|
+ lastProjectionMatrix.setTranslation(nan, nan);
|
|
|
+ lastTransformMatrix.setTranslation(nan, nan);
|
|
|
|
|
|
// zero out active texture list
|
|
|
activeTexUnits.clear();
|
|
@@ -299,7 +305,7 @@ bool Shader::loadVolatile()
|
|
|
// make sure glUseProgram gets called.
|
|
|
current = nullptr;
|
|
|
attach();
|
|
|
- checkSetScreenParams();
|
|
|
+ checkSetBuiltinUniforms();
|
|
|
}
|
|
|
|
|
|
return true;
|
|
@@ -629,68 +635,6 @@ bool Shader::hasVertexAttrib(VertexAttribID attrib) const
|
|
|
return builtinAttributes[int(attrib)] != -1;
|
|
|
}
|
|
|
|
|
|
-bool Shader::hasBuiltinUniform(BuiltinUniform builtin) const
|
|
|
-{
|
|
|
- return builtinUniforms[int(builtin)] != -1;
|
|
|
-}
|
|
|
-
|
|
|
-bool Shader::sendBuiltinMatrix(BuiltinUniform builtin, int size, const GLfloat *m, int count)
|
|
|
-{
|
|
|
- if (!hasBuiltinUniform(builtin))
|
|
|
- return false;
|
|
|
-
|
|
|
- GLint location = builtinUniforms[GLint(builtin)];
|
|
|
-
|
|
|
- TemporaryAttacher attacher(this);
|
|
|
-
|
|
|
- switch (size)
|
|
|
- {
|
|
|
- case 2:
|
|
|
- glUniformMatrix2fv(location, count, GL_FALSE, m);
|
|
|
- break;
|
|
|
- case 3:
|
|
|
- glUniformMatrix3fv(location, count, GL_FALSE, m);
|
|
|
- break;
|
|
|
- case 4:
|
|
|
- glUniformMatrix4fv(location, count, GL_FALSE, m);
|
|
|
- break;
|
|
|
- default:
|
|
|
- return false;
|
|
|
- }
|
|
|
-
|
|
|
- return true;
|
|
|
-}
|
|
|
-
|
|
|
-bool Shader::sendBuiltinFloat(BuiltinUniform builtin, int size, const GLfloat *vec, int count)
|
|
|
-{
|
|
|
- if (!hasBuiltinUniform(builtin))
|
|
|
- return false;
|
|
|
-
|
|
|
- GLint location = builtinUniforms[int(builtin)];
|
|
|
-
|
|
|
- TemporaryAttacher attacher(this);
|
|
|
-
|
|
|
- switch (size)
|
|
|
- {
|
|
|
- case 1:
|
|
|
- glUniform1fv(location, count, vec);
|
|
|
- break;
|
|
|
- case 2:
|
|
|
- glUniform2fv(location, count, vec);
|
|
|
- break;
|
|
|
- case 3:
|
|
|
- glUniform3fv(location, count, vec);
|
|
|
- break;
|
|
|
- case 4:
|
|
|
- glUniform4fv(location, count, vec);
|
|
|
- break;
|
|
|
- default:
|
|
|
- return false;
|
|
|
- }
|
|
|
-
|
|
|
- return true;
|
|
|
-}
|
|
|
-
|
|
|
void Shader::checkSetScreenParams()
|
|
|
{
|
|
|
OpenGL::Viewport view = gl.getViewport();
|
|
@@ -720,7 +664,13 @@ void Shader::checkSetScreenParams()
|
|
|
params[3] = (GLfloat) view.h;
|
|
|
}
|
|
|
|
|
|
- sendBuiltinFloat(BUILTIN_SCREEN_SIZE, 4, params, 1);
|
|
|
+ GLint location = builtinUniforms[BUILTIN_SCREEN_SIZE];
|
|
|
+
|
|
|
+ if (location >= 0)
|
|
|
+ {
|
|
|
+ TemporaryAttacher attacher(this);
|
|
|
+ glUniform4fv(location, 1, params);
|
|
|
+ }
|
|
|
|
|
|
lastCanvas = Canvas::current;
|
|
|
lastViewport = view;
|
|
@@ -731,11 +681,65 @@ void Shader::checkSetPointSize(float size)
|
|
|
if (size == lastPointSize)
|
|
|
return;
|
|
|
|
|
|
- sendBuiltinFloat(BUILTIN_POINT_SIZE, 1, &size, 1);
|
|
|
+ GLint location = builtinUniforms[BUILTIN_POINT_SIZE];
|
|
|
+
|
|
|
+ if (location >= 0)
|
|
|
+ {
|
|
|
+ TemporaryAttacher attacher(this);
|
|
|
+ glUniform1f(location, size);
|
|
|
+ }
|
|
|
|
|
|
lastPointSize = size;
|
|
|
}
|
|
|
|
|
|
+void Shader::checkSetBuiltinUniforms()
|
|
|
+{
|
|
|
+ checkSetScreenParams();
|
|
|
+
|
|
|
+ if (GLAD_ES_VERSION_2_0)
|
|
|
+ {
|
|
|
+ checkSetPointSize(gl.getPointSize());
|
|
|
+
|
|
|
+ const Matrix &curxform = gl.matrices.transform.back();
|
|
|
+ const Matrix &curproj = gl.matrices.projection.back();
|
|
|
+
|
|
|
+ TemporaryAttacher attacher(this);
|
|
|
+
|
|
|
+ bool tpmatrixneedsupdate = false;
|
|
|
+
|
|
|
+ // Only upload the matrices if they've changed.
|
|
|
+ if (memcmp(curxform.getElements(), lastTransformMatrix.getElements(), sizeof(float) * 16) != 0)
|
|
|
+ {
|
|
|
+ GLint location = builtinUniforms[BUILTIN_TRANSFORM_MATRIX];
|
|
|
+ if (location >= 0)
|
|
|
+ glUniformMatrix4fv(location, 1, GL_FALSE, curxform.getElements());
|
|
|
+
|
|
|
+ tpmatrixneedsupdate = true;
|
|
|
+ lastTransformMatrix = curxform;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (memcmp(curproj.getElements(), lastProjectionMatrix.getElements(), sizeof(float) * 16) != 0)
|
|
|
+ {
|
|
|
+ GLint location = builtinUniforms[BUILTIN_PROJECTION_MATRIX];
|
|
|
+ if (location >= 0)
|
|
|
+ glUniformMatrix4fv(location, 1, GL_FALSE, curproj.getElements());
|
|
|
+
|
|
|
+ tpmatrixneedsupdate = true;
|
|
|
+ lastProjectionMatrix = curproj;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (tpmatrixneedsupdate)
|
|
|
+ {
|
|
|
+ GLint location = builtinUniforms[BUILTIN_TRANSFORM_PROJECTION_MATRIX];
|
|
|
+ if (location >= 0)
|
|
|
+ {
|
|
|
+ Matrix tp_matrix(curproj * curxform);
|
|
|
+ glUniformMatrix4fv(location, 1, GL_FALSE, tp_matrix.getElements());
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
const std::map<std::string, Object *> &Shader::getBoundRetainables() const
|
|
|
{
|
|
|
return boundRetainables;
|