ecere/gfx/newFonts: Runtime switching of shaders/ffp
authorJerome St-Louis <jerome@ecere.com>
Wed, 6 Jul 2016 09:34:58 +0000 (05:34 -0400)
committerJerome St-Louis <jerome@ecere.com>
Wed, 2 Nov 2016 16:32:49 +0000 (12:32 -0400)
ecere/gfx/newFonts/DrawManager: Simplified and unified Shaders/FFP
- Making use of default vertex shader for now
- Moved image list from FontRenderer to DrawManager to avoid flush render while defining images
- Making use of glBufferSubData

ecere/src/gfx/newFonts/cc/mmbitmap.h
ecere/src/gfx/newFonts/drawManager.ec
ecere/src/gfx/newFonts/fmFontManager.ec
ecere/src/gfx/newFonts/fontRenderer.ec
ecere/src/gfx/newFonts/textureManager.ec

index 5455b38..1ae7122 100644 (file)
@@ -190,9 +190,8 @@ static inline int mmBitMapMaskGet( mmBitMap *bitmap, size_t entryindex, long mas
 
 static inline void mmBitMapMaskSet( mmBitMap *bitmap, size_t entryindex, long value, long mask )
 {
-  size_t index, shift;
-  index = entryindex >> CPUCONF_LONG_BITSHIFT;
-  shift = entryindex & ( CPUCONF_LONG_BITS - 1 );
+  size_t index = entryindex >> CPUCONF_LONG_BITSHIFT;
+  size_t shift = entryindex & ( CPUCONF_LONG_BITS - 1 );
 #ifdef MM_ATOMIC_SUPPORT
   long oldvalue, newvalue;
   for( ; ; )
index 1ff2c11..4ef28e5 100644 (file)
 import "OpenGLDisplayDriver"
+import "textureManager"
 
-#define _Noreturn
+#include "glHelpers.h"
 
-#include <stdio.h>
-#include <math.h>
+#define _Noreturn
 #include <stdlib.h>
-
-#if !defined(_GLES)
-   #define SHADERS
-#endif
-
-#if defined(__EMSCRIPTEN__)
-#if !defined(_GLES2)
-   #define _GLES2
-#endif
-   #include <GLES2/gl2.h>
-#endif
-
-#if defined(__ANDROID__) || defined(__ODROID__)
-#if !defined(_GLES)
-   #define _GLES
-#endif
-   #include <GLES/gl.h>
-#endif
-
-#if !defined(__ANDROID__) && !defined(__EMSCRIPTEN__) && !defined(__ODROID__)
-#  if defined(SHADERS)
-//#     include "gl_core_3_3.h"
-#     include "gl_compat_4_4.h"     // FIXME: no glPushAttrib() in core profile
-#  else
-#     include "gl_compat_4_4.h"
-#  endif
-#endif
-
-#ifdef SHADERS
-
-#undef glEnableClientState
-#undef glDisableClientState
-#undef GL_VERTEX_ARRAY
-#undef GL_NORMAL_ARRAY
-#undef GL_TEXTURE_COORD_ARRAY
-#undef GL_COLOR_ARRAY
-#undef glVertexPointer
-#undef glTexCoordPointer
-#undef glColorPointer
-
-#define glEnableClientState      glEnableVertexAttribArray
-#define glDisableClientState     glDisableVertexAttribArray
-#define GL_VERTEX_ARRAY          GLBufferContents::vertex
-#define GL_NORMAL_ARRAY          GLBufferContents::normal
-#define GL_TEXTURE_COORD_ARRAY   GLBufferContents::texCoord
-#define GL_COLOR_ARRAY           GLBufferContents::color
-#define glVertexPointer(n, t, s, p)    glVertexAttribPointer(GLBufferContents::vertex,   n, t, GL_FALSE, s, p)
-#define glTexCoordPointer(n, t, s, p)  glVertexAttribPointer(GLBufferContents::texCoord, n, t, GL_FALSE, s, p)
-#define glColorPointer(n, t, s, p)     glVertexAttribPointer(GLBufferContents::color,    n, t, GL_FALSE, s, p)
-
-#endif
-
-#if defined(_GLES) || defined(_GLES2) || defined(SHADERS)
-
-   #undef glRecti
-   #undef glBegin
-   #undef glTexCoord2i
-   #undef glVertex2i
-   #undef glTexCoord2d
-   #undef glVertex2d
-   #undef glTexCoord2f
-   #undef glVertex2f
-   #undef glEnd
-   #undef glColor3f
-   #undef glColor4ub
-   #undef glColor4fv
-   #undef glNormal3fv
-   #undef glNormal3f
-   #undef glTexCoord2fv
-   #undef glVertex3d
-   #undef glVertex3dv
-   #undef glVertex3f
-   #undef glVertex3fv
-
-   #undef glLoadMatrixd
-   #undef glLoadMatrixf
-   #undef glMultMatrixd
-   #undef glFrustum
-   #undef glOrtho
-   #undef glScaled
-   #undef glScalef
-   #undef glTranslated
-   #undef glRotated
-   #undef glMatrixMode
-   #undef glLoadIdentity
-   #undef glPushMatrix
-   #undef glPopMatrix
-
-   #undef glLineStipple
-   #undef glColorMaterial
-   #undef glLightModeli
-
-   #define glRecti               glimtkRecti
-   #define glBegin               glimtkBegin
-   #define glTexCoord2i          glimtkTexCoord2i
-   #define glVertex2i            glimtkVertex2i
-   #define glTexCoord2d          glimtkTexCoord2d
-   #define glVertex2d            glimtkVertex2d
-   #define glTexCoord2f          glimtkTexCoord2f
-   #define glVertex2f            glimtkVertex2f
-   #define glEnd                 glimtkEnd
-   #define glColor3f             glimtkColor3f
-   #define glColor4ub            glimtkColor4ub
-   #define glColor4fv            glimtkColor4fv
-   #define glNormal3fv           glimtkNormal3fv
-   #define glNormal3f            glimtkNormal3f
-   #define glTexCoord2fv         glimtkTexCoord2fv
-   #define glVertex3d            glimtkVertex3d
-   #define glVertex3dv           glimtkVertex3dv
-   #define glVertex3f            glimtkVertex3f
-   #define glVertex3fv           glimtkVertex3fv
-
-   #define glLoadMatrixd         glmsLoadMatrixd
-   #define glLoadMatrixf         glmsLoadMatrixf
-   #define glMultMatrixd         glmsMultMatrixd
-   #define glFrustum             glmsFrustum
-   #define glOrtho               glmsOrtho
-   #define glScaled              glmsScaled
-   #define glScalef              glmsScaled
-   #define glTranslated          glmsTranslated
-   #define glRotated             glmsRotated
-   #define glMatrixMode          glmsMatrixMode
-   #define glLoadIdentity        glmsLoadIdentity
-   #define glPushMatrix          glmsPushMatrix
-   #define glPopMatrix           glmsPopMatrix
-
-   #define glLineStipple         glesLineStipple
-   #define glColorMaterial       glesColorMaterial
-   #define glLightModeli         glesLightModeli
-
-#endif
-
+#include <math.h>
 #include "cc.h"
-
 #define OFFSET(s, m) ((uint)(uintptr) (&((s *) 0)->m))
 
-import "textureManager"
+// TODO: Indices (2/3 data)
+// TODO: glMapBufferRange() with GL_MAP_INVALIDATE_BUFFER_BIT | GL_MAP_FLUSH_EXPLICIT_BIT
+// TODO: movnti to write to VBO: _mm_stream_ps(), _mm_stream_si32(), _mm_stream_si64()
+// TODO: When the state changes, it should keep filling up a same VBO, then when the VBO is full (or when we are done), perform all the Draw() calls on that same VBO
+// TODO: VAO
 
-
-#define DM_ENABLE_IMAGE_ROTATION (1)
-#define DM_ENABLE_EXT_COLOR (1)
-
-////
-
-static struct DMDrawVertexFlat
-{
-  float vertex[2];
-  float texcoord0[2];
-  uint32 color;
-#if DM_ENABLE_EXT_COLOR
-  uint32 extcolor;
-#endif
-} __attribute__((aligned(16)));
-
-static struct DMDrawVertex
-{
-  short vertex[2];
-  short texcoord0[2];
-  uint32 color;
-#if DM_ENABLE_EXT_COLOR
-  uint32 extcolor;
-#endif
-} __attribute__((aligned(16)));
+static struct DMDrawVertex { short vx, vy, tx, ty; };
 
 struct DMDrawBuffer
 {
-   GLuint vbo;
+   GLAB vbo;
    int glType;
    int vertexCount;
    int vertexAlloc;
    void *vertexBuffer;
 };
 
-class DMProgramFlags : uint { bool valid:1; }
-
-struct DMProgram
-{
-  GLuint glProgram;
-  GLuint vertexShader;
-  GLuint fragmentShader;
-  GLint matrixloc;
-  GLint vertexloc;
-  GLint texcoord0loc;
-  GLint texcoord1loc;
-  GLint colorloc;
-#if DM_ENABLE_EXT_COLOR
-  GLint extcolorloc;
-#endif
-  GLint texbaseloc;
-  DMProgramFlags flags;
-  int64 lastUpdateCount;
-};
-
 class DMImageFlags : uint16
 {
    bool empty:1;     // Image is empty, do not draw
    bool blending:1;  // Must draw image with blending
+   int swizzle:2;
 }
 
-public struct DMImage
+#define DM_BARRIER_ORDER_BITS 5
+
+class DMOrderMask : uint32
+{
+   int imageOrder:8;
+   bool blend:1;
+   int texture:10;
+   int layer:4;
+   int barrier:DM_BARRIER_ORDER_BITS;
+};
+
+struct DMImage
 {
 private:
    Texture texture;
@@ -214,111 +54,36 @@ private:
    short sizex, sizey;
 
    // Computed order for sorted rendering, in defineImage()
-   uint32 orderMask;
+   DMOrderMask orderMask;
 
 public:
    void clear()
    {
       this = { flags = { empty = true } };
    }
-
-   void defineImage( Texture texture, int offsetx, int offsety, int sizex, int sizey, bool blending, int programIndex, int layerindex )
-   {
-      int ordx = offsetx >> 6;
-      int ordy = offsety >> 6;
-      uint32 orderimage = ccMortonNumber32( ordx, ordy ) & ( ( 1 << DM_IMAGE_ORDER_BITS ) - 1 );
-      this =
-      {
-         texture = texture;
-         srcx = (short)offsetx;
-         srcy = (short)offsety;
-         sizex = (short)sizex;
-         sizey = (short)sizey;
-         programIndex = (short)programIndex;
-         flags = { blending = blending };
-         orderMask = (orderimage << DM_IMAGE_ORDER_SHIFT) |
-                     (( blending == true ) << DM_BLEND_ORDER_SHIFT) |
-                     (programIndex << DM_PROGRAM_ORDER_SHIFT) |
-                     texture.orderMask |
-                     (layerindex << DM_LAYER_ORDER_SHIFT);
-      };
-   }
 };
 
 struct DMImageBuffer
 {
-  DMImage *image;
-  short offsetx;
-  short offsety;
-  short sizex;
-  short sizey;
-#if DM_ENABLE_IMAGE_ROTATION
-  short angcos;
-  short angsin;
-#endif
-#if DM_ENABLE_EXT_COLOR
-  uint32 extcolor;
-#endif
-  uint32 color;
-  uint32 orderindex;
+   int image;
+   short offsetx, offsety;
+   short sizex, sizey;
+   short angcos, angsin;
+   ColorAlpha color;
+   uint32 orderIndex;
 };
 
-
-////
-
-
-define DM_IMAGE_ORDER_BITS = 8;
-define DM_BLEND_ORDER_BITS = 1;
-define DM_PROGRAM_ORDER_BITS = 4;
-define DM_TEXTURE_ORDER_BITS = 10;
-define DM_LAYER_ORDER_BITS = 4;
-define DM_BARRIER_ORDER_BITS = 5;
-
-define DM_IMAGE_ORDER_SHIFT = 0;
-define DM_BLEND_ORDER_SHIFT = DM_IMAGE_ORDER_BITS;
-define DM_PROGRAM_ORDER_SHIFT = DM_IMAGE_ORDER_BITS+DM_BLEND_ORDER_BITS;
-define DM_TEXTURE_ORDER_SHIFT = DM_IMAGE_ORDER_BITS+DM_BLEND_ORDER_BITS+DM_PROGRAM_ORDER_BITS;
-define DM_LAYER_ORDER_SHIFT = DM_IMAGE_ORDER_BITS+DM_BLEND_ORDER_BITS+DM_PROGRAM_ORDER_BITS+DM_TEXTURE_ORDER_BITS;
-define DM_BARRIER_ORDER_SHIFT = DM_IMAGE_ORDER_BITS+DM_BLEND_ORDER_BITS+DM_PROGRAM_ORDER_BITS+DM_TEXTURE_ORDER_BITS+DM_LAYER_ORDER_BITS;
+define DRAW_BUFFER_COUNT = 64;  // TOFIX: Can't make static?
+define DRAW_BUFFER_VERTEX_ALLOC = 1024;
 
 define DM_LAYER_COUNT = 1<<DM_LAYER_ORDER_BITS;
-define DM_PROGRAM_COUNT = 1<<DM_PROGRAM_ORDER_BITS;
-
-define DM_CONTEXT_DRAW_BUFFER_COUNT = 64;
-define DM_CONTEXT_DRAW_BUFFER_VERTEX_ALLOC = 1024;
 
-
-/* Range is from zero to DM_LAYER_COUNT */
-enum DMLayer
-{
-  DM_LAYER_0_BOTTOM,
-  DM_LAYER_1_BOTTOM,
-  DM_LAYER_2_BELOW,
-  DM_LAYER_3_BELOW,
-  DM_LAYER_4_BELOW,
-  DM_LAYER_5_NORMAL,
-  DM_LAYER_6_NORMAL,
-  DM_LAYER_7_NORMAL,
-  DM_LAYER_8_ABOVE,
-  DM_LAYER_9_ABOVE,
-  DM_LAYER_10_ABOVE,
-  DM_LAYER_11_OVERLAY,
-  DM_LAYER_12_OVERLAY,
-  DM_LAYER_13_OVERLAY,
-  DM_LAYER_14_TOP,
-  DM_LAYER_15_TOP,
-};
-
-define DM_LAYER_BOTTOM = DMLayer::DM_LAYER_0_BOTTOM;
-define DM_LAYER_BELOW = DMLayer::DM_LAYER_3_BELOW;
-define DM_LAYER_NORMAL = DMLayer::DM_LAYER_6_NORMAL;
-define DM_LAYER_ABOVE = DMLayer::DM_LAYER_9_ABOVE;
-define DM_LAYER_TOP = DMLayer::DM_LAYER_15_TOP;
-
-define DM_PROGRAM_NORMAL = 0;
-define DM_PROGRAM_ALPHABLEND = 1;
-define DM_PROGRAM_ALPHABLEND_INTENSITY = 2;
-define DM_PROGRAM_ALPHABLEND_INTENSITY_EXTCOLOR = 3;
+// Range is from zero to DM_LAYER_COUNT
+define DM_LAYER_BOTTOM = 0;
+define DM_LAYER_BELOW = 3;
+define DM_LAYER_NORMAL = 6;
+define DM_LAYER_ABOVE = 9;
+define DM_LAYER_TOP = 15;
 
 #ifdef _DEBUG
 static inline void OpenGLErrorCheck( const char *file, int line )
@@ -336,280 +101,17 @@ static inline void OpenGLErrorCheck( const char *file, int line )
 // Not using 32767.0 ; overflow when converting to int16 due to floating point crud causes problems
 #define DM_IMAGE_ROTATION_NORMFACTOR (24576.0f)
 
-#define DM_VERTEX_NORMSHIFT (2)
-#define DM_VERTEX_NORMFACTOR (4.0f)
-
-#define DM_TEXCOORD_NORMSHIFT (13)
-#define DM_TEXCOORD_NORMFACTOR (8192.0 /*f*/)
-
-#ifdef SHADERS
-static GLuint dmCreateShader( GLenum type, const char *shadersource, const char *optionstring )
-{
-  GLuint shader;
-  GLint status;
-  GLsizei loglength;
-  char infolog[8192];
-  const GLchar *sourcearray[2];
-
-  shader = glCreateShader( type );
-  if( !( shader ) )
-    return 0;
-
-  if( !( optionstring ) )
-    optionstring = "";
-  sourcearray[0] = optionstring;
-  sourcearray[1] = shadersource;
-  glShaderSource( shader, 2, sourcearray, NULL );
-  glCompileShader( shader );
-  glGetShaderiv( shader, GL_COMPILE_STATUS, &status );
-  if( status != GL_TRUE )
-  {
-    fprintf( stderr, "ERROR: Failed to compile shader\n" );
-    glGetShaderInfoLog( shader, 8192, &loglength,infolog );
-    fprintf( stderr, "ERROR: \n%s\n\n", infolog );
-    glDeleteShader( shader );
-    return 0;
-  }
-  return shader;
-}
-
-static bool dmCreateProgram( DMProgram program, const char *vertexsource, const char *fragmentsource, char *optionstring )
-{
-  GLint status;
-  GLsizei loglength;
-  char infolog[8192];
-
-  program.glProgram = 0;
-  program.vertexShader = 0;
-  program.fragmentShader = 0;
-
-  program.vertexShader = dmCreateShader( GL_VERTEX_SHADER, vertexsource, optionstring );
-  if( !( program.vertexShader ) )
-  {
-    fprintf(stderr, "ERROR: Unable to load vertex shader\n");
-    goto error;
-  }
-  program.fragmentShader = dmCreateShader( GL_FRAGMENT_SHADER, fragmentsource, optionstring );
-  if( !( program.fragmentShader ) )
-  {
-    fprintf(stderr, "ERROR: Unable to load fragment shader\n");
-    goto error;
-  }
-  program.glProgram = glCreateProgram();
-  if( !( program.glProgram ) )
-  {
-    fprintf(stderr, "ERROR: Unable to create program\n");
-    goto error;
-  }
-
-  glAttachShader( program.glProgram, program.vertexShader );
-  glAttachShader( program.glProgram, program.fragmentShader );
-
-   glBindAttribLocation(program.glProgram, GLBufferContents::vertex, "vertex");
-   glBindAttribLocation(program.glProgram, GLBufferContents::texCoord, "texCoord");
-   glBindAttribLocation(program.glProgram, GLBufferContents::color, "color");
-   glBindAttribLocation(program.glProgram, GLBufferContents::normal, "normal");
-
-  glLinkProgram( program.glProgram );
-  glGetProgramiv( program.glProgram, GL_LINK_STATUS, &status );
-  if( status != GL_TRUE )
-  {
-    fprintf( stderr, "ERROR, failed to link shader program\n" );
-    glGetProgramInfoLog( program.glProgram, 8192, &loglength, infolog );
-    fprintf( stderr, "ERROR: \n%s\n\n", infolog );
-    goto error;
-  }
-
-  // glUseProgram( program.glProgram );
-
-  program.matrixloc = glGetUniformLocation( program.glProgram, "uniMatrix" );
-  program.vertexloc = glGetAttribLocation( program.glProgram, "inVertex" );
-  program.texcoord0loc = glGetAttribLocation( program.glProgram, "inTexcoord0" );
-  program.texcoord1loc = glGetAttribLocation( program.glProgram, "inTexcoord1" );
-  program.colorloc = glGetAttribLocation( program.glProgram, "inColor" );
-#if DM_ENABLE_EXT_COLOR
-  program.extcolorloc = glGetAttribLocation( program.glProgram, "inExtColor" );
-#endif
-  program.texbaseloc = glGetUniformLocation( program.glProgram, "texBase" );
-  program.flags.valid = true;
-
-  return true;
-
-  error:
-  if( program.fragmentShader )
-    glDeleteShader( program.fragmentShader );
-  if( program.vertexShader )
-    glDeleteShader( program.vertexShader );
-  if( program.glProgram )
-    glDeleteProgram( program.glProgram );
-  return false;
-}
-
-
-////
-
-
-const char *dmVertexShaderNormal =
-"#version 130\n"
-"uniform mat4 uniMatrix;\n"
-"in vec2 inVertex;\n"
-"in vec2 inTexcoord0;\n"
-"in vec4 inColor;\n"
-"out vec2 varTexcoord0;\n"
-"out vec4 varColor;\n"
-"void main()\n"
-"{\n"
-" \n"
-"  varTexcoord0 = inTexcoord0 * (1.0/" CC_STRINGIFY(DM_TEXCOORD_NORMFACTOR) ");\n"
-"  varColor = inColor;\n"
-"  gl_Position = uniMatrix * vec4( inVertex, 0.0, 1.0 );\n"
-"  return;\n"
-"}\n"
-;
-
-
-const char *dmFragmentShaderNormal =
-"#version 130\n"
-"uniform sampler2D texBase;\n"
-"in vec2 varTexcoord0;\n"
-"in vec4 varColor;\n"
-"void main()\n"
-"{\n"
-"  gl_FragColor = varColor * texture2D( texBase, varTexcoord0 );\n"
-"  return;\n"
-"}\n"
-;
-
-
-const char *dmVertexShaderAlpha =
-"#version 130\n"
-"uniform mat4 uniMatrix;\n"
-"in vec2 inVertex;\n"
-"in vec2 inTexcoord0;\n"
-"in vec4 inColor;\n"
-"out vec2 varTexcoord0;\n"
-"out vec4 varColor;\n"
-"void main()\n"
-"{\n"
-" \n"
-"  varTexcoord0 = inTexcoord0 * (1.0/" CC_STRINGIFY(DM_TEXCOORD_NORMFACTOR) ");\n"
-"  varColor = inColor;\n"
-"  gl_Position = uniMatrix * vec4( inVertex, 0.0, 1.0 );\n"
-"  return;\n"
-"}\n"
-;
-
-
-const char *dmFragmentShaderAlpha =
-"#version 130\n"
-"uniform sampler2D texBase;\n"
-"in vec2 varTexcoord0;\n"
-"in vec4 varColor;\n"
-"void main()\n"
-"{\n"
-"  gl_FragColor = vec4( varColor.rgb, varColor.a * texture2D( texBase, varTexcoord0 ).r );\n"
-"  return;\n"
-"}\n"
-;
-
-const char *dmVertexShaderAlphaIntensity =
-"#version 130\n"
-"uniform mat4 uniMatrix;\n"
-"in vec2 inVertex;\n"
-"in vec2 inTexcoord0;\n"
-"in vec4 inColor;\n"
-"out vec2 varTexcoord0;\n"
-"out vec4 varColor;\n"
-"void main()\n"
-"{\n"
-" \n"
-"  varTexcoord0 = inTexcoord0 * (1.0/" CC_STRINGIFY(DM_TEXCOORD_NORMFACTOR) ");\n"
-"  varColor = inColor;\n"
-"  gl_Position = uniMatrix * vec4( inVertex, 0.0, 1.0 );\n"
-"  return;\n"
-"}\n"
-;
-
-
-const char *dmFragmentShaderAlphaIntensity =
-"#version 130\n"
-"uniform sampler2D texBase;\n"
-"in vec2 varTexcoord0;\n"
-"in vec4 varColor;\n"
-"void main()\n"
-"{\n"
-"  vec2 tex;\n"
-"  tex = texture2D( texBase, varTexcoord0 ).rg;\n"
-"  gl_FragColor = vec4( varColor.rgb * tex.g, varColor.a * tex.r );\n"
-"  return;\n"
-"}\n"
-;
-
-const char *dmVertexShaderAlphaIntensityExtColor =
-"#version 130\n"
-"uniform mat4 uniMatrix;\n"
-"in vec2 inVertex;\n"
-"in vec2 inTexcoord0;\n"
-"in vec4 inColor;\n"
-"in vec4 inExtColor;\n"
-"out vec2 varTexcoord0;\n"
-"out vec4 varColor;\n"
-"out vec4 varExtColor;\n"
-"void main()\n"
-"{\n"
-" \n"
-"  varTexcoord0 = inTexcoord0 * (1.0/" CC_STRINGIFY(DM_TEXCOORD_NORMFACTOR) ");\n"
-"  varColor = inColor;\n"
-"  varExtColor = inExtColor;\n"
-"  gl_Position = uniMatrix * vec4( inVertex, 0.0, 1.0 );\n"
-"  return;\n"
-"}\n"
-;
-
-
-const char *dmFragmentShaderAlphaIntensityExtColor =
-"#version 130\n"
-"uniform sampler2D texBase;\n"
-"in vec2 varTexcoord0;\n"
-"in vec4 varColor;\n"
-"in vec4 varExtColor;\n"
-"void main()\n"
-"{\n"
-"  vec2 tex;\n"
-"  tex = texture2D( texBase, varTexcoord0 ).rg;\n"
-"  gl_FragColor = vec4( mix( varExtColor.rgb, varColor.rgb, tex.g ), mix( varExtColor.a, varColor.a, tex.g ) * tex.r );\n"
-"  return;\n"
-"}\n"
-;
-
-////
-#endif
-
-static void matrixOrtho( float *m, float left, float right, float bottom, float top, float nearval, float farval )
-{
-  float x = 2.0f / ( right - left );
-  float y = 2.0f / ( top - bottom );
-  float z = -2.0f / ( farval - nearval );
-  float tx = -( right + left ) / ( right - left );
-  float ty = -( top + bottom ) / ( top - bottom );
-  float tz = -( farval + nearval ) / ( farval - nearval );
-
-#define M(row,col)  m[col*4+row]
-  M(0,0) = x;    M(0,1) = 0.0;  M(0,2) = 0.0;  M(0,3) = tx;
-  M(1,0) = 0.0;  M(1,1) = y;     M(1,2) = 0.0;  M(1,3) = ty;
-  M(2,0) = 0.0;  M(2,1) = 0.0;  M(2,2) = z;     M(2,3) = tz;
-  M(3,0) = 0.0;  M(3,1) = 0.0;  M(3,2) = 0.0;  M(3,3) = 1.0;
-#undef M
-}
+#define DM_VERTEX_NORMFACTOR 4.0f
 
-////
-
-
-/* FIXME: Radix sort, not hybrid sort! */
+#define DM_TEXCOORD_NORMFACTOR 8192.0f
 
+// FIXME: Radix sort, not hybrid sort!
 static inline int dmSortImagesCmp( DMImageBuffer *draw0, DMImageBuffer *draw1 )
 {
-  return ( ( draw0->orderindex < draw1->orderindex ) ? 0 : 1 );
+   uint32 ix1 = draw1->orderIndex, ix2 = draw0->orderIndex;
+   if(ix1 < ix2) return 1;
+   if(ix1 == ix2 && draw1->color < draw0->color) return 1;
+   return 0;
 }
 
 #define HSORT_MAIN dmSortImages
@@ -620,564 +122,252 @@ static inline int dmSortImagesCmp( DMImageBuffer *draw0, DMImageBuffer *draw1 )
 #undef HSORT_CMP
 #undef HSORT_TYPE
 
-
-////
-
 // TOFIX: Make this private, have a property
-public class DrawManagerFlags : uint32 { public: bool prehistoricOpenGL:1; }
-
 public class DrawManager
 {
-   DrawManagerFlags flags;
+   bool renderingFlipped;
 
-   // Matrix
-   float matrix[16];
+   int imageCount, imageAlloc;
+   DMImage *imageList;
+   imageAlloc = 512;
+   imageList = new DMImage[imageAlloc];
+
+   void resetImages()
+   {
+      imageCount = 0;
+   }
+
+   void clearImages()
+   {
+      delete imageList;
+      imageCount = 0;
+      imageAlloc = 512;
+      imageList = new DMImage[imageAlloc];
+   }
 
-   int imageBufferCount;
-   int imageBufferSize;
-   DMImageBuffer *imageBuffer;
-   DMImageBuffer *imageBufferTmp;
+   int imageBufferCount, imageBufferSize;
+   DMImageBuffer *imageBuffers, *imageBuffersTmp;
 
    // Buffers for drawimages() batching
-   DMDrawBuffer drawBuffer[DM_CONTEXT_DRAW_BUFFER_COUNT];
-   int drawBufferIndex;
-   int drawBarrierIndex;
-   uint32 orderBarrierMask;
+   DMDrawBuffer drawBuffers[DRAW_BUFFER_COUNT];
+   int drawBufferIndex, drawBarrierIndex;
+   DMOrderMask orderBarrierMask;
 
    // Counter to track program uniforms and such
    int64 updateCount;
 
-   DMProgram shaderPrograms[DM_PROGRAM_COUNT];
-   GLuint prevProgram;
-
-   bool renderingFlipped;
-
-   static DMProgram *flushUseProgram( int programIndex )
+   int defineImage( Texture texture, int offsetx, int offsety, int sizex, int sizey, bool blending, int layer )
    {
-      DMProgram *program = &shaderPrograms[ programIndex ];
-      if( !program->flags.valid)
+      int ordx = offsetx >> 6;
+      int ordy = offsety >> 6;
+      int imageIndex = imageCount++;
+      if( imageCount > imageAlloc )
       {
-#ifdef SHADERS
-         glUseProgram( 0 );
-#endif
-         return 0;
+         imageAlloc <<= 1;
+         imageList = renew imageList DMImage[imageAlloc];
       }
-
-#ifdef SHADERS
-      glUseProgram( program->glProgram );
-#endif
-      if( program->lastUpdateCount != this.updateCount )
+      imageList[ imageIndex ] =
       {
-#ifdef SHADERS
-         glUniformMatrix4fv( program->matrixloc, 1, GL_FALSE, this.matrix );
-         glUniform1i( program->texbaseloc, 0 );
-#endif
-         program->lastUpdateCount = this.updateCount;
-      }
-      return program;
+         texture = texture;
+         srcx = (short)offsetx;
+         srcy = (short)offsety;
+         sizex = (short)sizex;
+         sizey = (short)sizey;
+         flags = { blending = blending, swizzle = texture.swizzle };
+         orderMask =
+         {
+            imageOrder = ccMortonNumber32( ordx, ordy ) & 0xFF,
+            blend = blending, texture = texture.orderMask, layer = layer
+         };
+      };
+      return imageIndex;
    }
 
-#if !defined(__EMSCRIPTEN__)
-   static void flushRenderDrawBufferArchaic( DMDrawBuffer drawBuffer, DMProgram program, int vertexCount )
+   static void flushRenderDrawBuffer( DMDrawBuffer drawBuffer,  int vertexCount )
    {
-      glEnable( GL_TEXTURE_2D );
-      glBindBuffer( GL_ARRAY_BUFFER, drawBuffer.vbo );
-      glColor3f( 1.0, 1.0, 1.0 );
-
-      glEnableClientState( GL_VERTEX_ARRAY );
-      glEnableClientState( GL_TEXTURE_COORD_ARRAY );
-      glEnableClientState( GL_COLOR_ARRAY );
+      glBindBuffer( GL_ARRAY_BUFFER, drawBuffer.vbo.buffer );
 
-      glVertexPointer( 2, GL_FLOAT, sizeof(DMDrawVertexFlat), (void *)OFFSET(DMDrawVertexFlat,vertex) );
-      glTexCoordPointer( 2, GL_FLOAT, sizeof(DMDrawVertexFlat), (void *)OFFSET(DMDrawVertexFlat,texcoord0) );
-      glColorPointer( 4, GL_UNSIGNED_BYTE, sizeof(DMDrawVertexFlat), (void *)OFFSET(DMDrawVertexFlat,color) );
+      GLVertexPointer  (2, GL_SHORT, sizeof(DMDrawVertex), (void *)OFFSET(DMDrawVertex, vx) );
+      GLTexCoordPointer(2, GL_SHORT, sizeof(DMDrawVertex), (void *)OFFSET(DMDrawVertex, tx) );
 
       glDrawArrays( GL_TRIANGLES, 0, vertexCount );
-
-      glDisableClientState( GL_VERTEX_ARRAY );
-      glDisableClientState( GL_TEXTURE_COORD_ARRAY );
-      glDisableClientState( GL_COLOR_ARRAY );
-      glDisable( GL_TEXTURE_2D );
-
-   #if DM_FLUSH_EACH_RENDER_DRAW_BUFFER
-      glFlush();
-   #endif
    }
 
-   void flushDrawImagesArchaic( )
+   void flushImages()
    {
-     bool flushflag, stateBlend;
-     int index, vertexCount, programIndex;
-     float vx0, vx1, vx2, vx3, vy0, vy1, vy2, vy3;
-   #if DM_ENABLE_IMAGE_ROTATION
-     float angsin, angcos, sizex, sizey;
-   #endif
-     float tx0, tx1, ty0, ty1;
-     DMImageBuffer *imageBuffer;
-     DMImage *image, *bindimage;
-     Texture texture, bindTexture;
-     DMDrawBuffer *drawBuffer;
-     DMDrawVertexFlat *vboVertex = null;
-#if defined(_GLES) || defined(_GLES2)
-     DMDrawVertexFlat *vboStorage = null;
-#endif
-     DMProgram *program;
-
-     ERRORCHECK();
-
-     drawBarrierIndex = 0;
-     orderBarrierMask = drawBarrierIndex << DM_BARRIER_ORDER_SHIFT;
-     if(imageBufferCount)
-     {
-        // Sort by image type and texture, minimize state changes
-        dmSortImages( this.imageBuffer, imageBufferTmp, imageBufferCount, (uint32)( (intptr_t)this.imageBuffer >> 4 ) );
-
-        // Fill a drawBuffer, write vertex and texcoords
-        drawBuffer = &this.drawBuffer[drawBufferIndex];
-        drawBufferIndex = ( drawBufferIndex + 1 ) % DM_CONTEXT_DRAW_BUFFER_COUNT;
-        glBindBuffer( GL_ARRAY_BUFFER, drawBuffer->vbo );
-#if defined(_GLES) || defined(_GLES2)
-        vboVertex = vboStorage = new DMDrawVertexFlat[drawBuffer->vertexAlloc * 1];
-#else
-        vboVertex = glMapBuffer( GL_ARRAY_BUFFER, GL_WRITE_ONLY );
-#endif
-        vertexCount = 0;
-
-        glActiveTexture( GL_TEXTURE0 );
-        glBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA );
-        glDisable( GL_BLEND );
-        GLSetupLighting(false);
-
-      #if DM_RENDER_IMAGE_DEBUG
-      printf( " Flush %d images\n", (int)imageBufferCount );
-      #endif
-
-        bindimage = 0;
-        bindTexture = 0;
-        stateBlend = 0;
-        programIndex = -1;
-        program = 0;
-        imageBuffer = this.imageBuffer;
-        for( index = 0 ; index < imageBufferCount ; index++, imageBuffer++ )
-        {
-          image = imageBuffer->image;
-          texture = image->texture;
-
-          flushflag = 0;
-          if( image != bindimage )
-          {
-            if( stateBlend != image->flags.blending )
-              flushflag = 1;
-            if( texture != bindTexture )
-              flushflag = 1;
-          }
-          if( vertexCount >= ( drawBuffer->vertexAlloc - 6 ) )
-            flushflag = 1;
-
-          if( flushflag )
-          {
-            if( vertexCount )
-            {
-#if defined(_GLES) || defined(_GLES2)
-              glBufferData( GL_ARRAY_BUFFER, drawBuffer->vertexAlloc * sizeof(DMDrawVertexFlat), vboStorage, GL_DYNAMIC_DRAW );
-#else
-              glUnmapBuffer( GL_ARRAY_BUFFER );
-#endif
-              // Flush font manager texture updates
-              flush( );
-              // Render buffered images
-              flushRenderDrawBufferArchaic( drawBuffer, program, vertexCount );
-              drawBuffer = &this.drawBuffer[drawBufferIndex];
-              drawBufferIndex = ( drawBufferIndex + 1 ) % DM_CONTEXT_DRAW_BUFFER_COUNT;
-              glBindBuffer( GL_ARRAY_BUFFER, drawBuffer->vbo );
-#if defined(_GLES) || defined(_GLES2)
-              vboVertex = vboStorage;
-#else
-              vboVertex = glMapBuffer( GL_ARRAY_BUFFER, GL_WRITE_ONLY );
-#endif
-              vertexCount = 0;
-            }
+      drawBarrierIndex = 0;
+      orderBarrierMask = 0;
 
-            if( stateBlend != ( image->flags.blending ) )
-            {
-              stateBlend = image->flags.blending;
-              ( stateBlend ? glEnable : glDisable )( GL_BLEND );
-      #if DM_RENDER_IMAGE_DEBUG
-      printf( "  Switch blending %d\n", stateBlend != false );
-      #endif
-            }
-            if( programIndex != image->programIndex )
-            {
-              programIndex = image->programIndex;
-              program = flushUseProgram( programIndex );
-            }
-            if( texture != bindTexture )
-            {
-              bindTexture = texture;
-              glBindTexture( GL_TEXTURE_2D, bindTexture.glTex );
-      #if DM_RENDER_IMAGE_DEBUG
-      printf( "  Switch to texture 0x%x\n", (int)texture.orderMask );
-      #endif
-            }
-            bindimage = image;
-          }
-
-      #if DM_RENDER_IMAGE_DEBUG
-      printf( "   Render image at %d %d, order 0x%x, texture %p\n", (int)imageBuffer->offsetx, (int)imageBuffer->offsety, (int)imageBuffer->orderindex, texture );
-      #endif
-
-      #if DM_ENABLE_IMAGE_ROTATION
-          angsin = (float)imageBuffer->angsin * (1.0f/DM_IMAGE_ROTATION_NORMFACTOR);
-          angcos = (float)imageBuffer->angcos * (1.0f/DM_IMAGE_ROTATION_NORMFACTOR);
-          sizex = (float)imageBuffer->sizex;
-          sizey = (float)imageBuffer->sizey;
-          vx0 = (float)imageBuffer->offsetx * (1.0f/DM_VERTEX_NORMFACTOR);
-          vy0 = (float)imageBuffer->offsety * (1.0f/DM_VERTEX_NORMFACTOR);
-          vx1 = vx0 + ( angcos * sizex );
-          vy1 = vy0 + ( angsin * sizex );
-          vx2 = vx0 - ( angsin * sizey );
-          vy2 = vy0 + ( angcos * sizey );
-          vx3 = vx0 + ( angcos * sizex ) - ( angsin * sizey );
-          vy3 = vy0 + ( angsin * sizex ) + ( angcos * sizey );
-      #else
-          vx0 = (float)imageBuffer->offsetx * (1.0f/DM_VERTEX_NORMFACTOR);
-          vy0 = (float)imageBuffer->offsety * (1.0f/DM_VERTEX_NORMFACTOR);
-          vx3 = vx0 + (float)( imageBuffer->sizex );
-          vy3 = vy0 + (float)( imageBuffer->sizey );
-          vx1 = vx3;
-          vy1 = vy0;
-          vx2 = vx0;
-          vy2 = vy3;
-      #endif
-
-          tx0 = (float)( image->srcx ) * texture.widthinv;
-          ty0 = (float)( image->srcy ) * texture.heightinv;
-          tx1 = (float)( image->srcx + image->sizex ) * texture.widthinv;
-          ty1 = (float)( image->srcy + image->sizey ) * texture.heightinv;
-
-          // Write data to VBO
-          vboVertex[0].vertex[0] = vx3;
-          vboVertex[0].vertex[1] = vy3;
-          vboVertex[0].texcoord0[0] = tx1;
-          vboVertex[0].texcoord0[1] = ty1;
-          vboVertex[0].color = imageBuffer->color;
-      #if DM_ENABLE_EXT_COLOR
-          vboVertex[0].extcolor = imageBuffer->extcolor;
-      #endif
-          vboVertex[1].vertex[0] = vx1;
-          vboVertex[1].vertex[1] = vy1;
-          vboVertex[1].texcoord0[0] = tx1;
-          vboVertex[1].texcoord0[1] = ty0;
-          vboVertex[1].color = imageBuffer->color;
-      #if DM_ENABLE_EXT_COLOR
-          vboVertex[1].extcolor = imageBuffer->extcolor;
-      #endif
-          vboVertex[2].vertex[0] = vx2;
-          vboVertex[2].vertex[1] = vy2;
-          vboVertex[2].texcoord0[0] = tx0;
-          vboVertex[2].texcoord0[1] = ty1;
-          vboVertex[2].color = imageBuffer->color;
-      #if DM_ENABLE_EXT_COLOR
-          vboVertex[2].extcolor = imageBuffer->extcolor;
-      #endif
-          vboVertex[3].vertex[0] = vx0;
-          vboVertex[3].vertex[1] = vy0;
-          vboVertex[3].texcoord0[0] = tx0;
-          vboVertex[3].texcoord0[1] = ty0;
-          vboVertex[3].color = imageBuffer->color;
-      #if DM_ENABLE_EXT_COLOR
-          vboVertex[3].extcolor = imageBuffer->extcolor;
-      #endif
-          vboVertex[4].vertex[0] = vx2;
-          vboVertex[4].vertex[1] = vy2;
-          vboVertex[4].texcoord0[0] = tx0;
-          vboVertex[4].texcoord0[1] = ty1;
-          vboVertex[4].color = imageBuffer->color;
-      #if DM_ENABLE_EXT_COLOR
-          vboVertex[4].extcolor = imageBuffer->extcolor;
-      #endif
-          vboVertex[5].vertex[0] = vx1;
-          vboVertex[5].vertex[1] = vy1;
-          vboVertex[5].texcoord0[0] = tx1;
-          vboVertex[5].texcoord0[1] = ty0;
-          vboVertex[5].color = imageBuffer->color;
-      #if DM_ENABLE_EXT_COLOR
-          vboVertex[5].extcolor = imageBuffer->extcolor;
-      #endif
-
-          vboVertex += 6;
-          vertexCount += 6;
-        }
-
-#if defined(_GLES) || defined(_GLES2) // TODO:
-        glBufferData( GL_ARRAY_BUFFER, drawBuffer->vertexAlloc * sizeof(DMDrawVertexFlat), vboStorage, GL_DYNAMIC_DRAW );
-        delete vboStorage;
-#else
-        glUnmapBuffer( GL_ARRAY_BUFFER );
-#endif
+      if(imageBufferCount)
+      {
+         bool stateBlend = true;
+#if ENABLE_GL_SHADERS
+         int swizzleMode = 0;
+#endif
+         int vertexCount = 0;
+         int index;
+         DMImageBuffer *imageBuffer = imageBuffers;
+         DMImage *bindImage = null;
+         Texture bindTexture = null;
+         DMDrawBuffer *drawBuffer;
+         DMDrawVertex *vboVertex = null;
+         ColorAlpha color = 0;
+   #if !ENABLE_GL_MAPBUF
+         DMDrawVertex *vboStorage = null;
+   #endif
 
-        // Flush font manager texture updates
-        flush();
+         ERRORCHECK();
 
-        // Render buffered images
-        flushRenderDrawBufferArchaic( drawBuffer, program, vertexCount );
-        imageBufferCount = 0;
+         glabCurArrayBuffer = 0;
 
-        ERRORCHECK();
+         GLFlushMatrices();
 
-     }
-   }
-#endif
+         glDisable(GL_DEPTH_TEST);
+         glDisable(GL_CULL_FACE);
+         GLSetupFog(false);
+         GLSetupTexturing(true);
+         GLSetupLighting(false);
+         GLEnableClientState(VERTICES);
+         GLEnableClientState(TEXCOORDS);
+         glEnable(GL_BLEND);
 
-#ifdef SHADERS
-   static void flushRenderDrawBuffer( DMDrawBuffer drawBuffer, DMProgram program, int vertexCount )
-   {
-      glabCurArrayBuffer = 0;
+         // Sort by image type and texture, minimize state changes
+         dmSortImages( imageBuffers, imageBuffersTmp, imageBufferCount, (uint32)( (uintptr)imageBuffers >> 4 ) );
 
-      glBindBuffer( GL_ARRAY_BUFFER, drawBuffer.vbo );
-      if( program.vertexloc != -1 )
-      {
-         glEnableVertexAttribArray( program.vertexloc );
-         glVertexAttribPointer( program.vertexloc, 2, GL_SHORT, GL_FALSE, sizeof(DMDrawVertex), (void *)OFFSET(DMDrawVertex,vertex) );
-      }
-      if( program.texcoord0loc != -1 )
-      {
-         glEnableVertexAttribArray( program.texcoord0loc );
-         glVertexAttribPointer( program.texcoord0loc, 2, GL_SHORT, GL_FALSE, sizeof(DMDrawVertex), (void *)OFFSET(DMDrawVertex,texcoord0) );
-      }
-      if( program.colorloc != -1 )
-      {
-         glEnableVertexAttribArray( program.colorloc );
-         glVertexAttribPointer( program.colorloc, 4, GL_UNSIGNED_BYTE, GL_TRUE, sizeof(DMDrawVertex), (void *)OFFSET(DMDrawVertex,color) );
-      }
+         // Fill a drawBuffer, write vertex and texcoords
+         drawBuffer = &drawBuffers[drawBufferIndex++];
+         drawBufferIndex %= DRAW_BUFFER_COUNT;
+         glBindBuffer( GL_ARRAY_BUFFER, drawBuffer->vbo.buffer );
+         glBindBuffer( GL_ELEMENT_ARRAY_BUFFER, 0 );
 
-   #if DM_ENABLE_EXT_COLOR
-      if( program.extcolorloc != -1 )
-      {
-         glEnableVertexAttribArray( program.extcolorloc );
-         glVertexAttribPointer( program.extcolorloc, 4, GL_UNSIGNED_BYTE, GL_TRUE, sizeof(DMDrawVertex), (void *)OFFSET(DMDrawVertex,extcolor) );
-      }
-   #endif
+#if ENABLE_GL_MAPBUF
+         vboVertex = glMapBuffer( GL_ARRAY_BUFFER, GL_WRITE_ONLY );
+#else
+         vboVertex = vboStorage = new DMDrawVertex[drawBuffer->vertexAlloc];
+#endif
 
-      glDrawArrays( GL_TRIANGLES, 0, vertexCount );
+         for(index = 0; index < imageBufferCount; index++, imageBuffer++)
+         {
+            DMImage * image = &imageList[imageBuffer->image];
+            Texture texture = image->texture;
+            short tx0 = (short)( (int)image->srcx * texture.widthinv  * DM_TEXCOORD_NORMFACTOR);
+            short ty0 = (short)( (int)image->srcy * texture.heightinv * DM_TEXCOORD_NORMFACTOR);
+            short tx1 = (short)(( (int)image->srcx + image->sizex ) * texture.widthinv  * DM_TEXCOORD_NORMFACTOR);
+            short ty1 = (short)(( (int)image->srcy + image->sizey ) * texture.heightinv * DM_TEXCOORD_NORMFACTOR);
+            short angsin = imageBuffer->angsin, angcos = imageBuffer->angcos;
+            short sizex = imageBuffer->sizex, sizey = imageBuffer->sizey;
+            short vx0 = imageBuffer->offsetx;
+            short vy0 = imageBuffer->offsety;
+            short vx1 = (short)(vx0 + ((int)angcos * sizex * DM_VERTEX_NORMFACTOR / DM_IMAGE_ROTATION_NORMFACTOR));
+            short vy1 = (short)(vy0 + ((int)angsin * sizex * DM_VERTEX_NORMFACTOR / DM_IMAGE_ROTATION_NORMFACTOR));
+            short vx2 = (short)(vx0 - ((int)angsin * sizey * DM_VERTEX_NORMFACTOR / DM_IMAGE_ROTATION_NORMFACTOR));
+            short vy2 = (short)(vy0 + ((int)angcos * sizey * DM_VERTEX_NORMFACTOR / DM_IMAGE_ROTATION_NORMFACTOR));
+            short vx3 = (short)(vx0 + (((int)angcos * sizex - (int)angsin * sizey) * DM_VERTEX_NORMFACTOR / DM_IMAGE_ROTATION_NORMFACTOR));
+            short vy3 = (short)(vy0 + (((int)angsin * sizex + (int)angcos * sizey) * DM_VERTEX_NORMFACTOR / DM_IMAGE_ROTATION_NORMFACTOR));
+            bool flushFlag =
+               (imageBuffer->color != color) ||
+               (image != bindImage && (stateBlend != image->flags.blending || texture != bindTexture
+#if ENABLE_GL_SHADERS
+               || (glCaps_shaders && swizzleMode != image->flags.swizzle)
+#endif
+               )) ||
+               (vertexCount >= drawBuffer->vertexAlloc - 6);
+
+            if(flushFlag)
+            {
+               if(vertexCount)
+               {
+#if ENABLE_GL_MAPBUF
+                  glUnmapBuffer( GL_ARRAY_BUFFER );
+#else
+                  glBufferSubData( GL_ARRAY_BUFFER, 0, vertexCount * sizeof(DMDrawVertex), vboStorage );
+#endif
+                  // Flush font manager texture updates
+                  flush();
+
+                  // Render buffered images
+                  flushRenderDrawBuffer( drawBuffer, vertexCount );
+                  drawBuffer = &drawBuffers[drawBufferIndex++];
+                  drawBufferIndex %= DRAW_BUFFER_COUNT;
+                  glBindBuffer( GL_ARRAY_BUFFER, drawBuffer->vbo.buffer );
+#if ENABLE_GL_MAPBUF
+                  vboVertex = glMapBuffer( GL_ARRAY_BUFFER, GL_WRITE_ONLY );
+#else
+                  vboVertex = vboStorage;
+#endif
+                  vertexCount = 0;
+               }
+
+               if(color != imageBuffer->color)
+               {
+                  color = imageBuffer->color;
+                  GLColor4ub(color.color.r, color.color.g, color.color.b, color.a);
+               }
+               if( stateBlend != image->flags.blending)
+               {
+                  stateBlend = image->flags.blending;
+                  ( stateBlend ? glEnable : glDisable )( GL_BLEND );
+               }
+#if ENABLE_GL_SHADERS
+               if( swizzleMode != image->flags.swizzle)
+               {
+                  swizzleMode = image->flags.swizzle;
+                  if(glCaps_shaders)
+                     shader_swizzle( swizzleMode );
+               }
+#endif
+               if( texture != bindTexture )
+               {
+                  bindTexture = texture;
+                  glBindTexture( GL_TEXTURE_2D, bindTexture.glTex );
+               }
+               bindImage = image;
+            }
 
-      if( program.vertexloc != -1 )
-         glDisableVertexAttribArray( program.vertexloc );
-      if( program.texcoord0loc != -1 )
-         glDisableVertexAttribArray( program.texcoord0loc );
-      if( program.colorloc != -1 )
-         glDisableVertexAttribArray( program.colorloc );
+            // Write data to VBO
+            // TODO: write vertex/texcoord all at once with SSE
+            vboVertex[0] = { vx3, vy3, tx1, ty1 };
+            vboVertex[1] = { vx1, vy1, tx1, ty0 };
+            vboVertex[2] = { vx2, vy2, tx0, ty1 };
+            vboVertex[3] = { vx0, vy0, tx0, ty0 };
+            vboVertex[4] = { vx2, vy2, tx0, ty1 };
+            vboVertex[5] = { vx1, vy1, tx1, ty0 };
+            vboVertex += 6;
+            vertexCount += 6;
+
+            glBindBuffer( GL_ARRAY_BUFFER, drawBuffer->vbo.buffer );
+         }
 
-   #if DM_FLUSH_EACH_RENDER_DRAW_BUFFER
-      glFlush();
-   #endif
-   }
+#if ENABLE_GL_MAPBUF
+         glUnmapBuffer( GL_ARRAY_BUFFER );
+#else
+         glBufferSubData( GL_ARRAY_BUFFER, 0, vertexCount * sizeof(DMDrawVertex), vboStorage );
+         delete vboStorage;
 #endif
 
-#ifdef SHADERS
-   static void flushDrawImages( )
-   {
-      int index, stateblend, vertexcount, flushflag, programIndex;
-      float vx0, vx1, vx2, vx3, vy0, vy1, vy2, vy3;
-      #if DM_ENABLE_IMAGE_ROTATION
-      float angsin, angcos, sizex, sizey;
-      #endif
-      float tx0, tx1, ty0, ty1;
-      DMImageBuffer *imageBuffer;
-      DMImage *image, *bindimage;
-      Texture texture, bindtexture;
-      DMDrawBuffer *drawBuffer;
-      DMDrawVertex *vboVertex = null;
-      DMProgram *program;
-
-      glabCurArrayBuffer = 0;
-
-      ERRORCHECK();
-
-      this.drawBarrierIndex = 0;
-      orderBarrierMask = drawBarrierIndex << DM_BARRIER_ORDER_SHIFT;
-      if( imageBufferCount )
-      {
-         /* Sort by image type and texture, minimize state changes */
-         dmSortImages( this.imageBuffer, this.imageBufferTmp, imageBufferCount, (uint32)( (uintptr)this.imageBuffer >> 4 ) );
+         // Flush font manager texture updates
+         flush();
 
-         /* Fill a drawBuffer, write vertex and texcoords */
-         drawBuffer = &this.drawBuffer[this.drawBufferIndex];
-         this.drawBufferIndex = ( this.drawBufferIndex + 1 ) % DM_CONTEXT_DRAW_BUFFER_COUNT;
-         glBindBuffer( GL_ARRAY_BUFFER, drawBuffer->vbo );
+         // Render buffered images
+         flushRenderDrawBuffer( drawBuffer, vertexCount );
+         imageBufferCount = 0;
 
-#if !defined(_GLES) && !defined(_GLES2) // TODO:
-         vboVertex = glMapBuffer( GL_ARRAY_BUFFER, GL_WRITE_ONLY );
-#endif
-         vertexcount = 0;
-
-         glActiveTexture( GL_TEXTURE0 );
-         glBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA );
-         glDisable( GL_BLEND );
-
-         #if DM_RENDER_IMAGE_DEBUG
-         printf( " Flush %d images\n", (int)imageBufferCount );
-         #endif
-
-         bindimage = 0;
-         bindtexture = 0;
-         stateblend = 0;
-         programIndex = -1;
-         program = 0;
-         imageBuffer = this.imageBuffer;
-         for( index = 0 ; index < imageBufferCount ; index++, imageBuffer++ )
-         {
-          image = imageBuffer->image;
-          texture = image->texture;
-
-          flushflag = 0;
-          if( image != bindimage )
-          {
-            if( stateblend != ( image->flags.blending ) )
-              flushflag = 1;
-            if( texture != bindtexture )
-              flushflag = 1;
-          }
-          if( vertexcount >= ( drawBuffer->vertexAlloc - 6 ) )
-            flushflag = 1;
-
-          if( flushflag )
-          {
-            if( vertexcount )
-            {
-#if !defined(_GLES) && !defined(_GLES2)  // TODO:
-              glUnmapBuffer( GL_ARRAY_BUFFER );
-#endif
-              // Flush font manager texture updates
-              flush();
-
-              // Render buffered images
-              flushRenderDrawBuffer( drawBuffer, program, vertexcount );
-              drawBuffer = &this.drawBuffer[this.drawBufferIndex];
-              this.drawBufferIndex = ( this.drawBufferIndex + 1 ) % DM_CONTEXT_DRAW_BUFFER_COUNT;
-              glBindBuffer( GL_ARRAY_BUFFER, drawBuffer->vbo );
-#if !defined(_GLES) && !defined(_GLES2)   // TODO:
-              vboVertex = glMapBuffer( GL_ARRAY_BUFFER, GL_WRITE_ONLY );
-#endif
-              vertexcount = 0;
-            }
+         ERRORCHECK();
 
-            if( stateblend != ( image->flags.blending ) )
-            {
-              stateblend = image->flags.blending;
-              ( stateblend ? glEnable : glDisable )( GL_BLEND );
-            #if DM_RENDER_IMAGE_DEBUG
-               printf( "  Switch blending %d\n", ( stateblend != 0 ) );
-            #endif
-            }
-            if( programIndex != image->programIndex )
-            {
-              programIndex = image->programIndex;
-              program = flushUseProgram( programIndex );
-            }
-            if( texture != bindtexture )
-            {
-              bindtexture = texture;
-              glBindTexture( GL_TEXTURE_2D, bindtexture.glTex );
-      #if DM_RENDER_IMAGE_DEBUG
-              printf( "  Switch to texture 0x%x\n", (int)texture.orderMask );
-      #endif
-            }
-            bindimage = image;
-          }
-
-         #if DM_RENDER_IMAGE_DEBUG
-         printf( "   Render image at %d %d, order 0x%x, texture %p\n", (int)imageBuffer->offsetx, (int)imageBuffer->offsety, (int)imageBuffer->orderindex, texture );
-         #endif
-
-      #if DM_ENABLE_IMAGE_ROTATION
-          /* FIXME TODO: Don't go through float, compute texcoord integers directly */
-          angsin = (float)imageBuffer->angsin * (1.0f/DM_IMAGE_ROTATION_NORMFACTOR);
-          angcos = (float)imageBuffer->angcos * (1.0f/DM_IMAGE_ROTATION_NORMFACTOR);
-          sizex = (float)imageBuffer->sizex;
-          sizey = (float)imageBuffer->sizey;
-          vx0 = (float)imageBuffer->offsetx * (1.0f/DM_VERTEX_NORMFACTOR);
-          vy0 = (float)imageBuffer->offsety * (1.0f/DM_VERTEX_NORMFACTOR);
-          vx1 = vx0 + ( angcos * sizex );
-          vy1 = vy0 + ( angsin * sizex );
-          vx2 = vx0 - ( angsin * sizey );
-          vy2 = vy0 + ( angcos * sizey );
-          vx3 = vx0 + ( angcos * sizex ) - ( angsin * sizey );
-          vy3 = vy0 + ( angsin * sizex ) + ( angcos * sizey );
-      #else
-          /* FIXME TODO: Don't go through float, compute texcoord integers directly */
-          vx0 = (float)imageBuffer->offsetx * (1.0f/DM_VERTEX_NORMFACTOR);
-          vy0 = (float)imageBuffer->offsety * (1.0f/DM_VERTEX_NORMFACTOR);
-          vx3 = vx0 + (float)( imageBuffer->sizex );
-          vy3 = vy0 + (float)( imageBuffer->sizey );
-          vx1 = vx3;
-          vy1 = vy0;
-          vx2 = vx0;
-          vy2 = vy3;
-      #endif
-
-          /* FIXME TODO: Don't go through float, compute texcoord integers directly */
-          tx0 = (float)( image->srcx ) * texture.widthinv;
-          ty0 = (float)( image->srcy ) * texture.heightinv;
-          tx1 = (float)( image->srcx + image->sizex ) * texture.widthinv;
-          ty1 = (float)( image->srcy + image->sizey ) * texture.heightinv;
-
-          /* Write data to VBO */
-          /* TODO: write vertex/texcoord all at once with SSE */
-          vboVertex[0].vertex[0] = (short)( vx3 * DM_VERTEX_NORMFACTOR );
-          vboVertex[0].vertex[1] = (short)( vy3 * DM_VERTEX_NORMFACTOR );
-          vboVertex[0].texcoord0[0] = (short)( tx1 * DM_TEXCOORD_NORMFACTOR );
-          vboVertex[0].texcoord0[1] = (short)( ty1 * DM_TEXCOORD_NORMFACTOR );
-          vboVertex[0].color = imageBuffer->color;
-          vboVertex[0].extcolor = imageBuffer->extcolor;
-          vboVertex[1].vertex[0] = (short)( vx1 * DM_VERTEX_NORMFACTOR );
-          vboVertex[1].vertex[1] = (short)( vy1 * DM_VERTEX_NORMFACTOR );
-          vboVertex[1].texcoord0[0] = (short)( tx1 * DM_TEXCOORD_NORMFACTOR );
-          vboVertex[1].texcoord0[1] = (short)( ty0 * DM_TEXCOORD_NORMFACTOR );
-          vboVertex[1].color = imageBuffer->color;
-          vboVertex[1].extcolor = imageBuffer->extcolor;
-          vboVertex[2].vertex[0] = (short)( vx2 * DM_VERTEX_NORMFACTOR );
-          vboVertex[2].vertex[1] = (short)( vy2 * DM_VERTEX_NORMFACTOR );
-          vboVertex[2].texcoord0[0] = (short)( tx0 * DM_TEXCOORD_NORMFACTOR );
-          vboVertex[2].texcoord0[1] = (short)( ty1 * DM_TEXCOORD_NORMFACTOR );
-          vboVertex[2].color = imageBuffer->color;
-          vboVertex[2].extcolor = imageBuffer->extcolor;
-          vboVertex[3].vertex[0] = (short)( vx0 * DM_VERTEX_NORMFACTOR );
-          vboVertex[3].vertex[1] = (short)( vy0 * DM_VERTEX_NORMFACTOR );
-          vboVertex[3].texcoord0[0] = (short)( tx0 * DM_TEXCOORD_NORMFACTOR );
-          vboVertex[3].texcoord0[1] = (short)( ty0 * DM_TEXCOORD_NORMFACTOR );
-          vboVertex[3].color = imageBuffer->color;
-          vboVertex[3].extcolor = imageBuffer->extcolor;
-          vboVertex[4].vertex[0] = (short)( vx2 * DM_VERTEX_NORMFACTOR );
-          vboVertex[4].vertex[1] = (short)( vy2 * DM_VERTEX_NORMFACTOR );
-          vboVertex[4].texcoord0[0] = (short)( tx0 * DM_TEXCOORD_NORMFACTOR );
-          vboVertex[4].texcoord0[1] = (short)( ty1 * DM_TEXCOORD_NORMFACTOR );
-          vboVertex[4].color = imageBuffer->color;
-          vboVertex[4].extcolor = imageBuffer->extcolor;
-          vboVertex[5].vertex[0] = (short)( vx1 * DM_VERTEX_NORMFACTOR );
-          vboVertex[5].vertex[1] = (short)( vy1 * DM_VERTEX_NORMFACTOR );
-          vboVertex[5].texcoord0[0] = (short)( tx1 * DM_TEXCOORD_NORMFACTOR );
-          vboVertex[5].texcoord0[1] = (short)( ty0 * DM_TEXCOORD_NORMFACTOR );
-          vboVertex[5].color = imageBuffer->color;
-          vboVertex[5].extcolor = imageBuffer->extcolor;
-
-          vboVertex += 6;
-          vertexcount += 6;
-        }
-
-#if !defined(_GLES) && !defined(_GLES2)      // TODO:
-        glUnmapBuffer( GL_ARRAY_BUFFER );
+         GLDisableClientState(TEXCOORDS);
+         GLSetupTexturing(false);
+#if ENABLE_GL_SHADERS
+         if(glCaps_shaders)
+            shader_swizzle(0);
 #endif
-        // Flush font manager texture updates
-        flush();
-        // Render buffered images
-        flushRenderDrawBuffer( drawBuffer, program, vertexcount );
-        imageBufferCount = 0;
 
-        ERRORCHECK();
+         if(glCaps_vertexBuffer)
+         {
+            glBindBuffer( GL_ARRAY_BUFFER, 0 );
+            glabCurArrayBuffer = 0;
+         }
       }
    }
-#endif
 
 public:
 
@@ -1185,59 +375,26 @@ public:
 
    virtual void flush();
 
-   bool init( DrawManagerFlags flags )
+   bool init()
    {
       int drawBufferIndex;
-      DMDrawBuffer *drawBuffer;
-      uint vertexSize;
+      uint vertexSize = sizeof(DMDrawVertex);
 
       imageBufferCount = 0;
       imageBufferSize = 4096;
-      imageBuffer = new DMImageBuffer[imageBufferSize];
-      imageBufferTmp = new DMImageBuffer[imageBufferSize];
-
-      this.flags = flags;
+      imageBuffers = new DMImageBuffer[imageBufferSize];
+      imageBuffersTmp = new DMImageBuffer[imageBufferSize];
 
-      if( flags.prehistoricOpenGL )
-         vertexSize = sizeof(DMDrawVertexFlat);
-      else
+      for( drawBufferIndex = 0 ; drawBufferIndex < DRAW_BUFFER_COUNT ; drawBufferIndex++ )
       {
-#ifdef SHADERS
-         DMProgram *program;
-         int programIndex;
-         for( programIndex = 0 ; programIndex < DM_PROGRAM_COUNT ; programIndex++ )
-         {
-            program = &shaderPrograms[ programIndex ];
-            program->flags = 0;
-            program->lastUpdateCount = -1;
-         }
-         program = &shaderPrograms[ DM_PROGRAM_NORMAL ];
-         if( !( dmCreateProgram( program, dmVertexShaderNormal, dmFragmentShaderNormal, 0 ) ) )
-            return false;
-         program = &shaderPrograms[ DM_PROGRAM_ALPHABLEND ];
-         if( !( dmCreateProgram( program, dmVertexShaderAlpha, dmFragmentShaderAlpha, 0 ) ) )
-            return false;
-         program = &shaderPrograms[ DM_PROGRAM_ALPHABLEND_INTENSITY ];
-         if( !( dmCreateProgram( program, dmVertexShaderAlphaIntensity, dmFragmentShaderAlphaIntensity, 0 ) ) )
-            return false;
-        program = &shaderPrograms[ DM_PROGRAM_ALPHABLEND_INTENSITY_EXTCOLOR ];
-        if( !( dmCreateProgram( program, dmVertexShaderAlphaIntensityExtColor, dmFragmentShaderAlphaIntensityExtColor, 0 ) ) )
-            return false;
-         // glUseProgram( 0 );
-         vertexSize = sizeof(DMDrawVertex);
-#endif
-      }
-
-      for( drawBufferIndex = 0 ; drawBufferIndex < DM_CONTEXT_DRAW_BUFFER_COUNT ; drawBufferIndex++ )
-      {
-         drawBuffer = &this.drawBuffer[drawBufferIndex];
+         DMDrawBuffer *drawBuffer = &drawBuffers[drawBufferIndex];
          drawBuffer->glType = GL_FLOAT;
          drawBuffer->vertexCount = 0;
-         drawBuffer->vertexAlloc = DM_CONTEXT_DRAW_BUFFER_VERTEX_ALLOC;
-         if(vboAvailable)
+         drawBuffer->vertexAlloc = DRAW_BUFFER_VERTEX_ALLOC;
+         if(glCaps_vertexBuffer)
          {
-            glGenBuffers( 1, &drawBuffer->vbo );
-            glBindBuffer( GL_ARRAY_BUFFER, drawBuffer->vbo );
+            glGenBuffers( 1, &drawBuffer->vbo.buffer );
+            glBindBuffer( GL_ARRAY_BUFFER, drawBuffer->vbo.buffer );
             glBufferData( GL_ARRAY_BUFFER, drawBuffer->vertexAlloc * vertexSize, 0, GL_DYNAMIC_DRAW );
          }
          drawBuffer->vertexBuffer = new byte[drawBuffer->vertexAlloc * vertexSize];
@@ -1245,8 +402,11 @@ public:
 
       updateCount = 0;
 
-      glabCurArrayBuffer = 0;
-
+      if(glCaps_vertexBuffer)
+      {
+         glBindBuffer( GL_ARRAY_BUFFER, 0 );
+         glabCurArrayBuffer = 0;
+      }
       return true;
    }
 
@@ -1255,251 +415,86 @@ public:
       end();
    }
 
-   void end( )
+   void end()
    {
       int i;
 
-      for( i = 0 ; i < DM_CONTEXT_DRAW_BUFFER_COUNT ; i++ )
+      for( i = 0 ; i < DRAW_BUFFER_COUNT ; i++ )
       {
-         DMDrawBuffer *db = &drawBuffer[i];
-         if(db->vbo)
-            glDeleteBuffers( 1, &db->vbo );
+         DMDrawBuffer *db = &drawBuffers[i];
+         if(db->vbo.buffer)
+            glDeleteBuffers( 1, &db->vbo.buffer );
          delete db->vertexBuffer;
       }
-
-      // TODO: Destroy the shaders!
-      delete imageBuffer;
-      delete imageBufferTmp;
+      delete imageBuffers;
+      delete imageBuffersTmp;
+      delete imageList;
    }
 
-   void ready( int viewportwidth, int viewportheight )
+   void ready( int viewportWidth, int viewportHeight )
    {
-      int mindex;
-      float norminv;
-#ifdef SHADERS
-      if(!flags.prehistoricOpenGL && !prevProgram)
-         glGetIntegerv(GL_CURRENT_PROGRAM, (GLint *)&prevProgram);
-#endif
-      // while(glGetError());
-
-      // ERRORCHECK();
+      float norminv = 1.0f / DM_VERTEX_NORMFACTOR;
+      float texinv = 1.0f / DM_TEXCOORD_NORMFACTOR;
 
-      // Save OpenGL state
-      // FIXME: no glPushAttrib() in core profile
-#if !defined(_GLES) && !defined(_GLES2)      // TODO:
-      glPushClientAttrib( GL_CLIENT_ALL_ATTRIB_BITS );
-      glPushAttrib( GL_ALL_ATTRIB_BITS );
-#endif
+      GLMatrixMode(MatrixMode::texture);
+      GLScalef(texinv,texinv,1);
 
-      // Prepare rendering pass
+      GLMatrixMode(MatrixMode::projection);
+      GLLoadIdentity();
       if(renderingFlipped)
-         matrixOrtho( matrix, 0.0, (float)viewportwidth, 0.0, (float)viewportheight, -1.0f, 1.0 );
+         GLOrtho( 0.0, (float)viewportWidth, 0.0, (float)viewportHeight, -1.0f, 1.0 );
       else
-         matrixOrtho( matrix, 0.0, (float)viewportwidth, (float)viewportheight, 0.0, -1.0f, 1.0 );
-      norminv = 1.0f / DM_VERTEX_NORMFACTOR;
-      for( mindex = 0 ; mindex < 12 ; mindex += 4 )
-      {
-        matrix[mindex+0] *= norminv;
-        matrix[mindex+1] *= norminv;
-        matrix[mindex+2] *= norminv;
-      }
+         GLOrtho( 0.0, (float)viewportWidth, (float)viewportHeight, 0.0, -1.0f, 1.0 );
+      GLScalef(norminv, norminv, norminv);
+
+      GLMatrixMode(MatrixMode::modelView);
+      GLLoadIdentity();
+      GLScalef(1,1,1);
+
       drawBarrierIndex = 0;
-      orderBarrierMask = drawBarrierIndex << DM_BARRIER_ORDER_SHIFT;
       orderBarrierMask = 0;
 
       updateCount++;
-
-      if(flags.prehistoricOpenGL)
-      {
-         glMatrixMode(MatrixMode::projection);
-         glLoadMatrixf(matrix);
-
-         glMatrixMode(MatrixMode::modelView);
-         glLoadIdentity();
-         glScalef(4,4,4);
-      }
-   }
-
-   void drawImage( DMImage image, int offsetx, int offsety, int sizex, int sizey, uint32 color )
-   {
-     DMImageBuffer *imageBuffer;
-
-     if( image.flags.empty || ( sizex <= 0 ) || ( sizey <= 0 ) )
-       return;
-
-     if( imageBufferCount >= imageBufferSize )
-     {
-       imageBufferSize <<= 1;
-       this.imageBuffer = renew this.imageBuffer DMImageBuffer[imageBufferSize];
-       imageBufferTmp = renew imageBufferTmp DMImageBuffer[imageBufferSize];
-     }
-
-     imageBuffer = &this.imageBuffer[ imageBufferCount ];
-     imageBuffer->image = image;
-     imageBuffer->offsetx = (short)(offsetx << DM_VERTEX_NORMSHIFT);
-     imageBuffer->offsety = (short)(offsety << DM_VERTEX_NORMSHIFT);
-     imageBuffer->sizex = (short)sizex;
-     imageBuffer->sizey = (short)sizey;
-   #if DM_ENABLE_IMAGE_ROTATION
-     imageBuffer->angsin = 0;
-     imageBuffer->angcos = (short)DM_IMAGE_ROTATION_NORMFACTOR;
-   #endif
-     imageBuffer->color = color;
-     imageBuffer->orderindex = image.orderMask | orderBarrierMask;
-
-   #if DM_RENDER_IMAGE_DEBUG
-   printf( "  Queue image at %d %d, order 0x%x\n", (int)imageBuffer->offsetx, (int)imageBuffer->offsety, (int)imageBuffer->orderindex );
-   #endif
-
-     imageBufferCount++;
-   }
-
-   void drawImageExtColor( DMImage image, int offsetx, int offsety, int sizex, int sizey, uint32 color, uint32 extcolor )
-   {
-     DMImageBuffer *imageBuffer;
-
-     if( ( image.flags.empty ) || ( sizex <= 0 ) || ( sizey <= 0 ) )
-       return;
-
-     if( imageBufferCount >= imageBufferSize )
-     {
-       imageBufferSize <<= 1;
-       this.imageBuffer = renew this.imageBuffer DMImageBuffer[imageBufferSize];
-       imageBufferTmp = renew imageBufferTmp DMImageBuffer[imageBufferSize];
-     }
-
-     imageBuffer = &this.imageBuffer[ imageBufferCount ];
-     imageBuffer->image = image;
-     imageBuffer->offsetx = (short)(offsetx << DM_VERTEX_NORMSHIFT);
-     imageBuffer->offsety = (short)(offsety << DM_VERTEX_NORMSHIFT);
-     imageBuffer->sizex = (short)sizex;
-     imageBuffer->sizey = (short)sizey;
-   #if DM_ENABLE_IMAGE_ROTATION
-     imageBuffer->angsin = 0;
-     imageBuffer->angcos = (short)DM_IMAGE_ROTATION_NORMFACTOR;
-   #endif
-     imageBuffer->color = color;
-   #if DM_ENABLE_EXT_COLOR
-     imageBuffer->extcolor = extcolor;
-   #endif
-     imageBuffer->orderindex = image.orderMask | orderBarrierMask;
-
-   #if DM_RENDER_IMAGE_DEBUG
-   printf( "  Queue image at %d %d, order 0x%x\n", (int)imageBuffer->offsetx, (int)imageBuffer->offsety, (int)imageBuffer->orderindex );
-   #endif
-
-     this.imageBufferCount++;
-   }
-
-   void drawImageFloat( DMImage image, float offsetx, float offsety, float sizex, float sizey, float angsin, float angcos, uint32 color )
-   {
-     DMImageBuffer *imageBuffer;
-
-     if( image.flags.empty || sizex <= 0 || sizey <= 0 )
-       return;
-
-     if( imageBufferCount >= imageBufferSize )
-     {
-       imageBufferSize <<= 1;
-       this.imageBuffer = renew this.imageBuffer DMImageBuffer[imageBufferSize];
-       imageBufferTmp = renew imageBufferTmp DMImageBuffer[imageBufferSize];
-     }
-
-     imageBuffer = &this.imageBuffer[ imageBufferCount ];
-     imageBuffer->image = image;
-     imageBuffer->offsetx = (short)roundf(offsetx * DM_VERTEX_NORMFACTOR);
-     imageBuffer->offsety = (short)roundf(offsety * DM_VERTEX_NORMFACTOR);
-     imageBuffer->sizex = (short)sizex;
-     imageBuffer->sizey = (short)sizey;
-   #if DM_ENABLE_IMAGE_ROTATION
-     imageBuffer->angsin = (short)roundf( angsin * DM_IMAGE_ROTATION_NORMFACTOR );
-     imageBuffer->angcos = (short)roundf( angcos * DM_IMAGE_ROTATION_NORMFACTOR );
-   #endif
-     imageBuffer->color = color;
-     imageBuffer->orderindex = image.orderMask | orderBarrierMask;
-
-   #if DM_RENDER_IMAGE_DEBUG
-   printf( "  Queue image at %d %d, order 0x%x\n", (int)imageBuffer->offsetx, (int)imageBuffer->offsety, (int)imageBuffer->orderindex );
-   #endif
-
-     imageBufferCount++;
-   }
-
-   void drawImageFloatExtColor( DMImage image, float offsetx, float offsety, float sizex, float sizey, float angsin, float angcos, uint32 color, uint32 extcolor )
-   {
-     DMImageBuffer *imageBuffer;
-
-     if( ( image.flags.empty ) || ( sizex <= 0 ) || ( sizey <= 0 ) )
-       return;
-
-     if( this.imageBufferCount >= this.imageBufferSize )
-     {
-       imageBufferSize <<= 1;
-       this.imageBuffer = renew this.imageBuffer DMImageBuffer[imageBufferSize];
-       imageBufferTmp = renew imageBufferTmp DMImageBuffer[imageBufferSize];
-     }
-
-     imageBuffer = &this.imageBuffer[ imageBufferCount ];
-     imageBuffer->image = image;
-     imageBuffer->offsetx = (short)roundf( offsetx * DM_VERTEX_NORMFACTOR );
-     imageBuffer->offsety = (short)roundf( offsety * DM_VERTEX_NORMFACTOR );
-     imageBuffer->sizex = (short)sizex;
-     imageBuffer->sizey = (short)sizey;
-   #if DM_ENABLE_IMAGE_ROTATION
-     imageBuffer->angsin = (short)roundf( angsin * DM_IMAGE_ROTATION_NORMFACTOR );
-     imageBuffer->angcos = (short)roundf( angcos * DM_IMAGE_ROTATION_NORMFACTOR );
-   #endif
-     imageBuffer->color = color;
-   #if DM_ENABLE_EXT_COLOR
-     imageBuffer->extcolor = extcolor;
-   #endif
-     imageBuffer->orderindex = image.orderMask | orderBarrierMask;
-
-   #if DM_RENDER_IMAGE_DEBUG
-   printf( "  Queue image at %d %d, order 0x%x\n", (int)imageBuffer->offsetx, (int)imageBuffer->offsety, (int)imageBuffer->orderindex );
-   #endif
-
-     this.imageBufferCount++;
    }
 
-   void flushImages( )
+   void drawImage( int index, float offsetx, float offsety, float angsin, float angcos, ColorAlpha color )
    {
-#if !defined(_GLES2)
-      if(flags.prehistoricOpenGL)
-         flushDrawImagesArchaic();
-#endif
-
-#if defined(SHADERS)
-      if(!flags.prehistoricOpenGL)
-         flushDrawImages( );
-#endif
+      DMImage * image = &imageList[index];
+      float sizex = image->sizex, sizey = image->sizey;
+      if(!image->flags.empty && sizex > 0 && sizey > 0)
+      {
+         if( imageBufferCount >= imageBufferSize )
+         {
+            imageBufferSize <<= 1;
+            imageBuffers = renew imageBuffers DMImageBuffer[imageBufferSize];
+            imageBuffersTmp = renew imageBuffersTmp DMImageBuffer[imageBufferSize];
+         }
+         imageBuffers[ imageBufferCount++ ] =
+         {
+            image = index;
+            offsetx = (short)roundf( offsetx * DM_VERTEX_NORMFACTOR );
+            offsety = (short)roundf( offsety * DM_VERTEX_NORMFACTOR );
+            sizex = (short)sizex;
+            sizey = (short)sizey;
+            angsin = (short)roundf( angsin * DM_IMAGE_ROTATION_NORMFACTOR );
+            angcos = (short)roundf( angcos * DM_IMAGE_ROTATION_NORMFACTOR );
+            color = color;
+            orderIndex = image->orderMask | orderBarrierMask;
+         };
+      }
    }
 
    void finish()
    {
       flushImages();
-
-     if(vboAvailable)
-        glBindBuffer( GL_ARRAY_BUFFER, 0 );
-     glabCurArrayBuffer = 0;
-#ifdef SHADERS
-     if( !flags.prehistoricOpenGL )
-         glUseProgram( prevProgram );
-#endif
-      // Restore OpenGL state
-      // FIXME: no glPushAttrib() in core profile
-#if !defined(_GLES) && !defined(_GLES2)       // TODO:
-      glPopAttrib();
-      glPopClientAttrib();
-#endif
    }
 
    void drawBarrier( )
    {
       drawBarrierIndex++;
-      if( drawBarrierIndex >= ( 1 << DM_BARRIER_ORDER_BITS ) )
+      if(drawBarrierIndex >= ( 1 << DM_BARRIER_ORDER_BITS ))
          flushImages( );
-      orderBarrierMask = drawBarrierIndex << DM_BARRIER_ORDER_SHIFT;
+      orderBarrierMask = { barrier = (1 << DM_BARRIER_ORDER_BITS)-1 };
    }
 
    void clear()
index e9a4085..b153e41 100644 (file)
@@ -6,11 +6,12 @@
 import "LinkList"
 import "File"
 import "FontResource"
+import "FontRenderer"
 
 import "atlasBuilder"
 import "imgDistMap"
 
-#define SHADERS
+#include "glHelpers.h"
 
 #include <math.h>
 
@@ -572,15 +573,8 @@ public class FontManager
      glyph->imageIndex = -1;
      if( renderer.registerImage )
      {
-        if(outlinePass)
-        {
-           renderer.setLayer(3); //DM_LAYER_BELOW);
-        }
-        glyph->imageIndex = renderer.registerImage( gx, gy, glyphareawidth, glyphareaheight );
-        if(outlinePass)
-        {
-           renderer.setLayer(6); //DM_LAYER_NORMAL);
-        }
+        renderer.setLayer(outlinePass ? 3 : 6);
+        glyph->imageIndex = renderer.registerImage( gx, gy, glyphareawidth, glyphareaheight);
      }
 
      // Add char to hash table
@@ -934,14 +928,12 @@ public:
        if( glyph )
        {
          font.addKerning(prevGlyphIndex, glyph, &x, &subpixel );
-#if !defined(SHADERS)
          if(font.processImage)
          {
             FMGlyph *outlineGlyph = getGlyph(font, codepoint, state->size, subpixel, true );
             if(outlineGlyph)
                drawTextGlyph(font, outlineGlyph, x, y, true );
          }
-#endif
          drawTextGlyph(font, glyph, x, y, false );
          addGlyphAdvance( &x, &subpixel, glyph );
        }
@@ -997,14 +989,12 @@ public:
        if( glyph )
        {
          font.addKerning(prevGlyphIndex, glyph, &x, &subpixel );
-#if !defined(SHADERS)
          if(font.processImage)
          {
             FMGlyph *outlineGlyph = getGlyph(font, codepoint, state->size, subpixel, true );
             if(outlineGlyph)
                drawTextGlyph(font, outlineGlyph, x, y, true );
          }
-#endif
          drawTextGlyph(font, glyph, x, y, false );
          addGlyphAdvance( &x, &subpixel, glyph );
        }
@@ -1063,14 +1053,12 @@ public:
        if( glyph )
        {
          font.addKerning(prevGlyphIndex, glyph, &x, &subpixel );
-#if !defined(SHADERS)
          if(font.processImage)
          {
             FMGlyph *outlineGlyph = getGlyph(font, codepoint, state->size, subpixel, true );
             if(outlineGlyph)
                drawTextGlyph(font, outlineGlyph, x, y, true );
          }
-#endif
          drawTextGlyph(font, glyph, x, y, false );
          addGlyphAdvance( &x, &subpixel, glyph );
          if( x > truncatepoint )
@@ -1570,14 +1558,12 @@ public:
       if( glyph )
       {
          subpixel = font.ftFont.getGlyphKernAdvance( pathdraw.prevGlyphIndex, glyph->glyphindex );
-#if !defined(SHADERS)
          if(font.processImage)
          {
             FMGlyph *outlineGlyph = getGlyph(font, unicode, state->size, 0, true );
             if(outlineGlyph)
                drawTextGlyphFloat(font, outlineGlyph, x, y, vectorx, vectory, (float)subpixel * (1.0f/64.0f), pathdraw.middleAlign, true );
          }
-#endif
          drawTextGlyphFloat(font, glyph, x, y, vectorx, vectory, (float)subpixel * (1.0f/64.0f), pathdraw.middleAlign, false );
 
          subpixel += glyph->advance;
index 5e0e406..8b1efc6 100644 (file)
@@ -10,32 +10,7 @@ import "Color"
 #include <math.h>
 #include <stdlib.h>
 
-#if !defined(_GLES)
-   #define SHADERS
-#endif
-
-#if !defined(__ANDROID__) && !defined(__EMSCRIPTEN__) && !defined(__ODROID__)
-#  if defined(SHADERS)
-//#     include "gl_core_3_3.h"
-#     include "gl_compat_4_4.h"     // FIXME: no glPushAttrib() in core profile
-#  else
-#     include "gl_compat_4_4.h"
-#  endif
-#endif
-
-#if defined(__EMSCRIPTEN__)
-#if !defined(_GLES2)
-   #define _GLES2
-#endif
-   #include <GLES2/gl2.h>
-#endif
-
-#if defined(__ANDROID__) || defined(__ODROID__)
-#if !defined(_GLES)
-   #define _GLES
-#endif
-   #include <GLES/gl.h>
-#endif
+#include "glHelpers.h"
 
 #include "cc.h"
 #include "mm.h"
@@ -44,8 +19,6 @@ import "fmFontManager"
 import "textureManager"
 import "drawManager"
 
-#define DM_ENABLE_EXT_COLOR (1)
-
 public class FontRenderer : FontManagerRenderer
 {
    DrawManager dm;
@@ -53,18 +26,11 @@ public class FontRenderer : FontManagerRenderer
    int textureWidth, textureHeight;
    int channelcount;
 
-   int imagecount;
-   int imageAlloc;
-   DMImage *imageList;
-
    ColorAlpha stateColor;
    ColorAlpha stateExtColor;
    ColorAlpha stateCursorColor;
    uint32 stateLayer;
 
-   imageAlloc = 512;
-   imageList = new DMImage[imageAlloc];
-
    stateColor = white;
    stateCursorColor = white;
    stateLayer = DM_LAYER_ABOVE;
@@ -82,7 +48,6 @@ public:
    ~FontRenderer()
    {
       delete texture;
-      delete imageList;
    }
 
    bool createTexture( int width, int height )
@@ -94,7 +59,7 @@ public:
 
       delete texture;
 
-      texture = { 0 << DM_TEXTURE_ORDER_SHIFT };
+      texture = { };
       texture.build(image, 0, 0.0, 0 );
 
       textureWidth = width;
@@ -104,53 +69,61 @@ public:
 
    int resizeTexture( int width, int height )
    {
-     int retval;
-
+     dm.clearImages();
      // Reuse create to resize too.
-     delete imageList;
-     imagecount = 0;
-     imageAlloc = 512;
-     imageList = new DMImage[imageAlloc];
-
-     retval = createTexture( width, height );
-     return retval;
+     return createTexture( width, height );
    }
 
    void updateTexture( int *rect, const byte* data )
    {
      if(texture)
      {
-#if defined(SHADERS) && !defined(_GLES2)
-        int glformat = GL_RED;
-#else
+#if defined(_GLES) || defined(_GLES2)
         int glformat = GL_ALPHA;
+#else
+        int glformat =
+   #if ENABLE_GL_LEGACY
+         glCaps_legacyFormats ? GL_ALPHA :
+   #endif
+            GL_RED;
 #endif
         int w = rect[2] - rect[0];
         int h = rect[3] - rect[1];
 
+
         if( channelcount == 1 );
-#if !defined(_GLES) && !defined(_GLES2)
         else if( channelcount == 2 )
-          glformat = GL_RG;
+        {
+#if !ENABLE_GL_LEGACY && !defined(_GLES) && !defined(_GLES2)
+          glformat = glCaps_legacyFormats ? GL_LUMINANCE_ALPHA : GL_RG;
+#else
+          glformat = GL_LUMINANCE_ALPHA;
 #endif
+        }
         else if( channelcount == 3 )
           glformat = GL_RGB;
         else if( channelcount == 4 )
           glformat = GL_RGBA;
 
         // FIXME: no glPushAttrib() in core profile
-#if !defined(_GLES) && !defined(_GLES2)
-        glPushClientAttrib( GL_CLIENT_PIXEL_STORE_BIT );
-        glPushAttrib( GL_TEXTURE_BIT );
+#if ENABLE_GL_LEGACY
+        if(glCaps_legacy)
+        {
+          glPushClientAttrib( GL_CLIENT_PIXEL_STORE_BIT );
+          glPushAttrib( GL_TEXTURE_BIT );
+        }
 #endif
-        glBindTexture( GL_TEXTURE_2D, texture.glTex );
+
         glPixelStorei( GL_UNPACK_ALIGNMENT, 1 );
-#if !defined(_GLES) && !defined(_GLES2)
-        glPixelStorei( GL_UNPACK_ROW_LENGTH, textureWidth );
-        glTexSubImage2D( GL_TEXTURE_2D, 0, rect[0], rect[1], w, h, glformat, GL_UNSIGNED_BYTE, data + (rect[1] * textureWidth + rect[0]) * channelcount);
-        //glPixelStorei( GL_UNPACK_SKIP_PIXELS, rect[0] );
-        //glPixelStorei( GL_UNPACK_SKIP_ROWS, rect[1] );
-#else
+        glBindTexture( GL_TEXTURE_2D, texture.glTex );
+#if ENABLE_GL_LEGACY
+        if(glCaps_legacy)
+        {
+           glPixelStorei( GL_UNPACK_ROW_LENGTH, textureWidth );
+           glTexSubImage2D( GL_TEXTURE_2D, 0, rect[0], rect[1], w, h, glformat, GL_UNSIGNED_BYTE, data + (rect[1] * textureWidth + rect[0]) * channelcount);
+        }
+        else
+#endif
        {
           int row = w * channelcount;
           byte * tmp = new byte[h * row];
@@ -160,13 +133,16 @@ public:
           glTexSubImage2D( GL_TEXTURE_2D, 0, rect[0], rect[1], w, h, glformat, GL_UNSIGNED_BYTE, tmp);
           delete tmp;
        }
+
+#if ENABLE_GL_LEGACY
+        if(glCaps_legacy)
+        {
+           glPopAttrib();
+           glPopClientAttrib();
+        }
+        else
 #endif
-#if !defined(_GLES) && !defined(_GLES2)
-        glPopAttrib();
-        glPopClientAttrib();
-#else
-        glPixelStorei( GL_UNPACK_ALIGNMENT, 4 );
-#endif
+           glPixelStorei( GL_UNPACK_ALIGNMENT, 4 );
 
       #if 0
         IMGImage image;
@@ -188,49 +164,17 @@ public:
 
    int registerImage( int offsetx, int offsety, int width, int height )
    {
-      int imageindex = imagecount;
-      DMImage *image;
-
-      if( imagecount >= imageAlloc )
-      {
-         imageAlloc <<= 1;
-         dm.flushImages(); // Need to flush as we will be invalidating images previously given to DrawManager
-         imageList = renew imageList DMImage[imageAlloc];
-      }
-      imagecount++;
-
-      image = &imageList[ imageindex ];
-   #if 1
-      image->defineImage( texture, offsetx, offsety, width, height, 1, DM_PROGRAM_ALPHABLEND_INTENSITY_EXTCOLOR, stateLayer );
-   #elif 1
-      image->defineImage( texture, offsetx, offsety, width, height, 1, DM_PROGRAM_ALPHABLEND_INTENSITY, stateLayer );
-   #elif 1
-      image->defineImage( texture, offsetx, offsety, width, height, 1, DM_PROGRAM_ALPHABLEND, stateLayer );
-   #else
-      image->defineImage( texture, offsetx, offsety, width, height, 1, DM_PROGRAM_NORMAL, stateLayer );
-   #endif
-
-      return imageindex;
+      return dm.defineImage( texture, offsetx, offsety, width, height, true, stateLayer );
    }
 
-   void drawImage( int targetx, int targety, int imageindex, bool useExtColor )
+   void drawImage( int targetx, int targety, int imageIndex, bool useExtColor )
    {
-      DMImage *image = &imageList[ imageindex ];
-   #if (DM_ENABLE_EXT_COLOR && defined(SHADERS))
-      dm.drawImageExtColor( image, targetx, targety, image->sizex, image->sizey, stateColor, stateExtColor );
-   #else
-      dm.drawImage( image, targetx, targety, image->sizex, image->sizey, useExtColor ? stateExtColor : stateColor );
-   #endif
+      dm.drawImage( imageIndex, targetx, targety, 0,1, useExtColor ? stateExtColor : stateColor );
    }
 
-   void drawImageCursor( int targetx, int targety, int imageindex )
+   void drawImageCursor( int targetx, int targety, int imageIndex )
    {
-      DMImage *image = &imageList[ imageindex ];
-   #if DM_ENABLE_EXT_COLOR
-      dm.drawImageExtColor( image, targetx, targety, image->sizex, image->sizey, stateCursorColor, stateExtColor );
-   #else
-      dm.drawImage( image, targetx, targety, image->sizex, image->sizey, stateCursorColor );
-   #endif
+      dm.drawImage( imageIndex, targetx, targety, 0,1, stateCursorColor );
    }
 
    void drawImageAlt( byte *texdata, int targetx, int targety, int offsetx, int offsety, int width, int height )
@@ -238,36 +182,29 @@ public:
 
    }
 
-   void drawImageFloat( float targetx, float targety, float angsin, float angcos, int imageindex, bool useExtColor )
+   void drawImageFloat( float targetx, float targety, float angsin, float angcos, int imageIndex, bool useExtColor )
    {
-      DMImage *image = &imageList[ imageindex ];
-
-      /* 0.2588190451, 0.965925826289 */
-   #if (DM_ENABLE_EXT_COLOR && defined(SHADERS))
-      dm.drawImageFloatExtColor( image, targetx, targety, (float)image->sizex, (float)image->sizey, angsin, angcos, stateColor, stateExtColor );
-   #else
-      dm.drawImageFloat( image, targetx, targety, (float)image->sizex, (float)image->sizey, angsin, angcos, useExtColor ? stateExtColor : stateColor );
-   #endif
+      dm.drawImage( imageIndex, targetx, targety, angsin, angcos, useExtColor ? stateExtColor : stateColor );
    }
 
    void resetImages( )
    {
-      imagecount = 0;
+      dm.resetImages();
    }
 
    void setColor( ColorAlpha color )
    {
-      stateColor = { color.a, { color.color.b, color.color.g, color.color.r } };
+      stateColor = color;
    }
 
    void setExtColor( ColorAlpha color )
    {
-      stateExtColor = { color.a, { color.color.b, color.color.g, color.color.r } };
+      stateExtColor = color;
    }
 
    void setCursorColor( ColorAlpha color )
    {
-      stateCursorColor = { color.a, { color.color.b, color.color.g, color.color.r } };
+      stateCursorColor = color;
    }
 
    void setLayer( uint32 layerIndex )
index 9571308..64474bf 100644 (file)
@@ -1,37 +1,9 @@
-import "instance"
+import "Display"
 
 #include <stdio.h>
 #include <math.h>
 
-#if !defined(_GLES)
-   #define SHADERS
-#endif
-
-#if !defined(__ANDROID__) && !defined(__EMSCRIPTEN__) && !defined(__ODROID__)
-#  if defined(SHADERS)
-#     include "gl_core_3_3.h"
-#  else
-#     include "gl_compat_4_4.h"
-#  endif
-#endif
-
-#if defined(__EMSCRIPTEN__)
-#if !defined(_GLES2)
-   #define _GLES2
-#endif
-   #include <GLES2/gl2.h>
-#endif
-
-#if defined(__ANDROID__) || defined(__ODROID__)
-#if !defined(_GLES)
-   #define _GLES
-#endif
-   #include <GLES/gl.h>
-#endif
-
-// TOFIX:
-int GL_ARB_texture_non_power_of_two = 1;
-int GL_EXT_texture_filter_anisotropic = 1;
+#include "glHelpers.h"
 
 #include "cc.h"
 
@@ -62,6 +34,7 @@ class Texture : struct
    float widthinv;
    float heightinv;
    TextureFlags flags;
+   int swizzle;
    uint32 orderMask;
 
    flags = { invalid = true };
@@ -72,21 +45,37 @@ public:
 
    static bool setData( IMGImage image, int internalformat, int mipmapmode, float anisotropy, int maxresolution )
    {
-     int width, height;
-     int glformat;
+      int width, height;
+      int glformat;
+      int swizzle = 0;
+
+      if( image.format.bytesPerPixel == 1 )
+      {
+#if defined(_GLES) || defined(_GLES2)
+         glformat = GL_ALPHA, swizzle = 1;
+#else
 
-     if( image.format.bytesPerPixel == 1 )
+   #if ENABLE_GL_LEGACY
+         if(glCaps_legacyFormats)
+            glformat = GL_ALPHA, swizzle = 1;
+         else
+   #endif
+           glformat = GL_RED, swizzle = 2;
+#endif
+      }
+     else if( image.format.bytesPerPixel == 2 )
      {
-#if defined(SHADERS) && !defined(__EMSCRIPTEN__)
-       glformat = GL_RED;
+#if defined(_GLES) || defined(_GLES2)
+       glformat = GL_LUMINANCE_ALPHA;
 #else
-       glformat = GL_ALPHA;
+   #if ENABLE_GL_LEGACY
+         if(glCaps_legacyFormats)
+            glformat = GL_LUMINANCE_ALPHA;
+         else
+   #endif
+            glformat = GL_RG;
 #endif
      }
-#if defined(SHADERS) && !defined(__EMSCRIPTEN__)
-     else if( image.format.bytesPerPixel == 2 )
-       glformat = GL_RG;
-#endif
      else if( image.format.bytesPerPixel == 3 )
        glformat = GL_RGB;
      else if( image.format.bytesPerPixel == 4 )
@@ -101,7 +90,7 @@ public:
 
      width = image.format.width;
      height = image.format.height;
-     if( !( GL_ARB_texture_non_power_of_two ) )
+     if(!glCaps_nonPow2Textures)
      {
        if( !( ccIsPow2Int32( width ) ) || !( ccIsPow2Int32( height ) ) )
        {
@@ -115,13 +104,18 @@ public:
 
      glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR );
      glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR );
+     if(image.data)
+       memset(image.data, 0, image.format.width * image.format.height);
      glTexImage2D( GL_TEXTURE_2D, 0, internalformat, image.format.width, image.format.height, 0, glformat, GL_UNSIGNED_BYTE, image.data );
 
-     if( ( GL_EXT_texture_filter_anisotropic ) && ( anisotropy > 1.0 ) )
-       ; //glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, anisotropy );
+#if GL_TEXTURE_MAX_ANISOTROPY_EXT
+     if(anisotropy > 1.0)
+       glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, anisotropy );
+#endif
 
      this.width = width;
      this.height = height;
+     this.swizzle = swizzle;
      widthinv = 1.0f / (float)width;
      heightinv = 1.0f / (float)height;