--- /dev/null
+#include <stdexcept>
+#include <msp/strings/format.h>
+#include "stenciltest.h"
+
+using namespace std;
+
+namespace Msp {
+namespace GL {
+
+StencilTest::StencilTest():
+ enabled(false),
+ compare(ALWAYS),
+ stencil_fail_op(KEEP),
+ depth_fail_op(KEEP),
+ depth_pass_op(KEEP),
+ reference(0)
+{ }
+
+
+StencilTest::Loader::Loader(StencilTest &st):
+ ObjectLoader<StencilTest>(st)
+{
+ add("compare", &Loader::compare);
+ add("actions", &Loader::actions);
+ add("reference", &StencilTest::reference);
+}
+
+void StencilTest::Loader::compare(Predicate c)
+{
+ obj.enabled = true;
+ obj.compare = c;
+}
+
+void StencilTest::Loader::actions(StencilOp sf, StencilOp df, StencilOp dp)
+{
+ obj.stencil_fail_op = sf;
+ obj.depth_fail_op = df;
+ obj.depth_pass_op = dp;
+}
+
+
+GLenum get_gl_stencil_op(StencilOp op)
+{
+ switch(op)
+ {
+ case KEEP: return GL_KEEP;
+ case SET_ZERO: return GL_ZERO;
+ case REPLACE: return GL_REPLACE;
+ case INCR: return GL_INCR;
+ case DECR: return GL_DECR;
+ case INVERT: return GL_INVERT;
+ case INCR_WRAP: return GL_INCR_WRAP;
+ case DECR_WRAP: return GL_DECR_WRAP;
+ default: throw invalid_argument("get_gl_stencil_op");
+ }
+}
+
+void operator>>(const LexicalConverter &conv, StencilOp &op)
+{
+ const string &str = conv.get();
+ if(str=="KEEP")
+ op = KEEP;
+ else if(str=="SET_ZERO")
+ op = SET_ZERO;
+ else if(str=="REPLACE")
+ op = REPLACE;
+ else if(str=="INCR")
+ op = INCR;
+ else if(str=="DECR")
+ op = DECR;
+ else if(str=="INVERT")
+ op = INVERT;
+ else if(str=="INCR_WRAP")
+ op = INCR_WRAP;
+ else if(str=="DECR_WRAP")
+ op = DECR_WRAP;
+ else
+ throw lexical_error(format("conversion of '%s' to StencilOp", str));
+}
+
+void operator<<(LexicalConverter &conv, StencilOp op)
+{
+ switch(op)
+ {
+ case KEEP: conv.result("KEEP"); break;
+ case SET_ZERO: conv.result("SET_ZERO"); break;
+ case REPLACE: conv.result("REPLACE"); break;
+ case INCR: conv.result("INCR"); break;
+ case DECR: conv.result("DECR"); break;
+ case INVERT: conv.result("INVERT"); break;
+ case INCR_WRAP: conv.result("INCR_WRAP"); break;
+ case DECR_WRAP: conv.result("DECR_WRAP"); break;
+ default: conv.result(format("StencilOp(%#x)", static_cast<int>(op)));
+ }
+}
+
+} // namespace GL
+} // namespace Msp