add experimental state tracker for opengl
git-svn-id: http://skia.googlecode.com/svn/trunk@211 2bbb7eff-a529-9590-31e7-b0007b416f81
diff --git a/src/gl/SkGLState.cpp b/src/gl/SkGLState.cpp
new file mode 100644
index 0000000..6a3cbc0
--- /dev/null
+++ b/src/gl/SkGLState.cpp
@@ -0,0 +1,155 @@
+#include "SkGLState.h"
+#include "SkColorPriv.h"
+
+// here is our global instance
+SkGLState SkGLState::gState;
+
+// this is an illegal pmcolor, since its alpha (0) is less than its red
+#define UNKNOWN_PMCOLOR (SK_R32_MASK << SK_R32_SHIFT)
+
+#define UNKNOWN_GLENUM ((GLenum)-1)
+
+// MUST be in the same order as SkGLState::Caps enum
+static const GLenum gCapsTable[] = {
+ GL_DITHER,
+ GL_TEXTURE_2D,
+};
+
+// MUST be in the same order as SkGLState::ClientState enum
+static const GLenum gClientStateTable[] = {
+ GL_TEXTURE_COORD_ARRAY,
+ GL_COLOR_ARRAY,
+};
+
+static const GLenum gShadeModelTable[] = {
+ GL_FLAT,
+ GL_SMOOTH
+};
+
+///////////////////////////////////////////////////////////////////////////////
+
+SkGLState::SkGLState() :
+ fCapsPtr(gCapsTable),
+ fClientPtr(gClientStateTable),
+ fShadePtr(gShadeModelTable) {
+ this->init();
+}
+
+void SkGLState::init() {
+ fCapBits = 0;
+ fClientStateBits = 0;
+ fShadeModel = UNKNOWN_GLENUM;
+ fScissorSize.set(-1, -1);
+ fPMColor = UNKNOWN_PMCOLOR;
+ fSrcBlend = fDstBlend = UNKNOWN_GLENUM;
+ fPointSize = fLineWidth = -1;
+}
+
+void SkGLState::reset() {
+ this->init();
+
+ size_t i;
+ for (i = 0; i < SK_ARRAY_COUNT(gCapsTable); i++) {
+ glDisable(fCapsPtr[i]);
+ }
+ for (i = 0; i < SK_ARRAY_COUNT(gClientStateTable); i++) {
+ glDisableClientState(fClientPtr[i]);
+ }
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+void SkGLState::enable(Caps c) {
+ unsigned mask = 1 << c;
+ if ((fCapBits & mask) == 0) {
+ fCapBits |= mask;
+ glEnable(fCapsPtr[c]);
+ }
+}
+
+void SkGLState::disable(Caps c) {
+ unsigned mask = 1 << c;
+ if (fCapBits & mask) {
+ fCapBits &= ~mask;
+ glDisable(fCapsPtr[c]);
+ }
+}
+
+void SkGLState::enableClientState(ClientState c) {
+ unsigned mask = 1 << c;
+ if ((fClientStateBits & mask) == 0) {
+ fClientStateBits |= mask;
+ glEnableClientState(fClientPtr[c]);
+ }
+}
+
+void SkGLState::disableClientState(ClientState c) {
+ unsigned mask = 1 << c;
+ if (fClientStateBits & mask) {
+ fClientStateBits &= ~mask;
+ glDisableClientState(fClientPtr[c]);
+ }
+}
+
+void SkGLState::shadeModel(ShadeModel s) {
+ if (fShadeModel != s) {
+ fShadeModel = s;
+ glShadeModel(fShadePtr[s]);
+ }
+}
+
+void SkGLState::scissor(int x, int y, int w, int h) {
+ SkASSERT(w >= 0 && h >= 0);
+ if (!fScissorLoc.equals(x, y) || !fScissorSize.equals(w, h)) {
+ fScissorLoc.set(x, y);
+ fScissorSize.set(w, h);
+ glScissor(x, y, w, h);
+ }
+}
+
+void SkGLState::pointSize(float x) {
+ if (fPointSize != x) {
+ fPointSize = x;
+ glPointSize(x);
+ }
+}
+
+void SkGLState::lineWidth(float x) {
+ if (fLineWidth != x) {
+ fLineWidth = x;
+ glLineWidth(x);
+ }
+}
+
+void SkGLState::blendFunc(GLenum src, GLenum dst) {
+ if (fSrcBlend != src || fDstBlend != dst) {
+ fSrcBlend = src;
+ fDstBlend = dst;
+ glBlendFunc(src, dst);
+ }
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+#ifdef SK_GL_HAS_COLOR4UB
+ static inline void gl_pmcolor(U8CPU r, U8CPU g, U8CPU b, U8CPU a) {
+ glColor4ub(r, g, b, a);
+ }
+#else
+ static inline SkFixed byte2fixed(U8CPU value) {
+ return ((value << 8) | value) + (value >> 7);
+ }
+
+ static inline void gl_pmcolor(U8CPU r, U8CPU g, U8CPU b, U8CPU a) {
+ glColor4x(byte2fixed(r), byte2fixed(g), byte2fixed(b), byte2fixed(a));
+ }
+#endif
+
+void SkGLState::pmColor(SkPMColor c) {
+ if (fPMColor != c) {
+ fPMColor = c;
+ gl_pmcolor(SkGetPackedR32(c), SkGetPackedG32(c),
+ SkGetPackedB32(c), SkGetPackedA32(c));
+ }
+}
+