i don't believe that we forgot that desktopgl has an unload for shader
[profile/ivi/evas.git] / src / modules / engines / gl_common / evas_gl_context.c
index 052643f..31cb602 100644 (file)
@@ -1,17 +1,36 @@
 #include "evas_gl_private.h"
 
+#ifdef HAVE_DLSYM
+# include <dlfcn.h>      /* dlopen,dlclose,etc */
+#else
+# error gl_common should not get compiled if dlsym is not found on the system!
+#endif
+
+#define PRG_INVALID 0xffffffff
 #define GLPIPES 1
 
 static int sym_done = 0;
+int _evas_engine_GL_common_log_dom = -1;
+
+typedef void    (*glsym_func_void) ();
 
 void (*glsym_glGenFramebuffers)      (GLsizei a, GLuint *b) = NULL;
 void (*glsym_glBindFramebuffer)      (GLenum a, GLuint b) = NULL;
 void (*glsym_glFramebufferTexture2D) (GLenum a, GLenum b, GLenum c, GLuint d, GLint e) = NULL;
 void (*glsym_glDeleteFramebuffers)   (GLsizei a, const GLuint *b) = NULL;
+void (*glsym_glGetProgramBinary)     (GLuint a, GLsizei b, GLsizei *c, GLenum *d, void *e) = NULL;
+void (*glsym_glProgramBinary)        (GLuint a, GLenum b, const void *c, GLint d) = NULL;
+void (*glsym_glProgramParameteri)    (GLuint a, GLuint b, GLint d) = NULL;
+void (*glsym_glReleaseShaderCompiler)(void) = NULL;
 
 #if defined (GLES_VARIETY_S3C6410) || defined (GLES_VARIETY_SGX)
 // just used for finding symbols :)
 typedef void (*_eng_fn) (void);
+
+typedef _eng_fn       (*secsym_func_eng_fn) ();
+typedef unsigned int  (*secsym_func_uint) ();
+typedef void         *(*secsym_func_void_ptr) ();
+
 static _eng_fn  (*secsym_eglGetProcAddress)          (const char *a) = NULL;
 
 void          *(*secsym_eglCreateImage)               (void *a, void *b, GLenum c, void *d, const int *e) = NULL;
@@ -22,10 +41,12 @@ unsigned int   (*secsym_eglUnmapImageSEC)             (void *a, void *b) = NULL;
 unsigned int   (*secsym_eglGetImageAttribSEC)         (void *a, void *b, int c, int *d) = NULL;
 #endif
 
+static int dbgflushnum = -1;
+
 static void
 sym_missing(void)
 {
-   printf("EVAS ERROR - GL symbols missing!\n");
+   ERR("GL symbols missing!");
 }
 
 static void
@@ -34,182 +55,193 @@ gl_symbols(void)
    if (sym_done) return;
    sym_done = 1;
 
-#ifdef _EVAS_ENGINE_SDL_H
-# define FINDSYM(dst, sym) if (!dst) dst = SDL_GL_GetProcAddress(sym)
-#else
-# define FINDSYM(dst, sym) if (!dst) dst = dlsym(RTLD_DEFAULT, sym)
-#endif
-#define FALLBAK(dst) if (!dst) dst = (void *)sym_missing;
-   
-   FINDSYM(glsym_glGenFramebuffers, "glGenFramebuffers");
-   FINDSYM(glsym_glGenFramebuffers, "glGenFramebuffersEXT");
-   FINDSYM(glsym_glGenFramebuffers, "glGenFramebuffersARB");
-   FALLBAK(glsym_glGenFramebuffers);
-   
-   FINDSYM(glsym_glBindFramebuffer, "glBindFramebuffer");
-   FINDSYM(glsym_glBindFramebuffer, "glBindFramebufferEXT");
-   FINDSYM(glsym_glBindFramebuffer, "glBindFramebufferARB");
-   FALLBAK(glsym_glBindFramebuffer);
-   
-   FINDSYM(glsym_glFramebufferTexture2D, "glFramebufferTexture2D");
-   FINDSYM(glsym_glFramebufferTexture2D, "glFramebufferTexture2DEXT");
-   FINDSYM(glsym_glFramebufferTexture2D, "glFramebufferTexture2DARB");
-   FALLBAK(glsym_glFramebufferTexture2D);
-
-   FINDSYM(glsym_glDeleteFramebuffers, "glDeleteFramebuffers");
-   FINDSYM(glsym_glDeleteFramebuffers, "glDeleteFramebuffersEXT");
-   FINDSYM(glsym_glDeleteFramebuffers, "glDeleteFramebuffersARB");
-   FALLBAK(glsym_glDeleteFramebuffers);
+   /* FIXME: If using the SDL engine, we should use SDL_GL_GetProcAddress
+    * instead of dlsym
+    * if (!dst) dst = (typ)SDL_GL_GetProcAddress(sym)
+    */
+#define FINDSYM(dst, sym, typ) if (!dst) dst = (typ)dlsym(RTLD_DEFAULT, sym)
+#define FALLBAK(dst, typ) if (!dst) dst = (typ)sym_missing;
+
+   FINDSYM(glsym_glGenFramebuffers, "glGenFramebuffers", glsym_func_void);
+   FINDSYM(glsym_glGenFramebuffers, "glGenFramebuffersEXT", glsym_func_void);
+   FINDSYM(glsym_glGenFramebuffers, "glGenFramebuffersARB", glsym_func_void);
+   FALLBAK(glsym_glGenFramebuffers, glsym_func_void);
+
+   FINDSYM(glsym_glBindFramebuffer, "glBindFramebuffer", glsym_func_void);
+   FINDSYM(glsym_glBindFramebuffer, "glBindFramebufferEXT", glsym_func_void);
+   FINDSYM(glsym_glBindFramebuffer, "glBindFramebufferARB", glsym_func_void);
+   FALLBAK(glsym_glBindFramebuffer, glsym_func_void);
+
+   FINDSYM(glsym_glFramebufferTexture2D, "glFramebufferTexture2D", glsym_func_void);
+   FINDSYM(glsym_glFramebufferTexture2D, "glFramebufferTexture2DEXT", glsym_func_void);
+   FINDSYM(glsym_glFramebufferTexture2D, "glFramebufferTexture2DARB", glsym_func_void);
+   FALLBAK(glsym_glFramebufferTexture2D, glsym_func_void);
+
+   FINDSYM(glsym_glDeleteFramebuffers, "glDeleteFramebuffers", glsym_func_void);
+   FINDSYM(glsym_glDeleteFramebuffers, "glDeleteFramebuffersEXT", glsym_func_void);
+   FINDSYM(glsym_glDeleteFramebuffers, "glDeleteFramebuffersARB", glsym_func_void);
+   FALLBAK(glsym_glDeleteFramebuffers, glsym_func_void);
+
+   FINDSYM(glsym_glGetProgramBinary, "glGetProgramBinary", glsym_func_void);
+   FINDSYM(glsym_glGetProgramBinary, "glGetProgramBinaryEXT", glsym_func_void);
+   FINDSYM(glsym_glGetProgramBinary, "glGetProgramBinaryARB", glsym_func_void);
+   FINDSYM(glsym_glGetProgramBinary, "glGetProgramBinaryOES", glsym_func_void);
+
+   FINDSYM(glsym_glProgramBinary, "glProgramBinary", glsym_func_void);
+   FINDSYM(glsym_glProgramBinary, "glProgramBinaryEXT", glsym_func_void);
+   FINDSYM(glsym_glProgramBinary, "glProgramBinaryARB", glsym_func_void);
+
+   FINDSYM(glsym_glProgramParameteri, "glProgramParameteri", glsym_func_void);
+   FINDSYM(glsym_glProgramParameteri, "glProgramParameteriEXT", glsym_func_void);
+   FINDSYM(glsym_glProgramParameteri, "glProgramParameteriARB", glsym_func_void);
+
+   FINDSYM(glsym_glReleaseShaderCompiler, "glReleaseShaderCompiler", glsym_func_void);
+   FINDSYM(glsym_glReleaseShaderCompiler, "glReleaseShaderCompilerEXT", glsym_func_void);
+   FINDSYM(glsym_glReleaseShaderCompiler, "glReleaseShaderCompilerARB", glsym_func_void);
 
 #if defined (GLES_VARIETY_S3C6410) || defined (GLES_VARIETY_SGX)
 #undef FINDSYM
-#define FINDSYM(dst, sym) \
-   if ((!dst) && (secsym_eglGetProcAddress)) dst = secsym_eglGetProcAddress(sym); \
-   if (!dst) dst = dlsym(RTLD_DEFAULT, sym)
+#define FINDSYM(dst, sym, typ) \
+   if ((!dst) && (secsym_eglGetProcAddress)) dst = (typ)secsym_eglGetProcAddress(sym); \
+   if (!dst) dst = (typ)dlsym(RTLD_DEFAULT, sym)
 // yes - gl core looking for egl stuff. i know it's odd. a reverse-layer thing
 // but it will work as the egl/glx layer calls gl core common stuff and thus
 // these symbols will work. making the glx/egl + x11 layer do this kind-of is
 // wrong as this is not x11 (output) layer specific like the native surface
 // stuff. this is generic zero-copy textures for gl
 
-   FINDSYM(secsym_eglGetProcAddress, "eglGetProcAddress");
-   FINDSYM(secsym_eglGetProcAddress, "eglGetProcAddressEXT");
-   FINDSYM(secsym_eglGetProcAddress, "eglGetProcAddressARB");
-   FINDSYM(secsym_eglGetProcAddress, "eglGetProcAddressKHR");
-   
-   FINDSYM(secsym_eglCreateImage, "eglCreateImage");
-   FINDSYM(secsym_eglCreateImage, "eglCreateImageEXT");
-   FINDSYM(secsym_eglCreateImage, "eglCreateImageARB");
-   FINDSYM(secsym_eglCreateImage, "eglCreateImageKHR");
-   
-   FINDSYM(secsym_eglDestroyImage, "eglDestroyImage");
-   FINDSYM(secsym_eglDestroyImage, "eglDestroyImageEXT");
-   FINDSYM(secsym_eglDestroyImage, "eglDestroyImageARB");
-   FINDSYM(secsym_eglDestroyImage, "eglDestroyImageKHR");
-   
-   FINDSYM(secsym_glEGLImageTargetTexture2DOES, "glEGLImageTargetTexture2DOES");
-   
-   FINDSYM(secsym_eglMapImageSEC, "eglMapImageSEC");
-//   FALLBAK(secsym_eglMapImageSEC);
-   
-   FINDSYM(secsym_eglUnmapImageSEC, "eglUnmapImageSEC");
-//   FALLBAK(secsym_eglUnmapImageSEC);
-   
-   FINDSYM(secsym_eglGetImageAttribSEC, "eglGetImageAttribSEC");
-//   FALLBAK(secsym_eglGetImageAttribSEC);
-#endif   
+   FINDSYM(secsym_eglGetProcAddress, "eglGetProcAddress", secsym_func_eng_fn);
+   FINDSYM(secsym_eglGetProcAddress, "eglGetProcAddressEXT", secsym_func_eng_fn);
+   FINDSYM(secsym_eglGetProcAddress, "eglGetProcAddressARB", secsym_func_eng_fn);
+   FINDSYM(secsym_eglGetProcAddress, "eglGetProcAddressKHR", secsym_func_eng_fn);
+
+   FINDSYM(secsym_eglCreateImage, "eglCreateImage", secsym_func_void_ptr);
+   FINDSYM(secsym_eglCreateImage, "eglCreateImageEXT", secsym_func_void_ptr);
+   FINDSYM(secsym_eglCreateImage, "eglCreateImageARB", secsym_func_void_ptr);
+   FINDSYM(secsym_eglCreateImage, "eglCreateImageKHR", secsym_func_void_ptr);
+
+   FINDSYM(secsym_eglDestroyImage, "eglDestroyImage", secsym_func_uint);
+   FINDSYM(secsym_eglDestroyImage, "eglDestroyImageEXT", secsym_func_uint);
+   FINDSYM(secsym_eglDestroyImage, "eglDestroyImageARB", secsym_func_uint);
+   FINDSYM(secsym_eglDestroyImage, "eglDestroyImageKHR", secsym_func_uint);
+
+   FINDSYM(glsym_glGetProgramBinary, "glGetProgramBinary", glsym_func_void);
+   FINDSYM(glsym_glGetProgramBinary, "glGetProgramBinaryEXT", glsym_func_void);
+   FINDSYM(glsym_glGetProgramBinary, "glGetProgramBinaryARB", glsym_func_void);
+   FINDSYM(glsym_glGetProgramBinary, "glGetProgramBinaryOES", glsym_func_void);
+   FINDSYM(glsym_glGetProgramBinary, "glGetProgramBinaryKHR", glsym_func_void);
+
+   FINDSYM(glsym_glProgramBinary, "glProgramBinary", glsym_func_void);
+   FINDSYM(glsym_glProgramBinary, "glProgramBinaryEXT", glsym_func_void);
+   FINDSYM(glsym_glProgramBinary, "glProgramBinaryARB", glsym_func_void);
+   FINDSYM(glsym_glProgramBinary, "glProgramBinaryOES", glsym_func_void);
+   FINDSYM(glsym_glProgramBinary, "glProgramBinaryKHR", glsym_func_void);
+
+   FINDSYM(glsym_glProgramParameteri, "glProgramParameteri", glsym_func_void);
+   FINDSYM(glsym_glProgramParameteri, "glProgramParameteriEXT", glsym_func_void);
+   FINDSYM(glsym_glProgramParameteri, "glProgramParameteriARB", glsym_func_void);
+   FINDSYM(glsym_glProgramParameteri, "glProgramParameteriOES", glsym_func_void);
+   FINDSYM(glsym_glProgramParameteri, "glProgramParameteriKHR", glsym_func_void);
+
+   FINDSYM(secsym_glEGLImageTargetTexture2DOES, "glEGLImageTargetTexture2DOES", glsym_func_void);
+
+   FINDSYM(secsym_eglMapImageSEC, "eglMapImageSEC", secsym_func_void_ptr);
+
+   FINDSYM(secsym_eglUnmapImageSEC, "eglUnmapImageSEC", secsym_func_uint);
+
+   FINDSYM(secsym_eglGetImageAttribSEC, "eglGetImageAttribSEC", secsym_func_uint);
+#endif
 }
 
-static void shader_array_flush(Evas_GL_Context *gc);
+static void shader_array_flush(Evas_Engine_GL_Context *gc);
 
-static Evas_GL_Context *_evas_gl_common_context = NULL;
+static Evas_Engine_GL_Context *_evas_gl_common_context = NULL;
 static Evas_GL_Shared *shared = NULL;
 
 void
 glerr(int err, const char *file, const char *func, int line, const char *op)
 {
-   fprintf(stderr, "GLERR: %s:%i %s(), %s: ", file, line, func, op);
+   const char *errmsg;
+   char buf[32];
+
    switch (err)
      {
      case GL_INVALID_ENUM:
-        fprintf(stderr, "GL_INVALID_ENUM\n");
+        errmsg = "GL_INVALID_ENUM";
         break;
      case GL_INVALID_VALUE:
-        fprintf(stderr, "GL_INVALID_VALUE\n");
+        errmsg = "GL_INVALID_VALUE";
         break;
      case GL_INVALID_OPERATION:
-        fprintf(stderr, "GL_INVALID_OPERATION\n");
+        errmsg = "GL_INVALID_OPERATION";
         break;
      case GL_OUT_OF_MEMORY:
-        fprintf(stderr, "GL_OUT_OF_MEMORY\n");
+        errmsg = "GL_OUT_OF_MEMORY";
         break;
      default:
-        fprintf(stderr, "0x%x\n", err);
+        snprintf(buf, sizeof(buf), "%#x", err);
+        errmsg = buf;
      }
-}
 
-static void
-matrix_ident(GLfloat *m)
-{
-   memset(m, 0, 16 * sizeof(GLfloat));
-   m[0] = m[5] = m[10] = m[15] = 1.0;
-   //------------------------
-   // 1 0 0 0
-   // 0 1 0 0
-   // 0 0 1 0
-   // 0 0 0 1
+   eina_log_print(_evas_engine_GL_common_log_dom, EINA_LOG_LEVEL_ERR,
+                  file, func, line, "%s: %s", op, errmsg);
 }
 
 static void
-matrix_ortho(GLfloat *m, 
-             GLfloat l, GLfloat r, 
-             GLfloat t, GLfloat b, 
+matrix_ortho(GLfloat *m,
+             GLfloat l, GLfloat r,
+             GLfloat t, GLfloat b,
              GLfloat near, GLfloat far,
-             int rot, int w, int h)
+             int rot, int vw, int vh,
+             int foc, GLfloat orth)
 {
    GLfloat rotf;
    GLfloat cosv, sinv;
    GLfloat tx, ty;
-   
-//   rot = 180;
-   //------------------------
-   m[0] = 2.0 / (r - l);
-   m[1] = 0.0;
-   m[2] = 0.0;
-   m[3] = 0.0;
 
-   //------------------------
-   m[4] = 0.0;
-   m[5] = 2.0 / (t - b);
-   m[6] = 0.0;
-   m[7] = 0.0;
-   
-   //------------------------
-   m[8] = 0.0;
-   m[9] = 0.0;
-   m[10] = -(2.0 / (far - near));
-   m[11] = 0.0;
-   
-   //------------------------
-   m[12] = -((r + l) / (r - l));
-   m[13] = -((t + b) / (t - b));
-   m[14] = -((near + far) / (far - near));
-   m[15] = 1.0;
-
-   // rot
    rotf = (((rot / 90) & 0x3) * M_PI) / 2.0;
 
-   tx = 0.0;
-   ty = 0.0;
+   tx = -0.5 * (1.0 - orth);
+   ty = -0.5 * (1.0 - orth);
+
    if (rot == 90)
      {
-        tx = -(w * 1.0);
-        ty = -(h * 0.0);
+        tx += -(vw * 1.0);
+        ty += -(vh * 0.0);
      }
    if (rot == 180)
      {
-        tx = -(w * 1.0);
-        ty = -(h * 1.0);
+        tx += -(vw * 1.0);
+        ty += -(vh * 1.0);
      }
    if (rot == 270)
      {
-        tx = -(w * 0.0);
-        ty = -(h * 1.0);
+        tx += -(vw * 0.0);
+        ty += -(vh * 1.0);
      }
-   
+
    cosv = cos(rotf);
    sinv = sin(rotf);
-   
+
    m[0] = (2.0 / (r - l)) * ( cosv);
    m[1] = (2.0 / (r - l)) * ( sinv);
-   
+   m[2] = 0.0;
+   m[3] = 0.0;
+
    m[4] = (2.0 / (t - b)) * (-sinv);
    m[5] = (2.0 / (t - b)) * ( cosv);
-   
-   m[12] += (m[0] * tx) + (m[4] * ty);
-   m[13] += (m[1] * tx) + (m[5] * ty);
-   m[14] += (m[2] * tx) + (m[6] * ty);
-   m[15] += (m[3] * tx) + (m[7] * ty);
+   m[6] = 0.0;
+   m[7] = 0.0;
+
+   m[8] = 0.0;
+   m[9] = 0.0;
+   m[10] = -(2.0 / (far - near));
+   m[11] = 1.0 / (GLfloat)foc;
+
+   m[12] = (m[0] * tx) + (m[4] * ty) - ((r + l) / (r - l));
+   m[13] = (m[1] * tx) + (m[5] * ty) - ((t + b) / (t - b));
+   m[14] = (m[2] * tx) + (m[6] * ty) - ((near + far) / (far - near));
+   m[15] = (m[3] * tx) + (m[7] * ty) + orth;
 }
 
 static int
@@ -301,11 +333,14 @@ _evas_gl_common_version_check()
 }
 
 static void
-_evas_gl_common_viewport_set(Evas_GL_Context *gc)
+_evas_gl_common_viewport_set(Evas_Engine_GL_Context *gc)
 {
    GLfloat proj[16];
-   int w = 1, h = 1, m = 1, rot = 1;
+   unsigned int i;
+   int w = 1, h = 1, m = 1, rot = 1, foc = 0;
 
+   EINA_SAFETY_ON_NULL_RETURN(gc);
+   foc = gc->foc;
    // surface in pipe 0 will be the same as all pipes
    if ((gc->pipe[0].shader.surface == gc->def_surface) ||
        (!gc->pipe[0].shader.surface))
@@ -322,113 +357,149 @@ _evas_gl_common_viewport_set(Evas_GL_Context *gc)
         m = -1;
      }
 
-   if ((!gc->change.size) || 
+   if ((!gc->change.size) ||
        ((gc->shared->w == w) && (gc->shared->h == h) &&
-           (gc->shared->rot == rot)))
+           (gc->shared->rot == rot) && (gc->shared->foc == gc->foc) &&
+           (gc->shared->mflip == m)))
       return;
-   
+
    gc->shared->w = w;
    gc->shared->h = h;
    gc->shared->rot = rot;
+   gc->shared->mflip = m;
+   gc->shared->foc = foc;
+   gc->shared->z0 = gc->z0;
+   gc->shared->px = gc->px;
+   gc->shared->py = gc->py;
    gc->change.size = 0;
 
-   if ((rot == 0) || (rot == 180))
-     glViewport(0, 0, w, h);
+   if (foc == 0)
+     {
+        if ((rot == 0) || (rot == 180))
+           glViewport(0, 0, w, h);
+        else
+           glViewport(0, 0, h, w);
+        GLERR(__FUNCTION__, __FILE__, __LINE__, "");
+        // std matrix
+        if (m == 1)
+           matrix_ortho(proj,
+                        0, w, 0, h,
+                        -1000000.0, 1000000.0,
+                        rot, w, h,
+                        1, 1.0);
+        // v flipped matrix for render-to-texture
+        else
+           matrix_ortho(proj,
+                        0, w, h, 0,
+                        -1000000.0, 1000000.0,
+                        rot, w, h,
+                        1, 1.0);
+     }
    else
-     glViewport(0, 0, h, w);
-   GLERR(__FUNCTION__, __FILE__, __LINE__, "");
-   
-   matrix_ident(proj);
-   if (m == 1) matrix_ortho(proj, 0, w, 0, h, -1.0, 1.0, rot, w, h);
-   else matrix_ortho(proj, 0, w, h, 0, -1.0, 1.0, rot, w, h);
-   
-   glUseProgram(gc->shared->shader.rect.prog);
-   GLERR(__FUNCTION__, __FILE__, __LINE__, "");
-   glUniformMatrix4fv(glGetUniformLocation(gc->shared->shader.rect.prog, "mvp"), 1,
-                      GL_FALSE, proj);
-   GLERR(__FUNCTION__, __FILE__, __LINE__, "");
-   glUseProgram(gc->shared->shader.font.prog);
-   GLERR(__FUNCTION__, __FILE__, __LINE__, "");
-   glUniformMatrix4fv(glGetUniformLocation(gc->shared->shader.font.prog, "mvp"), 1,
-                      GL_FALSE, proj);
-   GLERR(__FUNCTION__, __FILE__, __LINE__, "");
-   
-   glUseProgram(gc->shared->shader.yuv.prog);
-   GLERR(__FUNCTION__, __FILE__, __LINE__, "");
-   glUniformMatrix4fv(glGetUniformLocation(gc->shared->shader.yuv.prog, "mvp"), 1,
-                      GL_FALSE, proj);
-   GLERR(__FUNCTION__, __FILE__, __LINE__, "");
-   glUseProgram(gc->shared->shader.yuv_nomul.prog);
-   GLERR(__FUNCTION__, __FILE__, __LINE__, "");
-   glUniformMatrix4fv(glGetUniformLocation(gc->shared->shader.yuv_nomul.prog, "mvp"), 1,
-                      GL_FALSE, proj);
-   GLERR(__FUNCTION__, __FILE__, __LINE__, "");
-   
-   glUseProgram(gc->shared->shader.tex.prog);
-   GLERR(__FUNCTION__, __FILE__, __LINE__, "");
-   glUniformMatrix4fv(glGetUniformLocation(gc->shared->shader.tex.prog, "mvp"), 1,
-                      GL_FALSE, proj);
-   GLERR(__FUNCTION__, __FILE__, __LINE__, "");
-   glUseProgram(gc->shared->shader.tex_nomul.prog);
-   GLERR(__FUNCTION__, __FILE__, __LINE__, "");
-   glUniformMatrix4fv(glGetUniformLocation(gc->shared->shader.tex_nomul.prog, "mvp"), 1,
-                      GL_FALSE, proj);
-   GLERR(__FUNCTION__, __FILE__, __LINE__, "");
-   
-   glUseProgram(gc->shared->shader.img.prog);
-   GLERR(__FUNCTION__, __FILE__, __LINE__, "");
-   glUniformMatrix4fv(glGetUniformLocation(gc->shared->shader.img.prog, "mvp"), 1,
-                      GL_FALSE, proj);
-   GLERR(__FUNCTION__, __FILE__, __LINE__, "");
-   glUseProgram(gc->shared->shader.img_nomul.prog);
-   GLERR(__FUNCTION__, __FILE__, __LINE__, "");
-   glUniformMatrix4fv(glGetUniformLocation(gc->shared->shader.img_nomul.prog, "mvp"), 1,
-                      GL_FALSE, proj);
-   GLERR(__FUNCTION__, __FILE__, __LINE__, "");
+     {
+        int px, py, vx, vy, vw = 0, vh = 0, ax = 0, ay = 0, ppx = 0, ppy = 0;
 
-   glUseProgram(gc->shared->shader.img_bgra.prog);
-   GLERR(__FUNCTION__, __FILE__, __LINE__, "");
-   glUniformMatrix4fv(glGetUniformLocation(gc->shared->shader.img_bgra.prog, "mvp"), 1,
-                      GL_FALSE, proj);
-   GLERR(__FUNCTION__, __FILE__, __LINE__, "");
-   glUseProgram(gc->shared->shader.img_bgra_nomul.prog);
-   GLERR(__FUNCTION__, __FILE__, __LINE__, "");
-   glUniformMatrix4fv(glGetUniformLocation(gc->shared->shader.img_bgra_nomul.prog, "mvp"), 1,
-                      GL_FALSE, proj);
-   GLERR(__FUNCTION__, __FILE__, __LINE__, "");
+        px = gc->shared->px;
+        py = gc->shared->py;
+
+        if      ((rot == 0  ) || (rot == 90 )) ppx = px;
+        else if ((rot == 180) || (rot == 270)) ppx = w - px;
+        if      ((rot == 0  ) || (rot == 270)) ppy = py;
+        else if ((rot == 90 ) || (rot == 180)) ppy = h - py;
+
+        vx = ((w / 2) - ppx);
+        if (vx >= 0)
+          {
+             vw = w + (2 * vx);
+             if      ((rot == 0  ) || (rot == 90 )) ax = 2 * vx;
+             else if ((rot == 180) || (rot == 270)) ax = 0;
+          }
+        else
+          {
+             vw = w - (2 * vx);
+             if      ((rot == 0  ) || (rot == 90 )) ax = 0;
+             else if ((rot == 180) || (rot == 270)) ax = ppx - px;
+             vx = 0;
+          }
+
+        vy = ((h / 2) - ppy);
+        if (vy < 0)
+          {
+             vh = h - (2 * vy);
+             if      ((rot == 0  ))                                 ay = 0;
+             else if ((rot == 90 ) || (rot == 180) || (rot == 270)) ay = ppy - py;
+             vy = -vy;
+          }
+        else
+          {
+             vh = h + (2 * vy);
+             if      ((rot == 0  ) || (rot == 270)) ay = 2 * vy;
+             else if ((rot == 90 ) || (rot == 180)) ay = 0;
+             vy = 0;
+          }
+
+        if (m == -1) ay = vy * 2;
+
+        if ((rot == 0) || (rot == 180))
+           glViewport(-2 * vx, -2 * vy, vw, vh);
+        else
+           glViewport(-2 * vy, -2 * vx, vh, vw);
+        if (m == 1)
+           matrix_ortho(proj, 0, vw, 0, vh,
+                        -1000000.0, 1000000.0,
+                        rot, vw, vh,
+                        foc, 0.0);
+        else
+           matrix_ortho(proj, 0, vw, vh, 0,
+                        -1000000.0, 1000000.0,
+                        rot, vw, vh,
+                        foc, 0.0);
+        gc->shared->ax = ax;
+        gc->shared->ay = ay;
+     }
+
+   for (i = 0; i < SHADER_LAST; ++i)
+     {
+        glUseProgram(gc->shared->shader[i].prog);
+        GLERR(__FUNCTION__, __FILE__, __LINE__, "");
+        glUniformMatrix4fv(glGetUniformLocation(gc->shared->shader[i].prog, "mvp"), 1, GL_FALSE, proj);
+        GLERR(__FUNCTION__, __FILE__, __LINE__, "");
+     }
 
-   glUseProgram(gc->pipe[0].shader.cur_prog);
+   if (gc->state.current.cur_prog == PRG_INVALID)
+      glUseProgram(gc->shared->shader[0].prog);
+   else glUseProgram(gc->state.current.cur_prog);
    GLERR(__FUNCTION__, __FILE__, __LINE__, "");
 }
 
-Evas_GL_Context *
+Evas_Engine_GL_Context *
 evas_gl_common_context_new(void)
 {
-   Evas_GL_Context *gc;
+   Evas_Engine_GL_Context *gc;
    const char *s;
    int i;
 
 #if 1
    if (_evas_gl_common_context)
      {
-       _evas_gl_common_context->references++;
-       return _evas_gl_common_context;
+        _evas_gl_common_context->references++;
+        return _evas_gl_common_context;
      }
 #endif
    if (!_evas_gl_common_version_check())
      return NULL;
-   gc = calloc(1, sizeof(Evas_GL_Context));
+   gc = calloc(1, sizeof(Evas_Engine_GL_Context));
    if (!gc) return NULL;
 
    gl_symbols();
-   
+
    gc->references = 1;
-   
+
    _evas_gl_common_context = gc;
-   
+
    for (i = 0; i < MAX_PIPES; i++)
       gc->pipe[i].shader.render_op = EVAS_RENDER_BLEND;
-   
+
    if (!shared)
      {
         const GLubyte *ext;
@@ -447,9 +518,12 @@ evas_gl_common_context_new(void)
                  (strstr((char *)ext, "GL_EXT_texture_rectangle")) ||
                  (strstr((char *)ext, "GL_ARB_texture_rectangle")))
                shared->info.tex_rect = 1;
+             if ((strstr((char *)ext, "GL_ARB_get_program_binary")) ||
+                 (strstr((char *)ext, "GL_OES_get_program_binary")))
+               shared->info.bin_program = 1;
 #ifdef GL_TEXTURE_MAX_ANISOTROPY_EXT
              if ((strstr((char *)ext, "GL_EXT_texture_filter_anisotropic")))
-               glGetFloatv(GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT, 
+               glGetFloatv(GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT,
                            &(shared->info.anisotropic));
 #endif
 #ifdef GL_BGRA
@@ -461,8 +535,8 @@ evas_gl_common_context_new(void)
              // FIXME: there should be an extension name/string to check for
              // not just symbols in the lib
              i = 0;
-             if (getenv("EVAS_GL_NO_MAP_IMAGE_SEC"))
-                i = atoi(getenv("EVAS_GL_NO_MAP_IMAGE_SEC"));
+             s = getenv("EVAS_GL_NO_MAP_IMAGE_SEC");
+             if (s) i = atoi(s);
              if (!i)
                {
                   // test for all needed symbols - be "conservative" and
@@ -475,13 +549,24 @@ evas_gl_common_context_new(void)
                       (secsym_eglGetImageAttribSEC))
                      shared->info.sec_image_map = 1;
                }
-#endif             
+#endif
           }
         glGetIntegerv(GL_MAX_TEXTURE_IMAGE_UNITS,
                       &(shared->info.max_texture_units));
         glGetIntegerv(GL_MAX_TEXTURE_SIZE,
                       &(shared->info.max_texture_size));
-        
+        shared->info.max_vertex_elements = 6 * 100000;
+#ifdef GL_MAX_ELEMENTS_VERTICES
+/* only applies to glDrawRangeElements. don't really need to get it.
+        glGetIntegerv(GL_MAX_ELEMENTS_VERTICES,
+                      &(shared->info.max_vertex_elements));
+ */
+#endif
+        s = getenv("EVAS_GL_VERTEX_MAX");
+        if (s) shared->info.max_vertex_elements = atoi(s);
+        if (shared->info.max_vertex_elements < 6)
+           shared->info.max_vertex_elements = 6;
+
         // magic numbers that are a result of imperical testing and getting
         // "best case" performance across a range of systems
         shared->info.tune.cutout.max                 = DEF_CUTOUT;
@@ -491,7 +576,7 @@ evas_gl_common_context_new(void)
         shared->info.tune.atlas.max_w                = DEF_ATLAS_W;
         shared->info.tune.atlas.max_h                = DEF_ATLAS_H;
         shared->info.tune.atlas.slot_size            = DEF_ATLAS_SLOT;
-        
+
         // per gpu hacks. based on impirical measurement of some known gpu's
         s = (const char *)glGetString(GL_RENDERER);
         if (s)
@@ -501,7 +586,7 @@ evas_gl_common_context_new(void)
              else if (strstr(s, "NVIDIA Tegra"))
                 shared->info.tune.pipes.max = DEF_PIPES_TEGRA_2;
           }
-        
+
 #define GETENVOPT(name, tune_param, min, max) \
         do { \
            const char *__v = getenv(name); \
@@ -521,6 +606,11 @@ evas_gl_common_context_new(void)
         GETENVOPT("EVAS_GL_ATLAS_MAX_W", atlas.max_w, 0, MAX_ATLAS_W);
         GETENVOPT("EVAS_GL_ATLAS_MAX_H", atlas.max_h, 0, MAX_ATLAS_H);
         GETENVOPT("EVAS_GL_ATLAS_SLOT_SIZE", atlas.slot_size, MIN_ATLAS_SLOT, MAX_ATLAS_SLOT);
+        s = (const char *)getenv("EVAS_GL_GET_PROGRAM_BINARY");
+        if (s)
+          {
+             if (atoi(s) == 0) shared->info.bin_program = 0;
+          }
 
         if (getenv("EVAS_GL_INFO"))
            fprintf(stderr,
@@ -531,14 +621,18 @@ evas_gl_common_context_new(void)
                    "bgra : %i\n"
                    "max ansiotropic filtering: %3.3f\n"
                    "egl sec map image: %i\n"
+                   "max vertex count: %i\n"
                    "\n"
+                   "(can set EVAS_GL_VERTEX_MAX  EVAS_GL_NO_MAP_IMAGE_SEC  EVAS_GL_INFO  EVAS_GL_MEMINFO )\n"
+                   "\n"
+                   "EVAS_GL_GET_PROGRAM_BINARY: %i\n"
                    "EVAS_GL_CUTOUT_MAX: %i\n"
                    "EVAS_GL_PIPES_MAX: %i\n"
                    "EVAS_GL_ATLAS_ALLOC_SIZE: %i\n"
                    "EVAS_GL_ATLAS_ALLOC_ALPHA_SIZE: %i\n"
                    "EVAS_GL_ATLAS_MAX_W x EVAS_GL_ATLAS_MAX_H: %i x %i\n"
                    "EVAS_GL_ATLAS_SLOT_SIZE: %i\n"
-                   , 
+                   ,
                    (int)shared->info.max_texture_size, (int)shared->info.max_texture_size,
                    (int)shared->info.max_texture_units,
                    (int)shared->info.tex_npo2,
@@ -546,7 +640,9 @@ evas_gl_common_context_new(void)
                    (int)shared->info.bgra,
                    (double)shared->info.anisotropic,
                    (int)shared->info.sec_image_map,
-                   
+                   (int)shared->info.max_vertex_elements,
+
+                   (int)shared->info.bin_program,
                    (int)shared->info.tune.cutout.max,
                    (int)shared->info.tune.pipes.max,
                    (int)shared->info.tune.atlas.max_alloc_size,
@@ -554,7 +650,7 @@ evas_gl_common_context_new(void)
                    (int)shared->info.tune.atlas.max_w, (int)shared->info.tune.atlas.max_h,
                    (int)shared->info.tune.atlas.slot_size
                   );
-        
+
         glDisable(GL_DEPTH_TEST);
         GLERR(__FUNCTION__, __FILE__, __LINE__, "");
         glEnable(GL_DITHER);
@@ -568,7 +664,7 @@ evas_gl_common_context_new(void)
 //        glBlendFunc(GL_SRC_ALPHA, GL_ONE); // ???
         glDepthMask(GL_FALSE);
         GLERR(__FUNCTION__, __FILE__, __LINE__, "");
-        
+
         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
         GLERR(__FUNCTION__, __FILE__, __LINE__, "");
         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
@@ -584,89 +680,66 @@ evas_gl_common_context_new(void)
              GLERR(__FUNCTION__, __FILE__, __LINE__, "");
           }
 #endif
-        
+
         glEnableVertexAttribArray(SHAD_VERTEX);
         GLERR(__FUNCTION__, __FILE__, __LINE__, "");
         glEnableVertexAttribArray(SHAD_COLOR);
         GLERR(__FUNCTION__, __FILE__, __LINE__, "");
 
-        if (!evas_gl_common_shader_program_init(&(shared->shader.rect), 
-                                                &(shader_rect_vert_src), 
-                                                &(shader_rect_frag_src),
-                                                "rect")) goto error;
-        if (!evas_gl_common_shader_program_init(&(shared->shader.font),
-                                                &(shader_font_vert_src), 
-                                                &(shader_font_frag_src),
-                                                "font")) goto error;
-        if (!evas_gl_common_shader_program_init(&(shared->shader.img),
-                                                &(shader_img_vert_src),
-                                                &(shader_img_frag_src),
-                                                "img")) goto error;
-        if (!evas_gl_common_shader_program_init(&(shared->shader.img_nomul),
-                                                &(shader_img_nomul_vert_src),
-                                                &(shader_img_nomul_frag_src),
-                                                "img_nomul")) goto error;
-        if (!evas_gl_common_shader_program_init(&(shared->shader.img_bgra),
-                                                &(shader_img_bgra_vert_src),
-                                                &(shader_img_bgra_frag_src),
-                                                "img_bgra")) goto error;
-        if (!evas_gl_common_shader_program_init(&(shared->shader.img_bgra_nomul),
-                                                &(shader_img_bgra_nomul_vert_src),
-                                                &(shader_img_bgra_nomul_frag_src),
-                                                "img_bgra_nomul")) goto error;
-        if (!evas_gl_common_shader_program_init(&(shared->shader.tex),
-                                                &(shader_tex_vert_src), 
-                                                &(shader_tex_frag_src),
-                                                "tex")) goto error;
-        if (!evas_gl_common_shader_program_init(&(shared->shader.tex_nomul),
-                                                &(shader_tex_nomul_vert_src), 
-                                                &(shader_tex_nomul_frag_src),
-                                                "tex_nomul")) goto error;
-        if (!evas_gl_common_shader_program_init(&(shared->shader.yuv),
-                                                &(shader_yuv_vert_src), 
-                                                &(shader_yuv_frag_src),
-                                                "yuv")) goto error;
-        if (!evas_gl_common_shader_program_init(&(shared->shader.yuv_nomul),
-                                                &(shader_yuv_nomul_vert_src), 
-                                                &(shader_yuv_nomul_frag_src),
-                                                "yuv_nomul")) goto error;
-        
-        glUseProgram(shared->shader.yuv.prog);
-        GLERR(__FUNCTION__, __FILE__, __LINE__, "");
-        glUniform1i(glGetUniformLocation(shared->shader.yuv.prog, "tex"), 0);
-        GLERR(__FUNCTION__, __FILE__, __LINE__, "");
-        glUniform1i(glGetUniformLocation(shared->shader.yuv.prog, "texu"), 1);
-        GLERR(__FUNCTION__, __FILE__, __LINE__, "");
-        glUniform1i(glGetUniformLocation(shared->shader.yuv.prog, "texv"), 2);
-        GLERR(__FUNCTION__, __FILE__, __LINE__, "");
-        
-        glUseProgram(shared->shader.yuv_nomul.prog);
-        GLERR(__FUNCTION__, __FILE__, __LINE__, "");
-        glUniform1i(glGetUniformLocation(shared->shader.yuv_nomul.prog, "tex"), 0);
-        GLERR(__FUNCTION__, __FILE__, __LINE__, "");
-        glUniform1i(glGetUniformLocation(shared->shader.yuv_nomul.prog, "texu"), 1);
-        GLERR(__FUNCTION__, __FILE__, __LINE__, "");
-        glUniform1i(glGetUniformLocation(shared->shader.yuv_nomul.prog, "texv"), 2);
+       if (!evas_gl_common_shader_program_init(shared)) goto error;
+
+#define SHADER_TEXTURE_ADD(Shared, Shader, Name)                        \
+        glUseProgram(Shared->shader[SHADER_##Shader].prog);             \
+        GLERR(__FUNCTION__, __FILE__, __LINE__, "");                    \
+        glUniform1i(glGetUniformLocation(Shared->shader[SHADER_##Shader].prog, #Name), Shared->shader[SHADER_##Shader].tex_count++); \
         GLERR(__FUNCTION__, __FILE__, __LINE__, "");
-        
-        glUseProgram(gc->pipe[0].shader.cur_prog);
+
+        SHADER_TEXTURE_ADD(shared, YUV, tex);
+        SHADER_TEXTURE_ADD(shared, YUV, texu);
+        SHADER_TEXTURE_ADD(shared, YUV, texv);
+
+        SHADER_TEXTURE_ADD(shared, YUY2, tex);
+        SHADER_TEXTURE_ADD(shared, YUY2, texuv);
+
+        SHADER_TEXTURE_ADD(shared, NV12, tex);
+        SHADER_TEXTURE_ADD(shared, NV12, texuv);
+
+        SHADER_TEXTURE_ADD(shared, YUV_NOMUL, tex);
+        SHADER_TEXTURE_ADD(shared, YUV_NOMUL, texu);
+        SHADER_TEXTURE_ADD(shared, YUV_NOMUL, texv);
+
+        SHADER_TEXTURE_ADD(shared, YUY2_NOMUL, tex);
+        SHADER_TEXTURE_ADD(shared, YUY2_NOMUL, texuv);
+
+        SHADER_TEXTURE_ADD(shared, NV12_NOMUL, tex);
+        SHADER_TEXTURE_ADD(shared, NV12_NOMUL, texuv);
+
+        SHADER_TEXTURE_ADD(shared, IMG_MASK, tex);
+        SHADER_TEXTURE_ADD(shared, IMG_MASK, texm);
+
+        if (gc->state.current.cur_prog == PRG_INVALID)
+           glUseProgram(gc->shared->shader[0].prog);
+        else glUseProgram(gc->state.current.cur_prog);
         GLERR(__FUNCTION__, __FILE__, __LINE__, "");
+
+        evas_gl_common_shader_program_init_done();
         // in shader:
         // uniform sampler2D tex[8];
-        // 
+        //
         // in code:
         // GLuint texes[8];
         // GLint loc = glGetUniformLocation(prog, "tex");
         // glUniform1iv(loc, 8, texes);
 
-        shared->native_hash = eina_hash_int32_new(NULL);
+        shared->native_pm_hash  = eina_hash_int32_new(NULL);
+        shared->native_tex_hash = eina_hash_int32_new(NULL);
      }
    gc->shared = shared;
    gc->shared->references++;
    _evas_gl_common_viewport_set(gc);
-   
+
    gc->def_surface = evas_gl_common_image_surface_new(gc, 1, 1, 1);
-   
+
    return gc;
    error:
    evas_gl_common_context_free(gc);
@@ -674,14 +747,15 @@ evas_gl_common_context_new(void)
 }
 
 void
-evas_gl_common_context_free(Evas_GL_Context *gc)
+evas_gl_common_context_free(Evas_Engine_GL_Context *gc)
 {
    int i, j;
-   
+   Eina_List *l;
+
    gc->references--;
    if (gc->references > 0) return;
    if (gc->shared) gc->shared->references--;
-   
+
    if (gc->def_surface) evas_gl_common_image_free(gc->def_surface);
 
    if (gc->shared)
@@ -691,45 +765,36 @@ evas_gl_common_context_free(Evas_GL_Context *gc)
              if (gc->pipe[i].array.vertex) free(gc->pipe[i].array.vertex);
              if (gc->pipe[i].array.color) free(gc->pipe[i].array.color);
              if (gc->pipe[i].array.texuv) free(gc->pipe[i].array.texuv);
+             if (gc->pipe[i].array.texm) free(gc->pipe[i].array.texm);
              if (gc->pipe[i].array.texuv2) free(gc->pipe[i].array.texuv2);
              if (gc->pipe[i].array.texuv3) free(gc->pipe[i].array.texuv3);
           }
      }
-   
+
    if ((gc->shared) && (gc->shared->references == 0))
      {
-        evas_gl_common_shader_program_shutdown(&(gc->shared->shader.rect));
-        evas_gl_common_shader_program_shutdown(&(gc->shared->shader.font));
-        evas_gl_common_shader_program_shutdown(&(gc->shared->shader.img));
-        evas_gl_common_shader_program_shutdown(&(gc->shared->shader.img_nomul));
-        evas_gl_common_shader_program_shutdown(&(gc->shared->shader.img_bgra));
-        evas_gl_common_shader_program_shutdown(&(gc->shared->shader.img_bgra_nomul));
-        evas_gl_common_shader_program_shutdown(&(gc->shared->shader.yuv));
-        evas_gl_common_shader_program_shutdown(&(gc->shared->shader.yuv_nomul));
-        evas_gl_common_shader_program_shutdown(&(gc->shared->shader.tex));
-        evas_gl_common_shader_program_shutdown(&(gc->shared->shader.tex_nomul));
-        
+        Evas_GL_Texture_Pool *pt;
+
+        for (i = 0; i < SHADER_LAST; ++i)
+          evas_gl_common_shader_program_shutdown(&(gc->shared->shader[i]));
+
         while (gc->shared->images)
           {
              evas_gl_common_image_free(gc->shared->images->data);
           }
-        while (gc->shared->tex.whole)
-          {
-             evas_gl_common_texture_free(gc->shared->tex.whole->data);
-          }
+
+        EINA_LIST_FOREACH(gc->shared->tex.whole, l, pt)
+           evas_gl_texture_pool_empty(pt);
         for (i = 0; i < 33; i++)
           {
              for (j = 0; j < 3; j++)
                {
-                  while (gc->shared->tex.atlas[i][j])
-                    {
-                       evas_gl_common_texture_free
-                         ((Evas_GL_Texture *)gc->shared->tex.atlas[i][j]);
-                       gc->shared->tex.atlas[i][j] = NULL;
-                    }
+                  EINA_LIST_FOREACH(gc->shared->tex.atlas[i][j], l, pt)
+                     evas_gl_texture_pool_empty(pt);
                }
           }
-        eina_hash_free(gc->shared->native_hash);
+        eina_hash_free(gc->shared->native_pm_hash);
+        eina_hash_free(gc->shared->native_tex_hash);
         free(gc->shared);
         shared = NULL;
      }
@@ -738,36 +803,34 @@ evas_gl_common_context_free(Evas_GL_Context *gc)
 }
 
 void
-evas_gl_common_context_use(Evas_GL_Context *gc)
+evas_gl_common_context_use(Evas_Engine_GL_Context *gc)
 {
    if (_evas_gl_common_context == gc) return;
    _evas_gl_common_context = gc;
-   _evas_gl_common_viewport_set(gc);
+   if (gc) _evas_gl_common_viewport_set(gc);
 }
 
 void
-evas_gl_common_context_newframe(Evas_GL_Context *gc)
+evas_gl_common_context_newframe(Evas_Engine_GL_Context *gc)
 {
    int i;
-   static int dbgflushnum = -1;
 
    if (dbgflushnum < 0)
      {
         dbgflushnum = 0;
-        if (getenv("DBGEVAS")) dbgflushnum = 1;
+        if (getenv("EVAS_GL_DBG")) dbgflushnum = 1;
      }
-   if (dbgflushnum) printf("prev-flushnum: %i\n", gc->flushnum);
-   
+   if (dbgflushnum) printf("----prev-flushnum: %i -----------------------------------\n", gc->flushnum);
+
    gc->flushnum = 0;
    gc->state.current.cur_prog = 0;
    gc->state.current.cur_tex = 0;
    gc->state.current.cur_texu = 0;
    gc->state.current.cur_texv = 0;
+   gc->state.current.cur_texm = 0;
+   gc->state.current.cur_texmu = 0;
+   gc->state.current.cur_texmv = 0;
    gc->state.current.render_op = 0;
-   gc->state.current.cx = 0;
-   gc->state.current.cy = 0;
-   gc->state.current.cw = 0;
-   gc->state.current.ch = 0;
    gc->state.current.smooth = 0;
    gc->state.current.blend = 0;
    gc->state.current.clip = 0;
@@ -775,7 +838,7 @@ evas_gl_common_context_newframe(Evas_GL_Context *gc)
    gc->state.current.cy = 0;
    gc->state.current.cw = 0;
    gc->state.current.ch = 0;
-   
+
    for (i = 0; i < gc->shared->info.tune.pipes.max; i++)
      {
         gc->pipe[i].region.x = 0;
@@ -793,6 +856,7 @@ evas_gl_common_context_newframe(Evas_GL_Context *gc)
         gc->pipe[i].shader.cur_tex = 0;
         gc->pipe[i].shader.cur_texu = 0;
         gc->pipe[i].shader.cur_texv = 0;
+        gc->pipe[i].shader.cur_texm = 0;
         gc->pipe[i].shader.render_op = EVAS_RENDER_BLEND;
         gc->pipe[i].shader.smooth = 0;
         gc->pipe[i].shader.blend = 0;
@@ -803,12 +867,12 @@ evas_gl_common_context_newframe(Evas_GL_Context *gc)
         gc->pipe[i].shader.ch = 0;
      }
    gc->change.size = 1;
-   
+
    glDisable(GL_SCISSOR_TEST);
    GLERR(__FUNCTION__, __FILE__, __LINE__, "");
    glScissor(0, 0, 0, 0);
    GLERR(__FUNCTION__, __FILE__, __LINE__, "");
-   
+
    glDisable(GL_DEPTH_TEST);
    GLERR(__FUNCTION__, __FILE__, __LINE__, "");
    glEnable(GL_DITHER);
@@ -822,7 +886,7 @@ evas_gl_common_context_newframe(Evas_GL_Context *gc)
 //   glBlendFunc(GL_SRC_ALPHA, GL_ONE); // ???
    glDepthMask(GL_FALSE);
    GLERR(__FUNCTION__, __FILE__, __LINE__, "");
-        
+
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
    GLERR(__FUNCTION__, __FILE__, __LINE__, "");
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
@@ -838,14 +902,16 @@ evas_gl_common_context_newframe(Evas_GL_Context *gc)
         GLERR(__FUNCTION__, __FILE__, __LINE__, "");
      }
 #endif
-   
+
    glEnableVertexAttribArray(SHAD_VERTEX);
    GLERR(__FUNCTION__, __FILE__, __LINE__, "");
    glEnableVertexAttribArray(SHAD_COLOR);
    GLERR(__FUNCTION__, __FILE__, __LINE__, "");
-   glUseProgram(gc->pipe[0].shader.cur_prog);
+   if (gc->state.current.cur_prog == PRG_INVALID)
+      glUseProgram(gc->shared->shader[0].prog);
+   else glUseProgram(gc->state.current.cur_prog);
    GLERR(__FUNCTION__, __FILE__, __LINE__, "");
-   
+
    glActiveTexture(GL_TEXTURE0);
    GLERR(__FUNCTION__, __FILE__, __LINE__, "");
    glBindTexture(GL_TEXTURE_2D, gc->pipe[0].shader.cur_tex);
@@ -855,9 +921,10 @@ evas_gl_common_context_newframe(Evas_GL_Context *gc)
 }
 
 void
-evas_gl_common_context_resize(Evas_GL_Context *gc, int w, int h, int rot)
+evas_gl_common_context_resize(Evas_Engine_GL_Context *gc, int w, int h, int rot)
 {
    if ((gc->w == w) && (gc->h == h) && (gc->rot == rot)) return;
+   evas_gl_common_context_flush(gc);
    gc->change.size = 1;
    gc->rot = rot;
    gc->w = w;
@@ -866,24 +933,37 @@ evas_gl_common_context_resize(Evas_GL_Context *gc, int w, int h, int rot)
 }
 
 void
-evas_gl_common_context_target_surface_set(Evas_GL_Context *gc,
+evas_gl_common_context_target_surface_set(Evas_Engine_GL_Context *gc,
                                           Evas_GL_Image *surface)
 {
    if (surface == gc->pipe[0].shader.surface) return;
-   
+
    evas_gl_common_context_flush(gc);
 
+   gc->state.current.cur_prog = PRG_INVALID;
+   gc->state.current.cur_tex = -1;
+   gc->state.current.cur_texu = -1;
+   gc->state.current.cur_texv = -1;
+   gc->state.current.render_op = -1;
+   gc->state.current.smooth = -1;
+   gc->state.current.blend = -1;
+   gc->state.current.clip = -1;
+   gc->state.current.cx = -1;
+   gc->state.current.cy = -1;
+   gc->state.current.cw = -1;
+   gc->state.current.ch = -1;
+
    gc->pipe[0].shader.surface = surface;
    gc->change.size = 1;
 #if defined (GLES_VARIETY_S3C6410) || defined (GLES_VARIETY_SGX)
 # ifndef GL_FRAMEBUFFER
 #  define GL_FRAMEBUFFER GL_FRAMEBUFFER_OES
-# endif   
+# endif
 #else
 # ifndef GL_FRAMEBUFFER
 #  define GL_FRAMEBUFFER GL_FRAMEBUFFER_EXT
-# endif   
-#endif   
+# endif
+#endif
    if (gc->pipe[0].shader.surface == gc->def_surface)
      {
         glsym_glBindFramebuffer(GL_FRAMEBUFFER, 0);
@@ -915,10 +995,15 @@ evas_gl_common_context_target_surface_set(Evas_GL_Context *gc,
 #define PUSH_TEXUV3(n, u, v) \
    gc->pipe[n].array.texuv3[nu3++] = u; \
    gc->pipe[n].array.texuv3[nu3++] = v
+#define PUSH_TEXM(n, u, v) \
+   gc->pipe[n].array.texm[nm++] = u; \
+   gc->pipe[n].array.texm[nm++] = v
+
 
 static inline void
-array_alloc(Evas_GL_Context *gc, int n)
+array_alloc(Evas_Engine_GL_Context *gc, int n)
 {
+   gc->havestuff = EINA_TRUE;
    if (gc->pipe[n].array.num <= gc->pipe[n].array.alloc) return;
    gc->pipe[n].array.alloc += 6 * 1024;
    if (gc->pipe[n].array.use_vertex)
@@ -930,6 +1015,9 @@ array_alloc(Evas_GL_Context *gc, int n)
    if (gc->pipe[n].array.use_texuv)
      gc->pipe[n].array.texuv  = realloc(gc->pipe[n].array.texuv,
                                 gc->pipe[n].array.alloc * sizeof(GLfloat) * 2);
+   if (gc->pipe[n].array.use_texm)
+     gc->pipe[n].array.texm  = realloc(gc->pipe[n].array.texm,
+                                gc->pipe[n].array.alloc * sizeof(GLfloat) * 2);
    if (gc->pipe[n].array.use_texuv2)
      gc->pipe[n].array.texuv2  = realloc(gc->pipe[n].array.texuv2,
                                gc->pipe[n].array.alloc * sizeof(GLfloat) * 2);
@@ -938,30 +1026,31 @@ array_alloc(Evas_GL_Context *gc, int n)
                                  gc->pipe[n].array.alloc * sizeof(GLfloat) * 2);
 }
 
+#ifdef GLPIPES
 static int
-pipe_region_intersects(Evas_GL_Context *gc, int n,
+pipe_region_intersects(Evas_Engine_GL_Context *gc, int n,
                        int x, int y, int w, int h)
 {
    int i, rx, ry, rw, rh, ii;
-   
+
    rx = gc->pipe[n].region.x;
    ry = gc->pipe[n].region.y;
    rw = gc->pipe[n].region.w;
    rh = gc->pipe[n].region.h;
    if (!RECTS_INTERSECT(x, y, w, h, rx, ry, rw, rh))
       return 0;
-   
+
    // a hack for now. map pipes use their whole bounding box for intersects
    // which at worst case reduces to old pipeline flushes, but cheaper than
    // full quad region or triangle intersects right now
    if (gc->pipe[n].region.type == RTYPE_MAP) return 1;
-   
-   for (i = 0, 
-        ii = 0; 
-        
-        i < gc->pipe[n].array.num; 
-        
-        i += (3 * 2), 
+
+   for (i = 0,
+        ii = 0;
+
+        i < gc->pipe[n].array.num;
+
+        i += (3 * 2),
         ii += (3 * 3 * 2))
      {  // tri 1...
         // 0, 1, 2 < top left
@@ -976,13 +1065,14 @@ pipe_region_intersects(Evas_GL_Context *gc, int n,
      }
    return 0;
 }
+#endif
 
 static void
-pipe_region_expand(Evas_GL_Context *gc, int n,
+pipe_region_expand(Evas_Engine_GL_Context *gc, int n,
                    int x, int y, int w, int h)
 {
    int x1, y1, x2, y2;
-   
+
    if (gc->pipe[n].region.w <= 0)
      {
         gc->pipe[n].region.x = x;
@@ -1005,21 +1095,149 @@ pipe_region_expand(Evas_GL_Context *gc, int n,
    gc->pipe[n].region.h = y2 - y1;
 }
 
+static Eina_Bool
+vertex_array_size_check(Evas_Engine_GL_Context *gc, int pn, int n)
+{
+   return 1;
+// this fixup breaks for expedite test 32. why?
+   if ((gc->pipe[pn].array.num + n) > gc->shared->info.max_vertex_elements)
+     {
+        shader_array_flush(gc);
+        return 0;
+     }
+   return 1;
+}
+
+static inline Evas_GL_Shader
+evas_gl_common_shader_choice(int npoints __UNUSED__,
+                            RGBA_Map_Point *p,
+                            int r, int g, int b, int a,
+                            Evas_GL_Shader nomul,
+                            Evas_GL_Shader mul)
+{
+  if ((a == 255) && (r == 255) && (g == 255) && (b == 255))
+    {
+       if (!p) return nomul;
+
+       if ((p[0].col == 0xffffffff) && (p[1].col == 0xffffffff) &&
+           (p[2].col == 0xffffffff) && (p[3].col == 0xffffffff))
+         return nomul;
+    }
+  return mul;
+}
+
+static int
+_evas_gl_common_context_push(int rtype,
+                             Evas_Engine_GL_Context *gc,
+                             Evas_GL_Texture *tex,
+                             Evas_GL_Texture *texm,
+                             GLuint prog,
+                             int x, int y, int w, int h,
+                             Eina_Bool blend,
+                             Eina_Bool smooth,
+                             Eina_Bool clip,
+                             int cx, int cy, int cw, int ch)
+{
+   int pn = 0;
+
+#ifdef GLPIPES
+ again:
+#endif
+   vertex_array_size_check(gc, gc->state.top_pipe, 6);
+   pn = gc->state.top_pipe;
+#ifdef GLPIPES
+   if (!((pn == 0) && (gc->pipe[pn].array.num == 0)))
+     {
+        int found = 0;
+        int i;
+
+        for (i = pn; i >= 0; i--)
+          {
+             if ((gc->pipe[i].region.type == rtype)
+                 && (!tex || gc->pipe[i].shader.cur_tex == tex->pt->texture)
+                 && (!texm || gc->pipe[i].shader.cur_texm == texm->pt->texture)
+                 && (gc->pipe[i].shader.cur_prog == prog)
+                 && (gc->pipe[i].shader.smooth == smooth)
+                 && (gc->pipe[i].shader.blend == blend)
+                 && (gc->pipe[i].shader.render_op == gc->dc->render_op)
+                 && (gc->pipe[i].shader.clip == clip)
+                 && (!clip || ((gc->pipe[i].shader.cx == cx)
+                               && (gc->pipe[i].shader.cy == cy)
+                               && (gc->pipe[i].shader.cw == cw)
+                               && (gc->pipe[i].shader.ch == ch))))
+               {
+                  found = 1;
+                  pn = i;
+                  break;
+               }
+             if (pipe_region_intersects(gc, i, x, y, w, h)) break;
+          }
+        if (!found)
+          {
+             pn = gc->state.top_pipe + 1;
+             if (pn >= gc->shared->info.tune.pipes.max)
+               {
+                  shader_array_flush(gc);
+                  goto again;
+               }
+            gc->state.top_pipe = pn;
+         }
+     }
+   if ((tex) && (((tex->im) && (tex->im->native.data)) || tex->pt->dyn.img))
+     {
+        if (gc->pipe[pn].array.im != tex->im)
+          {
+             shader_array_flush(gc);
+             pn = gc->state.top_pipe;
+             gc->pipe[pn].array.im = tex->im;
+             goto again;
+          }
+     }
+#else
+   if (!((gc->pipe[pn].region.type == rtype)
+         && (!tex || gc->pipe[pn].shader.cur_tex == tex->pt->texture)
+         && (!texm || gc->pipe[pn].shader.cur_texm == texm->pt->texture)
+         && (gc->pipe[pn].shader.cur_prog == prog)
+         && (gc->pipe[pn].shader.smooth == smooth)
+         && (gc->pipe[pn].shader.blend == blend)
+         && (gc->pipe[pn].shader.render_op == gc->dc->render_op)
+         && (gc->pipe[pn].shader.clip == clip)
+         && (!clip || ((gc->pipe[pn].shader.cx == cx)
+                       && (gc->pipe[pn].shader.cy == cy)
+                       && (gc->pipe[pn].shader.cw == cw)
+                       && (gc->pipe[pn].shader.ch == ch)))))
+     {
+        shader_array_flush(gc);
+     }
+   if ((tex) && (((tex->im) && (tex->im->native.data)) || tex->pt->dyn.img))
+     {
+        if (gc->pipe[pn].array.im != tex->im)
+          {
+             shader_array_flush(gc);
+             gc->pipe[pn].array.im = tex->im;
+          }
+     }
+#endif
+
+   return pn;
+}
+
 void
-evas_gl_common_context_line_push(Evas_GL_Context *gc, 
+evas_gl_common_context_line_push(Evas_Engine_GL_Context *gc,
                                  int x1, int y1, int x2, int y2,
                                  int clip, int cx, int cy, int cw, int ch,
                                  int r, int g, int b, int a)
 {
    int pnum, nv, nc, nu, nt, i;
    Eina_Bool blend = 0;
-   GLuint prog = gc->shared->shader.rect.prog;
+   GLuint prog = gc->shared->shader[SHADER_RECT].prog;
    int pn = 0;
-   
+
    if (a < 255) blend = 1;
    if (gc->dc->render_op == EVAS_RENDER_COPY) blend = 0;
-   
+
    shader_array_flush(gc);
+   vertex_array_size_check(gc, gc->state.top_pipe, 2);
    pn = gc->state.top_pipe;
    gc->pipe[pn].shader.cur_tex = 0;
    gc->pipe[pn].shader.cur_prog = prog;
@@ -1030,27 +1248,27 @@ evas_gl_common_context_line_push(Evas_GL_Context *gc,
    gc->pipe[pn].shader.cy = cy;
    gc->pipe[pn].shader.cw = cw;
    gc->pipe[pn].shader.ch = ch;
-   
+
    gc->pipe[pn].array.line = 1;
    gc->pipe[pn].array.use_vertex = 1;
    gc->pipe[pn].array.use_color = 1;
    gc->pipe[pn].array.use_texuv = 0;
    gc->pipe[pn].array.use_texuv2 = 0;
    gc->pipe[pn].array.use_texuv3 = 0;
-   
+
    pnum = gc->pipe[pn].array.num;
    nv = pnum * 3; nc = pnum * 4; nu = pnum * 2; nt = pnum * 4;
-   gc->pipe[pn].array.num += 1;
+   gc->pipe[pn].array.num += 2;
    array_alloc(gc, pn);
-  
+
    PUSH_VERTEX(pn, x1, y1, 0);
    PUSH_VERTEX(pn, x2, y2, 0);
-   
+
    for (i = 0; i < 2; i++)
      {
         PUSH_COLOR(pn, r, g, b, a);
      }
-   
+
    shader_array_flush(gc);
    gc->pipe[pn].array.line = 0;
    gc->pipe[pn].array.use_vertex = 0;
@@ -1061,19 +1279,35 @@ evas_gl_common_context_line_push(Evas_GL_Context *gc,
 }
 
 void
-evas_gl_common_context_rectangle_push(Evas_GL_Context *gc, 
+evas_gl_common_context_rectangle_push(Evas_Engine_GL_Context *gc,
                                       int x, int y, int w, int h,
                                       int r, int g, int b, int a)
 {
    int pnum, nv, nc, nu, nt, i;
    Eina_Bool blend = 0;
-   GLuint prog = gc->shared->shader.rect.prog;
+   GLuint prog = gc->shared->shader[SHADER_RECT].prog;
    int pn = 0;
-   
+
+   if (gc->dc->mask.mask)
+     {
+       RGBA_Draw_Context *dc;
+       dc = gc->dc;
+       Evas_GL_Image *im;
+       im = (void *)dc->mask.mask;
+       evas_gl_common_context_font_push(gc, im->tex,
+                                         x - dc->mask.x,
+                                         y - dc->mask.y,
+                                         dc->mask.w, dc->mask.h,
+                                         x, y, w, h,
+                                         r, g, b, a);
+       return;
+     }
+
    if (a < 255) blend = 1;
    if (gc->dc->render_op == EVAS_RENDER_COPY) blend = 0;
-   
+
 again:
+   vertex_array_size_check(gc, gc->state.top_pipe, 6);
    pn = gc->state.top_pipe;
 #ifdef GLPIPES
    if ((pn == 0) && (gc->pipe[pn].array.num == 0))
@@ -1098,7 +1332,7 @@ again:
    else
      {
         int found = 0;
-        
+
         for (i = pn; i >= 0; i--)
           {
              if ((gc->pipe[i].region.type == RTYPE_RECT)
@@ -1142,7 +1376,7 @@ again:
              gc->pipe[pn].array.use_texuv3 = 0;
          }
      }
-#else   
+#else
    if ((gc->pipe[pn].shader.cur_tex != 0)
        || (gc->pipe[pn].shader.cur_prog != prog)
        || (gc->pipe[pn].shader.blend != blend)
@@ -1162,7 +1396,7 @@ again:
         gc->pipe[pn].shader.cw = 0;
         gc->pipe[pn].shader.ch = 0;
      }
-   
+
    gc->pipe[pn].region.type = RTYPE_RECT;
    gc->pipe[pn].array.line = 0;
    gc->pipe[pn].array.use_vertex = 1;
@@ -1171,22 +1405,22 @@ again:
    gc->pipe[pn].array.use_texuv2 = 0;
    gc->pipe[pn].array.use_texuv3 = 0;
 #endif
-   
+
    pipe_region_expand(gc, pn, x, y, w, h);
-   
+
    pnum = gc->pipe[pn].array.num;
    nv = pnum * 3; nc = pnum * 4; nu = pnum * 2; nt = pnum * 4;
    gc->pipe[pn].array.num += 6;
    array_alloc(gc, pn);
-  
+
    PUSH_VERTEX(pn, x    , y    , 0);
    PUSH_VERTEX(pn, x + w, y    , 0);
    PUSH_VERTEX(pn, x    , y + h, 0);
-   
+
    PUSH_VERTEX(pn, x + w, y    , 0);
    PUSH_VERTEX(pn, x + w, y + h, 0);
    PUSH_VERTEX(pn, x    , y + h, 0);
-   
+
    for (i = 0; i < 6; i++)
      {
         PUSH_COLOR(pn, r, g, b, a);
@@ -1194,7 +1428,7 @@ again:
 }
 
 void
-evas_gl_common_context_image_push(Evas_GL_Context *gc,
+evas_gl_common_context_image_push(Evas_Engine_GL_Context *gc,
                                   Evas_GL_Texture *tex,
                                   double sx, double sy, double sw, double sh,
                                   int x, int y, int w, int h,
@@ -1204,180 +1438,166 @@ evas_gl_common_context_image_push(Evas_GL_Context *gc,
    int pnum, nv, nc, nu, nu2, nt, i;
    GLfloat tx1, tx2, ty1, ty2;
    Eina_Bool blend = 1;
-   GLuint prog = gc->shared->shader.img.prog;
+   GLuint prog = gc->shared->shader[SHADER_IMG].prog;
    int pn = 0;
 
    if (!tex->alpha) blend = 0;
    if (a < 255) blend = 1;
-   
-   if (tex_only)
+
+   if (gc->filter_prog)
+     {
+        prog = gc->filter_prog;
+     }
+   else if (tex_only)
      {
         if (tex->pt->dyn.img)
           {
-             if ((a == 255) && (r == 255) && (g == 255) && (b == 255))
-                prog = gc->shared->shader.img_nomul.prog;
-             else
-                prog = gc->shared->shader.img.prog;
+             prog = gc->shared->shader[evas_gl_common_shader_choice(0, NULL, r, g, b, a,
+                                                                    SHADER_IMG_BGRA_NOMUL, SHADER_IMG_BGRA)].prog;
           }
         else
           {
-             if ((a == 255) && (r == 255) && (g == 255) && (b == 255))
-                prog = gc->shared->shader.tex_nomul.prog;
-             else
-                prog = gc->shared->shader.tex.prog;
+             prog = gc->shared->shader[evas_gl_common_shader_choice(0, NULL, r, g, b, a,
+                                                                    SHADER_TEX_NOMUL, SHADER_TEX)].prog;
           }
      }
    else
      {
         if (tex->gc->shared->info.bgra)
           {
-             if ((a == 255) && (r == 255) && (g == 255) && (b == 255))
-               prog = gc->shared->shader.img_bgra_nomul.prog;
-             else
-               prog = gc->shared->shader.img_bgra.prog;
+             prog = gc->shared->shader[evas_gl_common_shader_choice(0, NULL, r, g, b, a,
+                                                                    SHADER_IMG_BGRA_NOMUL, SHADER_IMG_BGRA)].prog;
           }
         else
           {
-             if ((a == 255) && (r == 255) && (g == 255) && (b == 255))
-               prog = gc->shared->shader.img_nomul.prog;
-             else
-               prog = gc->shared->shader.img.prog;
+             prog = gc->shared->shader[evas_gl_common_shader_choice(0, NULL, r, g, b, a,
+                                                                    SHADER_IMG_NOMUL, SHADER_IMG)].prog;
           }
      }
 
-again:
-   pn = gc->state.top_pipe;
-#ifdef GLPIPES
-   if ((pn == 0) && (gc->pipe[pn].array.num == 0))
+   pn = _evas_gl_common_context_push(RTYPE_IMAGE,
+                                     gc, tex, NULL,
+                                     prog,
+                                     x, y, w, h,
+                                     blend,
+                                     smooth,
+                                     0, 0, 0, 0, 0);
+
+   gc->pipe[pn].region.type = RTYPE_IMAGE;
+   gc->pipe[pn].shader.cur_tex = tex->pt->texture;
+   gc->pipe[pn].shader.cur_prog = prog;
+   gc->pipe[pn].shader.smooth = smooth;
+   gc->pipe[pn].shader.blend = blend;
+   gc->pipe[pn].shader.render_op = gc->dc->render_op;
+   gc->pipe[pn].shader.clip = 0;
+   gc->pipe[pn].shader.cx = 0;
+   gc->pipe[pn].shader.cy = 0;
+   gc->pipe[pn].shader.cw = 0;
+   gc->pipe[pn].shader.ch = 0;
+   gc->pipe[pn].array.line = 0;
+   gc->pipe[pn].array.use_vertex = 1;
+   // if nomul... dont need this
+   gc->pipe[pn].array.use_color = 1;
+   gc->pipe[pn].array.use_texuv = 1;
+   gc->pipe[pn].array.use_texuv2 = 0;
+   gc->pipe[pn].array.use_texuv3 = 0;
+
+   pipe_region_expand(gc, pn, x, y, w, h);
+
+   pnum = gc->pipe[pn].array.num;
+   nv = pnum * 3; nc = pnum * 4; nu = pnum * 2; nu2 = pnum * 2;
+   nt = pnum * 4;
+   gc->pipe[pn].array.num += 6;
+   array_alloc(gc, pn);
+
+   if ((tex->im) && (tex->im->native.data) && (!tex->im->native.yinvert))
      {
-        gc->pipe[pn].region.type = RTYPE_IMAGE;
-        gc->pipe[pn].shader.cur_tex = tex->pt->texture;
-        gc->pipe[pn].shader.cur_prog = prog;
-        gc->pipe[pn].shader.smooth = smooth;
-        gc->pipe[pn].shader.blend = blend;
-        gc->pipe[pn].shader.render_op = gc->dc->render_op;
-        gc->pipe[pn].shader.clip = 0;
-        gc->pipe[pn].shader.cx = 0;
-        gc->pipe[pn].shader.cy = 0;
-        gc->pipe[pn].shader.cw = 0;
-        gc->pipe[pn].shader.ch = 0;
-        gc->pipe[pn].array.line = 0;
-        gc->pipe[pn].array.use_vertex = 1;
-        // if nomul... dont need this
-        gc->pipe[pn].array.use_color = 1;
-        gc->pipe[pn].array.use_texuv = 1;
-        gc->pipe[pn].array.use_texuv2 = 0;
-        gc->pipe[pn].array.use_texuv3 = 0;
+        tx1 = ((double)(tex->x) + sx) / (double)tex->pt->w;
+        ty1 = 1.0 - ((double)(tex->y) + sy) / (double)tex->pt->h;
+        tx2 = ((double)(tex->x) + sx + sw) / (double)tex->pt->w;
+        ty2 = 1.0 - ((double)(tex->y) + sy + sh) / (double)tex->pt->h;
      }
    else
      {
-        int found = 0;
-        
-        for (i = pn; i >= 0; i--)
-          {
-             if ((gc->pipe[i].region.type == RTYPE_IMAGE)
-                 && (gc->pipe[i].shader.cur_tex == tex->pt->texture)
-                 && (gc->pipe[i].shader.cur_prog == prog)
-                 && (gc->pipe[i].shader.smooth == smooth)
-                 && (gc->pipe[i].shader.blend == blend)
-                 && (gc->pipe[i].shader.render_op == gc->dc->render_op)
-                 && (gc->pipe[i].shader.clip == 0)
-                )
-               {
-                  found = 1;
-                  pn = i;
-                  break;
-               }
-             if (pipe_region_intersects(gc, i, x, y, w, h)) break;
-          }
-        if (!found)
-          {
-             pn = gc->state.top_pipe + 1;
-             if (pn >= gc->shared->info.tune.pipes.max)
-               {
-                  shader_array_flush(gc);
-                  goto again;
-               }
-             gc->state.top_pipe = pn;
-             gc->pipe[pn].region.type = RTYPE_IMAGE;
-             gc->pipe[pn].shader.cur_tex = tex->pt->texture;
-             gc->pipe[pn].shader.cur_prog = prog;
-             gc->pipe[pn].shader.smooth = smooth;
-             gc->pipe[pn].shader.blend = blend;
-             gc->pipe[pn].shader.render_op = gc->dc->render_op;
-             gc->pipe[pn].shader.clip = 0;
-             gc->pipe[pn].shader.cx = 0;
-             gc->pipe[pn].shader.cy = 0;
-             gc->pipe[pn].shader.cw = 0;
-             gc->pipe[pn].shader.ch = 0;
-             gc->pipe[pn].array.line = 0;
-             gc->pipe[pn].array.use_vertex = 1;
-             // if nomul... dont need this
-             gc->pipe[pn].array.use_color = 1;
-             gc->pipe[pn].array.use_texuv = 1;
-             gc->pipe[pn].array.use_texuv2 = 0;
-             gc->pipe[pn].array.use_texuv3 = 0;
-   
-         }
-     }
-   if ((tex->im) && (tex->im->native.data))
-     {
-        if (gc->pipe[pn].array.im != tex->im)
-          {
-             shader_array_flush(gc);
-             pn = gc->state.top_pipe;
-             gc->pipe[pn].array.im = tex->im;
-             goto again;
-          }
-     }
-   if (tex->pt->dyn.img)
-     {
-        if (gc->pipe[pn].array.im != tex->im)
-          {
-             shader_array_flush(gc);
-             pn = gc->state.top_pipe;
-             gc->pipe[pn].array.im = tex->im;
-             goto again;
-          }
-     }
-#else   
-   if ((gc->pipe[pn].shader.cur_tex != tex->pt->texture)
-       || (gc->pipe[pn].shader.cur_prog != prog)
-       || (gc->pipe[pn].shader.smooth != smooth)
-       || (gc->pipe[pn].shader.blend != blend)
-       || (gc->pipe[pn].shader.render_op != gc->dc->render_op)
-       || (gc->pipe[pn].shader.clip != 0)
-       )
-     {
-        shader_array_flush(gc);
-        gc->pipe[pn].shader.cur_tex = tex->pt->texture;
-        gc->pipe[pn].shader.cur_prog = prog;
-        gc->pipe[pn].shader.smooth = smooth;
-        gc->pipe[pn].shader.blend = blend;
-        gc->pipe[pn].shader.render_op = gc->dc->render_op;
-        gc->pipe[pn].shader.clip = 0;
-        gc->pipe[pn].shader.cx = 0;
-        gc->pipe[pn].shader.cy = 0;
-        gc->pipe[pn].shader.cw = 0;
-        gc->pipe[pn].shader.ch = 0;
-     } 
-   if ((tex->im) && (tex->im->native.data))
-     {
-        if (gc->pipe[pn].array.im != tex->im)
-          {
-             shader_array_flush(gc);
-             gc->pipe[pn].array.im = tex->im;
-          }
+        tx1 = ((double)(tex->x) + sx) / (double)tex->pt->w;
+        ty1 = ((double)(tex->y) + sy) / (double)tex->pt->h;
+        tx2 = ((double)(tex->x) + sx + sw) / (double)tex->pt->w;
+        ty2 = ((double)(tex->y) + sy + sh) / (double)tex->pt->h;
      }
-   if (tex->pt->dyn.img)
+
+   PUSH_VERTEX(pn, x    , y    , 0);
+   PUSH_VERTEX(pn, x + w, y    , 0);
+   PUSH_VERTEX(pn, x    , y + h, 0);
+
+   PUSH_TEXUV(pn, tx1, ty1);
+   PUSH_TEXUV(pn, tx2, ty1);
+   PUSH_TEXUV(pn, tx1, ty2);
+
+   PUSH_VERTEX(pn, x + w, y    , 0);
+   PUSH_VERTEX(pn, x + w, y + h, 0);
+   PUSH_VERTEX(pn, x    , y + h, 0);
+
+   PUSH_TEXUV(pn, tx2, ty1);
+   PUSH_TEXUV(pn, tx2, ty2);
+   PUSH_TEXUV(pn, tx1, ty2);
+
+   // if nomul... dont need this
+   for (i = 0; i < 6; i++)
      {
-        if (gc->pipe[pn].array.im != tex->im)
-          {
-             shader_array_flush(gc);
-             gc->pipe[pn].array.im = tex->im;
-          }
+        PUSH_COLOR(pn, r, g, b, a);
      }
+}
 
+void
+evas_gl_common_context_image_mask_push(Evas_Engine_GL_Context *gc,
+                                  Evas_GL_Texture *tex,
+                                  Evas_GL_Texture *texm,
+                                  double sx, double sy, double sw, double sh,
+                                  double sxm, double sym, double swm,double shm,
+                                  int x, int y, int w, int h,
+                                  int r, int g, int b, int a,
+                                  Eina_Bool smooth)
+{
+   int pnum, nv, nc, nu, nm, nt, i;
+   GLfloat tx1, tx2, ty1, ty2;
+   GLfloat txm1, txm2, tym1, tym2;
+   Eina_Bool blend = 1;
+   GLuint prog = gc->shared->shader[SHADER_IMG_MASK].prog;
+   int pn = 0;
+
+#if 0
+   if (tex->gc->shared->info.bgra)
+   {
+      prog = gc->shared->shader[SHADER_IMG_MASK].prog;
+   }
+   else
+   {
+#warning Nash: FIXME: Need two shaders?
+          printf("Not good: Need other texture\n");
+          prog = gc->shared->shader[SHADER_IMG].prog;
+   }
+#endif
+
+   pn = _evas_gl_common_context_push(RTYPE_IMASK,
+                                     gc, tex, texm,
+                                     prog,
+                                     x, y, w, h,
+                                     blend,
+                                     smooth,
+                                     0, 0, 0, 0, 0);
+
+   gc->pipe[pn].region.type = RTYPE_IMASK;
+   gc->pipe[pn].shader.cur_tex = tex->pt->texture;
+   gc->pipe[pn].shader.cur_texm = texm->pt->texture;
+   gc->pipe[pn].shader.cur_prog = prog;
+   gc->pipe[pn].shader.smooth = smooth;
+   gc->pipe[pn].shader.blend = blend;
+   gc->pipe[pn].shader.render_op = gc->dc->render_op;
+   gc->pipe[pn].shader.clip = 0;
+   gc->pipe[pn].shader.cx = 0;
+   gc->pipe[pn].shader.cy = 0;
+   gc->pipe[pn].shader.cw = 0;
+   gc->pipe[pn].shader.ch = 0;
    gc->pipe[pn].array.line = 0;
    gc->pipe[pn].array.use_vertex = 1;
    // if nomul... dont need this
@@ -1385,12 +1605,12 @@ again:
    gc->pipe[pn].array.use_texuv = 1;
    gc->pipe[pn].array.use_texuv2 = 0;
    gc->pipe[pn].array.use_texuv3 = 0;
-#endif
+   gc->pipe[pn].array.use_texm = 1;
 
    pipe_region_expand(gc, pn, x, y, w, h);
-  
+
    pnum = gc->pipe[pn].array.num;
-   nv = pnum * 3; nc = pnum * 4; nu = pnum * 2; nu2 = pnum * 2;
+   nv = pnum * 3; nc = pnum * 4; nm = pnum * 2; nu = pnum * 2;
    nt = pnum * 4;
    gc->pipe[pn].array.num += 6;
    array_alloc(gc, pn);
@@ -1401,6 +1621,11 @@ again:
         ty1 = ((double)(tex->y) + sy + sh) / (double)tex->pt->h;
         tx2 = ((double)(tex->x) + sx + sw) / (double)tex->pt->w;
         ty2 = ((double)(tex->y) + sy) / (double)tex->pt->h;
+
+       txm1 = ((double)(texm->x) + sxm) / (double)texm->pt->w;
+        tym1 = ((double)(texm->y) + sym + shm) / (double)texm->pt->h;
+        txm2 = ((double)(texm->x) + sxm + swm) / (double)texm->pt->w;
+        tym2 = ((double)(texm->y) + sym) / (double)texm->pt->h;
      }
    else
      {
@@ -1408,24 +1633,41 @@ again:
         ty1 = ((double)(tex->y) + sy) / (double)tex->pt->h;
         tx2 = ((double)(tex->x) + sx + sw) / (double)tex->pt->w;
         ty2 = ((double)(tex->y) + sy + sh) / (double)tex->pt->h;
+
+        txm1 = (texm->x + sxm) / (double)texm->pt->w;
+        tym1 = (texm->y + sym) / (double)texm->pt->h;
+        txm2 = (texm->x + sxm + swm) / (double)texm->pt->w;
+        tym2 = (texm->y + sym + shm) / (double)texm->pt->h;
      }
+ // printf(" %3.6lf %3.6lf %3.6lf %3.6lf\n",sx,sy,sw,sh);
+ //  printf("m%3.6lf %3.6lf %3.6lf %3.6lf\n",sxm,sym,swm,shm);
+ // printf(" %3f %3f %3f %3f\n",tx1,ty1,tx2,ty2);
+ // printf("m%3f %3f %3f %3f\n",txm1,tym1,txm2,tym2);
 
    PUSH_VERTEX(pn, x    , y    , 0);
    PUSH_VERTEX(pn, x + w, y    , 0);
    PUSH_VERTEX(pn, x    , y + h, 0);
-   
+
    PUSH_TEXUV(pn, tx1, ty1);
    PUSH_TEXUV(pn, tx2, ty1);
    PUSH_TEXUV(pn, tx1, ty2);
-   
+
+   PUSH_TEXM(pn, txm1, tym1);
+   PUSH_TEXM(pn, txm2, tym1);
+   PUSH_TEXM(pn, txm1, tym2);
+
    PUSH_VERTEX(pn, x + w, y    , 0);
    PUSH_VERTEX(pn, x + w, y + h, 0);
    PUSH_VERTEX(pn, x    , y + h, 0);
-   
+
    PUSH_TEXUV(pn, tx2, ty1);
    PUSH_TEXUV(pn, tx2, ty2);
    PUSH_TEXUV(pn, tx1, ty2);
 
+   PUSH_TEXM(pn, txm2, tym1);
+   PUSH_TEXM(pn, txm2, tym2);
+   PUSH_TEXM(pn, txm1, tym2);
+
    // if nomul... dont need this
    for (i = 0; i < 6; i++)
      {
@@ -1433,8 +1675,9 @@ again:
      }
 }
 
+
 void
-evas_gl_common_context_font_push(Evas_GL_Context *gc,
+evas_gl_common_context_font_push(Evas_Engine_GL_Context *gc,
                                  Evas_GL_Texture *tex,
                                  double sx, double sy, double sw, double sh,
                                  int x, int y, int w, int h,
@@ -1442,113 +1685,37 @@ evas_gl_common_context_font_push(Evas_GL_Context *gc,
 {
    int pnum, nv, nc, nu, nt, i;
    GLfloat tx1, tx2, ty1, ty2;
+   GLuint prog = gc->shared->shader[SHADER_FONT].prog;
    int pn = 0;
 
-again:
-   pn = gc->state.top_pipe;
-#ifdef GLPIPES
-   if ((pn == 0) && (gc->pipe[pn].array.num == 0))
-     {
-        gc->pipe[pn].region.type = RTYPE_FONT;
-        gc->pipe[pn].shader.cur_tex = tex->pt->texture;
-        gc->pipe[pn].shader.cur_prog = gc->shared->shader.font.prog;
-        gc->pipe[pn].shader.smooth = 0;
-        gc->pipe[pn].shader.blend = 1;
-        gc->pipe[pn].shader.render_op = gc->dc->render_op;
-        gc->pipe[pn].shader.clip = 0;
-        gc->pipe[pn].shader.cx = 0;
-        gc->pipe[pn].shader.cy = 0;
-        gc->pipe[pn].shader.cw = 0;
-        gc->pipe[pn].shader.ch = 0;
-        gc->pipe[pn].array.line = 0;
-        gc->pipe[pn].array.use_vertex = 1;
-        gc->pipe[pn].array.use_color = 1;
-        gc->pipe[pn].array.use_texuv = 1;
-        gc->pipe[pn].array.use_texuv2 = 0;
-        gc->pipe[pn].array.use_texuv3 = 0;
-     }
-   else
-     {
-        int found = 0;
-        
-        for (i = pn; i >= 0; i--)
-          {
-             if ((gc->pipe[i].region.type == RTYPE_FONT)
-                 && (gc->pipe[i].shader.cur_tex == tex->pt->texture)
-                 && (gc->pipe[i].shader.cur_prog == gc->shared->shader.font.prog)
-                 && (gc->pipe[i].shader.smooth == 0)
-                 && (gc->pipe[i].shader.blend == 1)
-                 && (gc->pipe[i].shader.render_op == gc->dc->render_op)
-                 && (gc->pipe[i].shader.clip == 0)
-                )
-               {
-                  found = 1;
-                  pn = i;
-                  break;
-               }
-             if (pipe_region_intersects(gc, i, x, y, w, h)) break;
-          }
-        if (!found)
-          {
-             pn = gc->state.top_pipe + 1;
-             if (pn >= gc->shared->info.tune.pipes.max)
-               {
-                  shader_array_flush(gc);
-                  goto again;
-               }
-             gc->state.top_pipe = pn;
-             gc->pipe[pn].region.type = RTYPE_FONT;
-             gc->pipe[pn].shader.cur_tex = tex->pt->texture;
-             gc->pipe[pn].shader.cur_prog = gc->shared->shader.font.prog;
-             gc->pipe[pn].shader.smooth = 0;
-             gc->pipe[pn].shader.blend = 1;
-             gc->pipe[pn].shader.render_op = gc->dc->render_op;
-             gc->pipe[pn].shader.clip = 0;
-             gc->pipe[pn].shader.cx = 0;
-             gc->pipe[pn].shader.cy = 0;
-             gc->pipe[pn].shader.cw = 0;
-             gc->pipe[pn].shader.ch = 0;
-             gc->pipe[pn].array.line = 0;
-             gc->pipe[pn].array.use_vertex = 1;
-             gc->pipe[pn].array.use_color = 1;
-             gc->pipe[pn].array.use_texuv = 1;
-             gc->pipe[pn].array.use_texuv2 = 0;
-             gc->pipe[pn].array.use_texuv3 = 0;
-         }
-     }
-#else   
-   if ((gc->pipe[pn].shader.cur_tex != tex->pt->texture)
-       || (gc->pipe[pn].shader.cur_prog != gc->shared->shader.font.prog)
-       || (gc->pipe[pn].shader.smooth != 0)
-       || (gc->pipe[pn].shader.blend != 1)
-       || (gc->pipe[pn].shader.render_op != gc->dc->render_op)
-       || (gc->pipe[pn].shader.clip != 0)
-       )
-     {
-        shader_array_flush(gc);
-        gc->pipe[pn].shader.cur_tex = tex->pt->texture;
-        gc->pipe[pn].shader.cur_prog = gc->shared->shader.font.prog;
-        gc->pipe[pn].shader.smooth = 0;
-        gc->pipe[pn].shader.blend = 1;
-        gc->pipe[pn].shader.render_op = gc->dc->render_op;
-        gc->pipe[pn].shader.clip = 0;
-        gc->pipe[pn].shader.cx = 0;
-        gc->pipe[pn].shader.cy = 0;
-        gc->pipe[pn].shader.cw = 0;
-        gc->pipe[pn].shader.ch = 0;
-     }
+   pn = _evas_gl_common_context_push(RTYPE_FONT,
+                                    gc, tex, NULL,
+                                    prog,
+                                    x, y, w, h,
+                                    1,
+                                    0,
+                                    0, 0, 0, 0, 0);
 
    gc->pipe[pn].region.type = RTYPE_FONT;
+   gc->pipe[pn].shader.cur_tex = tex->pt->texture;
+   gc->pipe[pn].shader.cur_prog = prog;
+   gc->pipe[pn].shader.smooth = 0;
+   gc->pipe[pn].shader.blend = 1;
+   gc->pipe[pn].shader.render_op = gc->dc->render_op;
+   gc->pipe[pn].shader.clip = 0;
+   gc->pipe[pn].shader.cx = 0;
+   gc->pipe[pn].shader.cy = 0;
+   gc->pipe[pn].shader.cw = 0;
+   gc->pipe[pn].shader.ch = 0;
    gc->pipe[pn].array.line = 0;
    gc->pipe[pn].array.use_vertex = 1;
    gc->pipe[pn].array.use_color = 1;
    gc->pipe[pn].array.use_texuv = 1;
    gc->pipe[pn].array.use_texuv2 = 0;
    gc->pipe[pn].array.use_texuv3 = 0;
-#endif
-   
+
    pipe_region_expand(gc, pn, x, y, w, h);
-   
+
    pnum = gc->pipe[pn].array.num;
    nv = pnum * 3; nc = pnum * 4; nu = pnum * 2; nt = pnum * 4;
    gc->pipe[pn].array.num += 6;
@@ -1568,19 +1735,19 @@ again:
         tx2 = ((double)(tex->x) + sx + sw) / (double)tex->pt->w;
         ty2 = ((double)(tex->y) + sy + sh) / (double)tex->pt->h;
      }
-   
+
    PUSH_VERTEX(pn, x    , y    , 0);
    PUSH_VERTEX(pn, x + w, y    , 0);
    PUSH_VERTEX(pn, x    , y + h, 0);
-   
+
    PUSH_TEXUV(pn, tx1, ty1);
    PUSH_TEXUV(pn, tx2, ty1);
    PUSH_TEXUV(pn, tx1, ty2);
-   
+
    PUSH_VERTEX(pn, x + w, y    , 0);
    PUSH_VERTEX(pn, x + w, y + h, 0);
    PUSH_VERTEX(pn, x    , y + h, 0);
-   
+
    PUSH_TEXUV(pn, tx2, ty1);
    PUSH_TEXUV(pn, tx2, ty2);
    PUSH_TEXUV(pn, tx1, ty2);
@@ -1592,8 +1759,8 @@ again:
 }
 
 void
-evas_gl_common_context_yuv_push(Evas_GL_Context *gc,
-                                Evas_GL_Texture *tex, 
+evas_gl_common_context_yuv_push(Evas_Engine_GL_Context *gc,
+                                Evas_GL_Texture *tex,
                                 double sx, double sy, double sw, double sh,
                                 int x, int y, int w, int h,
                                 int r, int g, int b, int a,
@@ -1602,129 +1769,46 @@ evas_gl_common_context_yuv_push(Evas_GL_Context *gc,
    int pnum, nv, nc, nu, nu2, nu3, nt, i;
    GLfloat tx1, tx2, ty1, ty2, t2x1, t2x2, t2y1, t2y2;
    Eina_Bool blend = 0;
-   GLuint prog = gc->shared->shader.yuv.prog;
+   GLuint prog;
    int pn = 0;
 
    if (a < 255) blend = 1;
-   
-   if ((a == 255) && (r == 255) && (g == 255) && (b == 255))
-     prog = gc->shared->shader.yuv_nomul.prog;
-   else
-     prog = gc->shared->shader.yuv.prog;
-   
-again:
-   pn = gc->state.top_pipe;
-#ifdef GLPIPES
-   if ((pn == 0) && (gc->pipe[pn].array.num == 0))
-     {
-        gc->pipe[pn].region.type = RTYPE_YUV;
-        gc->pipe[pn].shader.cur_tex = tex->pt->texture;
-        gc->pipe[pn].shader.cur_texu = tex->ptu->texture;
-        gc->pipe[pn].shader.cur_texv = tex->ptv->texture;
-        gc->pipe[pn].shader.cur_prog = prog;
-        gc->pipe[pn].shader.smooth = smooth;
-        gc->pipe[pn].shader.blend = blend;
-        gc->pipe[pn].shader.render_op = gc->dc->render_op;
-        gc->pipe[pn].shader.clip = 0;
-        gc->pipe[pn].shader.cx = 0;
-        gc->pipe[pn].shader.cy = 0;
-        gc->pipe[pn].shader.cw = 0;
-        gc->pipe[pn].shader.ch = 0;
-        gc->pipe[pn].array.line = 0;
-        gc->pipe[pn].array.use_vertex = 1;
-        gc->pipe[pn].array.use_color = 1;
-        gc->pipe[pn].array.use_texuv = 1;
-        gc->pipe[pn].array.use_texuv2 = 1;
-        gc->pipe[pn].array.use_texuv3 = 1;
-     }
-   else
-     {
-        int found = 0;
-        
-        for (i = pn; i >= 0; i--)
-          {
-             if ((gc->pipe[i].region.type == RTYPE_YUV)
-                 && (gc->pipe[i].shader.cur_tex == tex->pt->texture)
-                 && (gc->pipe[i].shader.cur_prog == gc->shared->shader.font.prog)
-                 && (gc->pipe[i].shader.smooth == smooth)
-                 && (gc->pipe[i].shader.blend == blend)
-                 && (gc->pipe[i].shader.render_op == gc->dc->render_op)
-                 && (gc->pipe[i].shader.clip == 0)
-                )
-               {
-                  found = 1;
-                  pn = i;
-                  break;
-               }
-             if (pipe_region_intersects(gc, i, x, y, w, h)) break;
-          }
-        if (!found)
-          {
-             pn = gc->state.top_pipe + 1;
-             if (pn >= gc->shared->info.tune.pipes.max)
-               {
-                  shader_array_flush(gc);
-                  goto again;
-               }
-             gc->state.top_pipe = pn;
-             gc->pipe[pn].region.type = RTYPE_YUV;
-             gc->pipe[pn].shader.cur_tex = tex->pt->texture;
-             gc->pipe[pn].shader.cur_texu = tex->ptu->texture;
-             gc->pipe[pn].shader.cur_texv = tex->ptv->texture;
-             gc->pipe[pn].shader.cur_prog = prog;
-             gc->pipe[pn].shader.smooth = smooth;
-             gc->pipe[pn].shader.blend = blend;
-             gc->pipe[pn].shader.render_op = gc->dc->render_op;
-             gc->pipe[pn].shader.clip = 0;
-             gc->pipe[pn].shader.cx = 0;
-             gc->pipe[pn].shader.cy = 0;
-             gc->pipe[pn].shader.cw = 0;
-             gc->pipe[pn].shader.ch = 0;
-             gc->pipe[pn].array.line = 0;
-             gc->pipe[pn].array.use_vertex = 1;
-             gc->pipe[pn].array.use_color = 1;
-             gc->pipe[pn].array.use_texuv = 1;
-             gc->pipe[pn].array.use_texuv2 = 1;
-             gc->pipe[pn].array.use_texuv3 = 1;
-         }
-     }
-#else   
-   if ((gc->pipe[pn].shader.cur_tex != tex->pt->texture)
-       || (gc->pipe[pn].shader.cur_prog != prog)
-       || (gc->pipe[pn].shader.smooth != smooth)
-       || (gc->pipe[pn].shader.blend != blend)
-       || (gc->pipe[pn].shader.render_op != gc->dc->render_op)
-       || (gc->pipe[pn].shader.clip != 0)
-       )
-     {
-        shader_array_flush(gc);
-        gc->pipe[pn].shader.cur_tex = tex->pt->texture;
-        gc->pipe[pn].shader.cur_texu = tex->ptu->texture;
-        gc->pipe[pn].shader.cur_texv = tex->ptv->texture;
-        gc->pipe[pn].shader.cur_prog = prog;
-        gc->pipe[pn].shader.smooth = smooth;
-        gc->pipe[pn].shader.blend = blend;
-        gc->pipe[pn].shader.render_op = gc->dc->render_op;
-        gc->pipe[pn].shader.clip = 0;
-        gc->pipe[pn].shader.cx = 0;
-        gc->pipe[pn].shader.cy = 0;
-        gc->pipe[pn].shader.cw = 0;
-        gc->pipe[pn].shader.ch = 0;
-     }
-   
+
+   prog = gc->shared->shader[evas_gl_common_shader_choice(0, NULL, r, g, b, a,
+                                                          SHADER_YUV_NOMUL, SHADER_YUV)].prog;
+
+   pn = _evas_gl_common_context_push(RTYPE_YUV,
+                                    gc, tex, NULL,
+                                    prog,
+                                    x, y, w, h,
+                                    blend,
+                                    smooth,
+                                    0, 0, 0, 0, 0);
+
    gc->pipe[pn].region.type = RTYPE_YUV;
+   gc->pipe[pn].shader.cur_tex = tex->pt->texture;
+   gc->pipe[pn].shader.cur_texu = tex->ptu->texture;
+   gc->pipe[pn].shader.cur_texv = tex->ptv->texture;
+   gc->pipe[pn].shader.cur_prog = prog;
+   gc->pipe[pn].shader.smooth = smooth;
+   gc->pipe[pn].shader.blend = blend;
+   gc->pipe[pn].shader.render_op = gc->dc->render_op;
+   gc->pipe[pn].shader.clip = 0;
+   gc->pipe[pn].shader.cx = 0;
+   gc->pipe[pn].shader.cy = 0;
+   gc->pipe[pn].shader.cw = 0;
+   gc->pipe[pn].shader.ch = 0;
    gc->pipe[pn].array.line = 0;
    gc->pipe[pn].array.use_vertex = 1;
    gc->pipe[pn].array.use_color = 1;
    gc->pipe[pn].array.use_texuv = 1;
    gc->pipe[pn].array.use_texuv2 = 1;
    gc->pipe[pn].array.use_texuv3 = 1;
-#endif
-   
+
    pipe_region_expand(gc, pn, x, y, w, h);
-   
+
    pnum = gc->pipe[pn].array.num;
-   nv = pnum * 3; nc = pnum * 4; nu = pnum * 2; 
+   nv = pnum * 3; nc = pnum * 4; nu = pnum * 2;
    nu2 = pnum * 2; nu3 = pnum * 2; nt = pnum * 4;
    gc->pipe[pn].array.num += 6;
    array_alloc(gc, pn);
@@ -1733,32 +1817,32 @@ again:
    ty1 = (sy) / (double)tex->pt->h;
    tx2 = (sx + sw) / (double)tex->pt->w;
    ty2 = (sy + sh) / (double)tex->pt->h;
-   
+
    t2x1 = ((sx) / 2) / (double)tex->ptu->w;
    t2y1 = ((sy) / 2) / (double)tex->ptu->h;
    t2x2 = ((sx + sw) / 2) / (double)tex->ptu->w;
    t2y2 = ((sy + sh) / 2) / (double)tex->ptu->h;
-   
+
    PUSH_VERTEX(pn, x    , y    , 0);
    PUSH_VERTEX(pn, x + w, y    , 0);
    PUSH_VERTEX(pn, x    , y + h, 0);
-   
+
    PUSH_TEXUV(pn, tx1, ty1);
    PUSH_TEXUV(pn, tx2, ty1);
    PUSH_TEXUV(pn, tx1, ty2);
-   
+
    PUSH_TEXUV2(pn, t2x1, t2y1);
    PUSH_TEXUV2(pn, t2x2, t2y1);
    PUSH_TEXUV2(pn, t2x1, t2y2);
-   
+
    PUSH_TEXUV3(pn, t2x1, t2y1);
    PUSH_TEXUV3(pn, t2x2, t2y1);
    PUSH_TEXUV3(pn, t2x1, t2y2);
-   
+
    PUSH_VERTEX(pn, x + w, y    , 0);
    PUSH_VERTEX(pn, x + w, y + h, 0);
    PUSH_VERTEX(pn, x    , y + h, 0);
-   
+
    PUSH_TEXUV(pn, tx2, ty1);
    PUSH_TEXUV(pn, tx2, ty2);
    PUSH_TEXUV(pn, tx1, ty2);
@@ -1777,315 +1861,381 @@ again:
      }
 }
 
-// FIXME: we don't handle mapped yuv!!!! :(
-// FIXME: we don't handle clipped maps right :(
 void
-evas_gl_common_context_image_map4_push(Evas_GL_Context *gc,
-                                       Evas_GL_Texture *tex,
-                                       RGBA_Map_Point *p,
-                                       int clip, int cx, int cy, int cw, int ch,
-                                       int r, int g, int b, int a,
-                                       Eina_Bool smooth, Eina_Bool tex_only,
-                                       Eina_Bool yuv)
+evas_gl_common_context_yuy2_push(Evas_Engine_GL_Context *gc,
+                                Evas_GL_Texture *tex,
+                                double sx, double sy, double sw, double sh,
+                                int x, int y, int w, int h,
+                                int r, int g, int b, int a,
+                                Eina_Bool smooth)
 {
    int pnum, nv, nc, nu, nu2, nu3, nt, i;
-   const int points[6] = { 0, 1, 2, 0, 2, 3 };
-   int x = 0, y = 0, w = 0, h = 0, px = 0, py = 0;
-   GLfloat tx[4], ty[4], t2x[4], t2y[4];
-   Eina_Bool blend = 1;
-   DATA32 cmul;
-   GLuint prog = gc->shared->shader.img.prog;
+   GLfloat tx1, tx2, ty1, ty2, t2x1, t2x2, t2y1, t2y2;
+   Eina_Bool blend = 0;
+   GLuint prog;
    int pn = 0;
-   
-   if (!tex->alpha) blend = 0;
+
    if (a < 255) blend = 1;
-   if ((A_VAL(&(p[0].col)) < 0xff) || (A_VAL(&(p[1].col)) < 0xff) ||
-       (A_VAL(&(p[2].col)) < 0xff) || (A_VAL(&(p[3].col)) < 0xff))
-     blend = 1;
-   
-   if (yuv)
+
+   prog = gc->shared->shader[evas_gl_common_shader_choice(0, NULL, r, g, b, a,
+                                                          SHADER_YUY2_NOMUL, SHADER_YUY2)].prog;
+
+   pn = _evas_gl_common_context_push(RTYPE_YUY2,
+                                    gc, tex, NULL,
+                                    prog,
+                                    x, y, w, h,
+                                    blend,
+                                    smooth,
+                                    0, 0, 0, 0, 0);
+
+   gc->pipe[pn].region.type = RTYPE_YUY2;
+   gc->pipe[pn].shader.cur_tex = tex->pt->texture;
+   gc->pipe[pn].shader.cur_texu = tex->ptuv->texture;
+   gc->pipe[pn].shader.cur_prog = prog;
+   gc->pipe[pn].shader.smooth = smooth;
+   gc->pipe[pn].shader.blend = blend;
+   gc->pipe[pn].shader.render_op = gc->dc->render_op;
+   gc->pipe[pn].shader.clip = 0;
+   gc->pipe[pn].shader.cx = 0;
+   gc->pipe[pn].shader.cy = 0;
+   gc->pipe[pn].shader.cw = 0;
+   gc->pipe[pn].shader.ch = 0;
+   gc->pipe[pn].array.line = 0;
+   gc->pipe[pn].array.use_vertex = 1;
+   gc->pipe[pn].array.use_color = 1;
+   gc->pipe[pn].array.use_texuv = 1;
+   gc->pipe[pn].array.use_texuv2 = 1;
+   gc->pipe[pn].array.use_texuv3 = 0;
+
+   pipe_region_expand(gc, pn, x, y, w, h);
+
+   pnum = gc->pipe[pn].array.num;
+   nv = pnum * 3; nc = pnum * 4; nu = pnum * 2;
+   nu2 = pnum * 2; nu3 = pnum * 2; nt = pnum * 4;
+   gc->pipe[pn].array.num += 6;
+   array_alloc(gc, pn);
+
+   tx1 = (sx) / (double)tex->pt->w;
+   ty1 = (sy) / (double)tex->pt->h;
+   tx2 = (sx + sw) / (double)tex->pt->w;
+   ty2 = (sy + sh) / (double)tex->pt->h;
+
+   t2x1 = sx / (double)tex->ptuv->w;
+   t2y1 = sy / (double)tex->ptuv->h;
+   t2x2 = (sx + sw) / (double)tex->ptuv->w;
+   t2y2 = (sy + sh) / (double)tex->ptuv->h;
+
+   PUSH_VERTEX(pn, x    , y    , 0);
+   PUSH_VERTEX(pn, x + w, y    , 0);
+   PUSH_VERTEX(pn, x    , y + h, 0);
+
+   PUSH_TEXUV(pn, tx1, ty1);
+   PUSH_TEXUV(pn, tx2, ty1);
+   PUSH_TEXUV(pn, tx1, ty2);
+
+   PUSH_TEXUV2(pn, t2x1, t2y1);
+   PUSH_TEXUV2(pn, t2x2, t2y1);
+   PUSH_TEXUV2(pn, t2x1, t2y2);
+
+   PUSH_VERTEX(pn, x + w, y    , 0);
+   PUSH_VERTEX(pn, x + w, y + h, 0);
+   PUSH_VERTEX(pn, x    , y + h, 0);
+
+   PUSH_TEXUV(pn, tx2, ty1);
+   PUSH_TEXUV(pn, tx2, ty2);
+   PUSH_TEXUV(pn, tx1, ty2);
+
+   PUSH_TEXUV2(pn, t2x2, t2y1);
+   PUSH_TEXUV2(pn, t2x2, t2y2);
+   PUSH_TEXUV2(pn, t2x1, t2y2);
+
+   for (i = 0; i < 6; i++)
      {
-        prog = gc->shared->shader.yuv.prog;
-        if ((a == 255) && (r == 255) && (g == 255) && (b == 255))
-          {
-             if ((p[0].col == 0xffffffff) && (p[1].col == 0xffffffff) &&
-                 (p[2].col == 0xffffffff) && (p[3].col == 0xffffffff))
-                prog = gc->shared->shader.yuv_nomul.prog;
-             else
-                prog = gc->shared->shader.yuv.prog;
-          }
-        else
-           prog = gc->shared->shader.yuv.prog;
+        PUSH_COLOR(pn, r, g, b, a);
      }
-   else
-     {
-        if (tex_only)
-          {
-             if (tex->pt->dyn.img)
-               {
-                  if ((a == 255) && (r == 255) && (g == 255) && (b == 255))
-                    {
-                       if ((p[0].col == 0xffffffff) && (p[1].col == 0xffffffff) &&
-                           (p[2].col == 0xffffffff) && (p[3].col == 0xffffffff))
-                          prog = gc->shared->shader.img_nomul.prog;
-                       else
-                          prog = gc->shared->shader.img.prog;
-                    }
-                  else
-                     prog = gc->shared->shader.img.prog;
-               }
-             else
-               {
-                  if ((a == 255) && (r == 255) && (g == 255) && (b == 255))
-                    {
-                       if ((p[0].col == 0xffffffff) && (p[1].col == 0xffffffff) &&
-                           (p[2].col == 0xffffffff) && (p[3].col == 0xffffffff))
-                          prog = gc->shared->shader.tex_nomul.prog;
-                       else
-                          prog = gc->shared->shader.tex.prog;
-                    }
-                  else
-                     prog = gc->shared->shader.tex.prog;
-               }
-          }
-        else
-          {
-             if (tex->gc->shared->info.bgra)
-               {
-                  if ((a == 255) && (r == 255) && (g == 255) && (b == 255))
-                    {
-                       if ((p[0].col == 0xffffffff) && (p[1].col == 0xffffffff) &&
-                           (p[2].col == 0xffffffff) && (p[3].col == 0xffffffff))
-                          prog = gc->shared->shader.img_bgra_nomul.prog;
-                       else
-                          prog = gc->shared->shader.img_bgra.prog;
-                    }
-                  else
-                     prog = gc->shared->shader.img_bgra.prog;
-               }
-             else
-               {
-                  if ((a == 255) && (r == 255) && (g == 255) && (b == 255))
-                    {
-                       if ((p[0].col == 0xffffffff) && (p[1].col == 0xffffffff) &&
-                           (p[2].col == 0xffffffff) && (p[3].col == 0xffffffff))
-                          prog = gc->shared->shader.img_nomul.prog;
-                       else
-                          prog = gc->shared->shader.img.prog;
-                    }
-                  else
-                     prog = gc->shared->shader.img.prog;
-               }
-          }
+}
+
+void
+evas_gl_common_context_nv12_push(Evas_Engine_GL_Context *gc,
+                                Evas_GL_Texture *tex,
+                                double sx, double sy, double sw, double sh,
+                                int x, int y, int w, int h,
+                                int r, int g, int b, int a,
+                                Eina_Bool smooth)
+{
+   int pnum, nv, nc, nu, nu2, nu3, nt, i;
+   GLfloat tx1, tx2, ty1, ty2, t2x1, t2x2, t2y1, t2y2;
+   Eina_Bool blend = 0;
+   GLuint prog;
+   int pn = 0;
+
+   if (a < 255) blend = 1;
+
+   prog = gc->shared->shader[evas_gl_common_shader_choice(0, NULL, r, g, b, a,
+                                                          SHADER_NV12_NOMUL, SHADER_NV12)].prog;
+
+   pn = _evas_gl_common_context_push(RTYPE_NV12,
+                                    gc, tex, NULL,
+                                    prog,
+                                    x, y, w, h,
+                                    blend,
+                                    smooth,
+                                    0, 0, 0, 0, 0);
+
+   gc->pipe[pn].region.type = RTYPE_NV12;
+   gc->pipe[pn].shader.cur_tex = tex->pt->texture;
+   gc->pipe[pn].shader.cur_tex_dyn = tex->pt->dyn.img;
+   gc->pipe[pn].shader.cur_texu = tex->ptuv->texture;
+   gc->pipe[pn].shader.cur_texu_dyn = tex->ptuv->dyn.img;
+   gc->pipe[pn].shader.cur_prog = prog;
+   gc->pipe[pn].shader.smooth = smooth;
+   gc->pipe[pn].shader.blend = blend;
+   gc->pipe[pn].shader.render_op = gc->dc->render_op;
+   gc->pipe[pn].shader.clip = 0;
+   gc->pipe[pn].shader.cx = 0;
+   gc->pipe[pn].shader.cy = 0;
+   gc->pipe[pn].shader.cw = 0;
+   gc->pipe[pn].shader.ch = 0;
+   gc->pipe[pn].array.line = 0;
+   gc->pipe[pn].array.use_vertex = 1;
+   gc->pipe[pn].array.use_color = 1;
+   gc->pipe[pn].array.use_texuv = 1;
+   gc->pipe[pn].array.use_texuv2 = 1;
+   gc->pipe[pn].array.use_texuv3 = 0;
+
+   pipe_region_expand(gc, pn, x, y, w, h);
+
+   pnum = gc->pipe[pn].array.num;
+   nv = pnum * 3; nc = pnum * 4; nu = pnum * 2;
+   nu2 = pnum * 2; nu3 = pnum * 2; nt = pnum * 4;
+   gc->pipe[pn].array.num += 6;
+   array_alloc(gc, pn);
+
+   tx1 = (sx) / (double)tex->pt->w;
+   ty1 = (sy) / (double)tex->pt->h;
+   tx2 = (sx + sw) / (double)tex->pt->w;
+   ty2 = (sy + sh) / (double)tex->pt->h;
+
+   t2x1 = sx / (double)tex->ptuv->w;
+   t2y1 = sy / (double)tex->ptuv->h;
+   t2x2 = (sx + sw) / (double)tex->ptuv->w;
+   t2y2 = (sy + sh) / (double)tex->ptuv->h;
+
+   PUSH_VERTEX(pn, x    , y    , 0);
+   PUSH_VERTEX(pn, x + w, y    , 0);
+   PUSH_VERTEX(pn, x    , y + h, 0);
+
+   PUSH_TEXUV(pn, tx1, ty1);
+   PUSH_TEXUV(pn, tx2, ty1);
+   PUSH_TEXUV(pn, tx1, ty2);
+
+   PUSH_TEXUV2(pn, t2x1, t2y1);
+   PUSH_TEXUV2(pn, t2x2, t2y1);
+   PUSH_TEXUV2(pn, t2x1, t2y2);
+
+   PUSH_VERTEX(pn, x + w, y    , 0);
+   PUSH_VERTEX(pn, x + w, y + h, 0);
+   PUSH_VERTEX(pn, x    , y + h, 0);
+
+   PUSH_TEXUV(pn, tx2, ty1);
+   PUSH_TEXUV(pn, tx2, ty2);
+   PUSH_TEXUV(pn, tx1, ty2);
+
+   PUSH_TEXUV2(pn, t2x2, t2y1);
+   PUSH_TEXUV2(pn, t2x2, t2y2);
+   PUSH_TEXUV2(pn, t2x1, t2y2);
+
+   for (i = 0; i < 6; i++)
+     {
+        PUSH_COLOR(pn, r, g, b, a);
      }
-   
-//   /*xxx*/ shader_array_flush(gc);
-again:
-   pn = gc->state.top_pipe;
-#ifdef GLPIPES
-   if ((pn == 0) && (gc->pipe[pn].array.num == 0))
+}
+
+void
+evas_gl_common_context_image_map_push(Evas_Engine_GL_Context *gc,
+                                      Evas_GL_Texture *tex,
+                                      int npoints,
+                                      RGBA_Map_Point *p,
+                                      int clip, int cx, int cy, int cw, int ch,
+                                      int r, int g, int b, int a,
+                                     Eina_Bool smooth, Eina_Bool tex_only,
+                                     Evas_Colorspace cspace)
+{
+   int pnum, nv, nc, nu, nu2, nu3, nt, i;
+   const int points[6] = { 0, 1, 2, 0, 2, 3 };
+   int x = 0, y = 0, w = 0, h = 0, px = 0, py = 0;
+   GLfloat tx[4], ty[4], t2x[4], t2y[4];
+   Eina_Bool blend = 1;
+   DATA32 cmul;
+   GLuint prog = gc->shared->shader[SHADER_IMG].prog;
+   Eina_Bool utexture = EINA_FALSE;
+   Eina_Bool uvtexture = EINA_FALSE;
+   int pn = 0;
+   int flat = 0;
+
+   if (!tex->alpha) blend = 0;
+   if (a < 255) blend = 1;
+   if (npoints != 4)
      {
-        gc->pipe[pn].region.type = RTYPE_MAP;
-        gc->pipe[pn].shader.cur_tex = tex->pt->texture;
-        if (yuv)
-          {
-             gc->pipe[pn].shader.cur_texu = tex->ptu->texture;
-             gc->pipe[pn].shader.cur_texv = tex->ptv->texture;
-          }
-        gc->pipe[pn].shader.cur_prog = prog;
-        gc->pipe[pn].shader.smooth = smooth;
-        gc->pipe[pn].shader.blend = blend;
-        gc->pipe[pn].shader.render_op = gc->dc->render_op;
-        gc->pipe[pn].shader.clip = clip;
-        gc->pipe[pn].shader.cx = cx;
-        gc->pipe[pn].shader.cy = cy;
-        gc->pipe[pn].shader.cw = cw;
-        gc->pipe[pn].shader.ch = ch;
-        gc->pipe[pn].array.line = 0;
-        gc->pipe[pn].array.use_vertex = 1;
-        gc->pipe[pn].array.use_color = 1;
-        gc->pipe[pn].array.use_texuv = 1;
-        if (yuv)
-          {
-             gc->pipe[pn].array.use_texuv2 = 1;
-             gc->pipe[pn].array.use_texuv3 = 1;
-          }
-        else
-          {
-             gc->pipe[pn].array.use_texuv2 = 0;
-             gc->pipe[pn].array.use_texuv3 = 0;
-          }
+        // FIXME: nash - you didn't fix this for n points. its still all
+        // 4 point stuff!!! grrrr.
+        abort();
      }
-   else
+   if ((A_VAL(&(p[0].col)) < 0xff) || (A_VAL(&(p[1].col)) < 0xff) ||
+       (A_VAL(&(p[2].col)) < 0xff) || (A_VAL(&(p[3].col)) < 0xff))
+     blend = 1;
+
+   if ((p[0].z == p[1].z) && (p[1].z == p[2].z) && (p[2].z == p[3].z))
+      flat = 1;
+
+   if (!clip) cx = cy = cw = ch = 0;
+
+   if (!flat)
      {
-        int found = 0;
-        
-        for (i = pn; i >= 0; i--)
-          {
-             if ((gc->pipe[i].region.type == RTYPE_MAP)
-                 && (gc->pipe[i].shader.cur_tex == tex->pt->texture)
-                 && (gc->pipe[i].shader.cur_prog == prog)
-                 && (gc->pipe[i].shader.smooth == smooth)
-                 && (gc->pipe[i].shader.blend == blend)
-                 && (gc->pipe[i].shader.render_op == gc->dc->render_op)
-                 && (gc->pipe[i].shader.clip == clip)
-                 && (gc->pipe[i].shader.cx == cx)
-                 && (gc->pipe[i].shader.cy == cy)
-                 && (gc->pipe[i].shader.cw == cw)
-                 && (gc->pipe[i].shader.ch == ch)
-                )
-               {
-                  found = 1;
-                  pn = i;
-                  break;
-               }
-             if (pipe_region_intersects(gc, i, x, y, w, h)) break;
-          }
-        if (!found)
-          {
-             pn = gc->state.top_pipe + 1;
-             if (pn >= gc->shared->info.tune.pipes.max)
-               {
-                  shader_array_flush(gc);
-                  goto again;
-               }
-             gc->state.top_pipe = pn;
-             gc->pipe[pn].region.type = RTYPE_MAP;
-             gc->pipe[pn].shader.cur_tex = tex->pt->texture;
-             if (yuv)
-               {
-                  gc->pipe[pn].shader.cur_texu = tex->ptu->texture;
-                  gc->pipe[pn].shader.cur_texv = tex->ptv->texture;
-               }
-             gc->pipe[pn].shader.cur_prog = prog;
-             gc->pipe[pn].shader.smooth = smooth;
-             gc->pipe[pn].shader.blend = blend;
-             gc->pipe[pn].shader.render_op = gc->dc->render_op;
-             gc->pipe[pn].shader.clip = clip;
-             gc->pipe[pn].shader.cx = cx;
-             gc->pipe[pn].shader.cy = cy;
-             gc->pipe[pn].shader.cw = cw;
-             gc->pipe[pn].shader.ch = ch;
-             gc->pipe[pn].array.line = 0;
-             gc->pipe[pn].array.use_vertex = 1;
-             gc->pipe[pn].array.use_color = 1;
-             gc->pipe[pn].array.use_texuv = 1;
-             if (yuv)
-               {
-                  gc->pipe[pn].array.use_texuv2 = 1;
-                  gc->pipe[pn].array.use_texuv3 = 1;
-               }
+        if (p[0].foc <= 0) flat = 1;
+     }
+
+   switch (cspace)
+     {
+      case EVAS_COLORSPACE_YCBCR422P601_PL:
+      case EVAS_COLORSPACE_YCBCR422P709_PL:
+         prog = gc->shared->shader[evas_gl_common_shader_choice(npoints, p, r, g, b, a,
+                                                                SHADER_YUV_NOMUL, SHADER_YUV)].prog;
+         utexture = EINA_TRUE;
+         break;
+      case EVAS_COLORSPACE_YCBCR422601_PL:
+         prog = gc->shared->shader[evas_gl_common_shader_choice(npoints, p, r, g, b, a,
+                                                                SHADER_YUY2_NOMUL, SHADER_YUY2)].prog;
+         uvtexture = EINA_TRUE;
+         break;
+      case EVAS_COLORSPACE_YCBCR420NV12601_PL:
+      case EVAS_COLORSPACE_YCBCR420TM12601_PL:
+         prog = gc->shared->shader[evas_gl_common_shader_choice(npoints, p, r, g, b, a,
+                                                                SHADER_NV12_NOMUL, SHADER_NV12)].prog;
+         uvtexture = EINA_TRUE;
+         break;
+
+      default:
+         if (tex_only)
+           {
+              if (tex->pt->dyn.img)
+                {
+                   prog = gc->shared->shader[evas_gl_common_shader_choice(npoints, p, r, g, b, a,
+                                                                          SHADER_IMG_BGRA_NOMUL, SHADER_IMG_BGRA)].prog;
+                }
+              else
+                {
+                   prog = gc->shared->shader[evas_gl_common_shader_choice(npoints, p, r, g, b, a,
+                                                                          SHADER_TEX_NOMUL, SHADER_TEX)].prog;
+                }
+           }
+         else
+           {
+              if (tex->gc->shared->info.bgra)
+                {
+                   prog = gc->shared->shader[evas_gl_common_shader_choice(npoints, p, r, g, b, a,
+                                                                          SHADER_IMG_BGRA_NOMUL,
+                                                                          SHADER_IMG_BGRA)].prog;
+                }
              else
                {
-                  gc->pipe[pn].array.use_texuv2 = 0;
-                  gc->pipe[pn].array.use_texuv3 = 0;
+                  prog = gc->shared->shader[evas_gl_common_shader_choice(npoints, p, r, g, b, a,
+                                                                         SHADER_IMG_NOMUL,
+                                                                         SHADER_IMG)].prog;
                }
-         }
+           }
      }
-   if ((tex->im) && (tex->im->native.data))
+
+   x = w = (p[0].x >> FP);
+   y = h = (p[0].y >> FP);
+   for (i = 0; i < 4; i++)
      {
-        if (gc->pipe[pn].array.im != tex->im)
+        tx[i] = ((double)(tex->x) + (((double)p[i].u) / FP1)) /
+          (double)tex->pt->w;
+        ty[i] = ((double)(tex->y) + (((double)p[i].v) / FP1)) /
+          (double)tex->pt->h;
+        px = (p[i].x >> FP);
+        if      (px < x) x = px;
+        else if (px > w) w = px;
+        py = (p[i].y >> FP);
+        if      (py < y) y = py;
+        else if (py > h) h = py;
+        if (utexture)
           {
-             shader_array_flush(gc);
-             pn = gc->state.top_pipe;
-             gc->pipe[pn].array.im = tex->im;
-             goto again;
+             t2x[i] = ((((double)p[i].u / 2) / FP1)) / (double)tex->ptu->w;
+             t2y[i] = ((((double)p[i].v / 2) / FP1)) / (double)tex->ptu->h;
+          }
+        else if (uvtexture)
+          {
+             t2x[i] = ((((double)p[i].u / 2) / FP1)) / (double)tex->ptuv->w;
+             t2y[i] = ((((double)p[i].v / 2) / FP1)) / (double)tex->ptuv->h;
           }
      }
-   if (tex->pt->dyn.img)
+   w = w - x;
+   h = h - y;
+
+   if (clip)
      {
-        if (gc->pipe[pn].array.im != tex->im)
+        int nx = x, ny = y, nw = w, nh = h;
+
+        RECTS_CLIP_TO_RECT(nx, ny, nw, nh, cx, cy, cw, ch);
+        if ((nx == x) && (ny == y) && (nw == w) && (nh == h))
           {
-             shader_array_flush(gc);
-             pn = gc->state.top_pipe;
-             gc->pipe[pn].array.im = tex->im;
-             goto again;
+             clip = 0; cx = 0; cy = 0; cw = 0; ch = 0;
           }
+        x = nx; y = nw; w = nw; h = nh;
      }
-#else   
-   if ((gc->pipe[pn].shader.cur_tex != tex->pt->texture)
-       || (gc->pipe[pn].shader.cur_prog != prog)
-       || (gc->pipe[pn].shader.smooth != smooth)
-       || (gc->pipe[pn].shader.blend != blend)
-       || (gc->pipe[pn].shader.render_op != gc->dc->render_op)
-       || (gc->pipe[pn].shader.clip != clip)
-       || (gc->pipe[pn].shader.cx != cx)
-       || (gc->pipe[pn].shader.cy != cy)
-       || (gc->pipe[pn].shader.cw != cw)
-       || (gc->pipe[pn].shader.ch != ch)
-       )
+
+   if (!flat)
      {
         shader_array_flush(gc);
-        gc->pipe[pn].shader.cur_tex = tex->pt->texture;
-        gc->pipe[pn].shader.cur_prog = prog;
-        gc->pipe[pn].shader.smooth = smooth;
-        gc->pipe[pn].shader.blend = blend;
-        gc->pipe[pn].shader.render_op = gc->dc->render_op;
-        gc->pipe[pn].shader.clip = clip;
-        gc->pipe[pn].shader.cx = cx;
-        gc->pipe[pn].shader.cy = cy;
-        gc->pipe[pn].shader.cw = cw;
-        gc->pipe[pn].shader.ch = ch;
+        gc->foc = p[0].foc >> FP;
+        gc->z0 = p[0].z0 >> FP;
+        gc->px = p[0].px >> FP;
+        gc->py = p[0].py >> FP;
+        gc->change.size = 1;
+        _evas_gl_common_viewport_set(gc);
      }
-   if ((tex->im) && (tex->im->native.data))
+
+   pn = _evas_gl_common_context_push(RTYPE_MAP,
+                                    gc, tex, NULL,
+                                    prog,
+                                    x, y, w, h,
+                                    blend,
+                                    smooth,
+                                    clip, cx, cy, cw, ch);
+   gc->pipe[pn].region.type = RTYPE_MAP;
+   gc->pipe[pn].shader.cur_tex = tex->pt->texture;
+   if (utexture)
      {
-        if (gc->pipe[pn].array.im != tex->im)
-          {
-             shader_array_flush(gc);
-             gc->pipe[pn].array.im = tex->im;
-          }
+       gc->pipe[pn].shader.cur_texu = tex->ptu->texture;
+       gc->pipe[pn].shader.cur_texu_dyn = tex->ptu->dyn.img;
+       gc->pipe[pn].shader.cur_texv = tex->ptv->texture;
+       gc->pipe[pn].shader.cur_texv_dyn = tex->ptv->dyn.img;
      }
-   if (tex->pt->dyn.img)
+   else if (uvtexture)
      {
-        if (gc->pipe[pn].array.im != tex->im)
-          {
-             shader_array_flush(gc);
-             gc->pipe[pn].array.im = tex->im;
-          }
+       gc->pipe[pn].shader.cur_texu = tex->ptuv->texture;
+       gc->pipe[pn].shader.cur_texu_dyn = tex->ptuv->dyn.img;
      }
-
-   gc->pipe[pn].region.type = RTYPE_MAP;
+   gc->pipe[pn].shader.cur_prog = prog;
+   gc->pipe[pn].shader.smooth = smooth;
+   gc->pipe[pn].shader.blend = blend;
+   gc->pipe[pn].shader.render_op = gc->dc->render_op;
+   gc->pipe[pn].shader.clip = clip;
+   gc->pipe[pn].shader.cx = cx;
+   gc->pipe[pn].shader.cy = cy;
+   gc->pipe[pn].shader.cw = cw;
+   gc->pipe[pn].shader.ch = ch;
    gc->pipe[pn].array.line = 0;
    gc->pipe[pn].array.use_vertex = 1;
    gc->pipe[pn].array.use_color = 1;
    gc->pipe[pn].array.use_texuv = 1;
-   if (yuv)
-     {
-        gc->pipe[pn].array.use_texuv2 = 1;
-        gc->pipe[pn].array.use_texuv3 = 1;
-     }
-   else
-     {
-        gc->pipe[pn].array.use_texuv2 = 0;
-        gc->pipe[pn].array.use_texuv3 = 0;
-     }
-#endif   
-   
-   x = w = (p[points[0]].x >> FP);
-   y = h = (p[points[0]].y >> FP);
-   for (i = 0; i < 4; i++)
-     {
-        tx[i] = ((double)(tex->x) + (((double)p[i].u) / FP1)) /
-          (double)tex->pt->w;
-        ty[i] = ((double)(tex->y) + (((double)p[i].v) / FP1)) / 
-          (double)tex->pt->h;
-        px = (p[points[i]].x >> FP);
-        if      (px < x) x = px;
-        else if (px > w) w = py;
-        py = (p[points[i]].y >> FP);
-        if      (py < y) y = py;
-        else if (py > h) h = py;
-        if (yuv)
-          {
-             t2x[i] = ((((double)p[i].u / 2) / FP1)) / (double)tex->ptu->w;
-             t2y[i] = ((((double)p[i].v / 2) / FP1)) / (double)tex->ptu->h;
-          }
-     }
-   w = w - x;
-   h = h - y;
-   
+   gc->pipe[pn].array.use_texuv2 = (utexture || uvtexture) ? 1 : 0;
+   gc->pipe[pn].array.use_texuv3 = (utexture) ? 1 : 0;
+
    pipe_region_expand(gc, pn, x, y, w, h);
-   
+
    pnum = gc->pipe[pn].array.num;
    nv = pnum * 3; nc = pnum * 4; nu = pnum * 2; nu2 = pnum * 2;
    nu2 = pnum * 2; nu3 = pnum * 2; nt = pnum * 4;
@@ -2094,22 +2244,37 @@ again:
 
    if ((tex->im) && (tex->im->native.data) && (!tex->im->native.yinvert))
      {
-        // FIXME: handle yinvert
-        fprintf(stderr, "EVAS GL ENGINE ERROR: not handling inverted y case for map4\n");
+        for (i = 0; i < 4; i++)
+          {
+             ty[i] = 1.0 - ty[i];
+             if (utexture || uvtexture)
+                t2y[i] = 1.0 - t2y[i];
+          }
      }
-   
+
    cmul = ARGB_JOIN(a, r, g, b);
    for (i = 0; i < 6; i++)
      {
         DATA32 cl = MUL4_SYM(cmul, p[points[i]].col);
-        PUSH_VERTEX(pn,
-                    (p[points[i]].x >> FP), 
-                    (p[points[i]].y >> FP),
-                    0);
+        if (flat)
+          {
+             PUSH_VERTEX(pn,
+                         (p[points[i]].x >> FP),
+                         (p[points[i]].y >> FP),
+                         0);
+          }
+        else
+          {
+             PUSH_VERTEX(pn,
+                         (p[points[i]].fx) + gc->shared->ax,
+                         (p[points[i]].fy) + gc->shared->ay,
+                         (p[points[i]].fz)
+                         + (gc->shared->foc - gc->shared->z0));
+          }
         PUSH_TEXUV(pn,
                    tx[points[i]],
                    ty[points[i]]);
-        if (yuv)
+        if (utexture)
           {
              PUSH_TEXUV2(pn,
                          t2x[points[i]],
@@ -2118,30 +2283,81 @@ again:
                          t2x[points[i]],
                          t2y[points[i]]);
           }
-        
+        else if (uvtexture)
+          {
+             PUSH_TEXUV2(pn,
+                         t2x[points[i]],
+                         t2y[points[i]]);
+          }
+
         PUSH_COLOR(pn,
                    R_VAL(&cl),
                    G_VAL(&cl),
                    B_VAL(&cl),
                    A_VAL(&cl));
      }
+   if (!flat)
+     {
+        shader_array_flush(gc);
+        gc->foc = 0;
+        gc->z0 = 0;
+        gc->px = 0;
+        gc->py = 0;
+        gc->change.size = 1;
+        _evas_gl_common_viewport_set(gc);
+     }
 }
 
 void
-evas_gl_common_context_flush(Evas_GL_Context *gc)
+evas_gl_common_context_flush(Evas_Engine_GL_Context *gc)
 {
    shader_array_flush(gc);
 }
 
 static void
-shader_array_flush(Evas_GL_Context *gc)
+scissor_rot(Evas_Engine_GL_Context *gc __UNUSED__,
+            int rot, int gw, int gh, int cx, int cy, int cw, int ch)
 {
-   int i;
-   
+   switch (rot)
+     {
+      case 0: // UP this way: ^
+        glScissor(cx, cy, cw, ch);
+        break;
+      case 90: // UP this way: <
+        glScissor(gh - (cy + ch), cx, ch, cw);
+        break;
+      case 180: // UP this way: v
+        glScissor(gw - (cx + cw), gh - (cy + ch), cw, ch);
+        break;
+      case 270: // UP this way: >
+        glScissor(cy, gw - (cx + cw), ch, cw);
+        break;
+      default: // assume up is up
+        glScissor(cx, cy, cw, ch);
+        break;
+     }
+}
+
+static void
+shader_array_flush(Evas_Engine_GL_Context *gc)
+{
+   int i, gw, gh, setclip, cy, fbo = 0, done = 0;
+
+   if (!gc->havestuff) return;
+   gw = gc->w;
+   gh = gc->h;
+   if (!((gc->pipe[0].shader.surface == gc->def_surface) ||
+         (!gc->pipe[0].shader.surface)))
+     {
+        gw = gc->pipe[0].shader.surface->w;
+        gh = gc->pipe[0].shader.surface->h;
+        fbo = 1;
+     }
    for (i = 0; i < gc->shared->info.tune.pipes.max; i++)
      {
         if (gc->pipe[i].array.num <= 0) break;
-
+        setclip = 0;
+        done++;
         gc->flushnum++;
         GLERR(__FUNCTION__, __FILE__, __LINE__, "<flush err>");
         if (gc->pipe[i].shader.cur_prog != gc->state.current.cur_prog)
@@ -2149,7 +2365,7 @@ shader_array_flush(Evas_GL_Context *gc)
              glUseProgram(gc->pipe[i].shader.cur_prog);
              GLERR(__FUNCTION__, __FILE__, __LINE__, "");
           }
-        
+
         if (gc->pipe[i].shader.cur_tex != gc->state.current.cur_tex)
           {
 #if 0
@@ -2178,12 +2394,12 @@ shader_array_flush(Evas_GL_Context *gc)
                      (GL_TEXTURE_2D, gc->pipe[i].array.im->tex->pt->dyn.img);
                }
              else
-#endif                
+#endif
                {
                   if (!gc->pipe[i].array.im->native.loose)
                     {
                        if (gc->pipe[i].array.im->native.func.bind)
-                          gc->pipe[i].array.im->native.func.bind(gc->pipe[i].array.im->native.func.data, 
+                          gc->pipe[i].array.im->native.func.bind(gc->pipe[i].array.im->native.func.data,
                                                                  gc->pipe[i].array.im);
                     }
                }
@@ -2271,36 +2487,52 @@ shader_array_flush(Evas_GL_Context *gc)
                   GLERR(__FUNCTION__, __FILE__, __LINE__, "");
                }
           }
-        /* hmmm this breaks things. must find out why!   
-         if (gc->pipe[i].shader.clip != gc->state.current.clip)
-         {
-         if (gc->pipe[i].shader.clip)
-         glEnable(GL_SCISSOR_TEST);
-         else
-         {
-         glDisable(GL_SCISSOR_TEST);
-         //             glScissor(0, 0, 0, 0);
-         }
-         }
-         if (gc->pipe[i].shader.clip)
-         {
-         if ((gc->pipe[i].shader.cx != gc->state.current.cx) ||
-         (gc->pipe[i].shader.cx != gc->state.current.cx) ||
-         (gc->pipe[i].shader.cx != gc->state.current.cx) ||
-         (gc->pipe[i].shader.cx != gc->state.current.cx))
-         {
-         glScissor(gc->pipe[i].shader.cx, 
-         gc->h - gc->pipe[i].shader.cy - gc->pipe[i].shader.ch,
-         gc->pipe[i].shader.cw,
-         gc->pipe[i].shader.ch);
-         }
-         //                    gc->pipe[i].clip.x,
-         //                    gc->h - gc->pipe[i].clip.y - gc->pipe[i].clip.h,
-         //                    gc->pipe[i].clip.w,
-         //                    gc->pipe[i].clip.h);
-         * 
-         }
-         */
+        if (gc->pipe[i].shader.clip != gc->state.current.clip)
+          {
+
+             if (gc->pipe[i].shader.clip)
+               {
+                  cy = gh - gc->pipe[i].shader.cy - gc->pipe[i].shader.ch;
+                  if (fbo) cy = gc->pipe[i].shader.cy;
+                  glEnable(GL_SCISSOR_TEST);
+                  if (!fbo)
+                     scissor_rot(gc, gc->rot, gw, gh,
+                                 gc->pipe[i].shader.cx,
+                                 cy,
+                                 gc->pipe[i].shader.cw,
+                                 gc->pipe[i].shader.ch);
+                  else
+                     glScissor(gc->pipe[i].shader.cx, cy,
+                               gc->pipe[i].shader.cw, gc->pipe[i].shader.ch);
+                  setclip = 1;
+               }
+             else
+               {
+                  glDisable(GL_SCISSOR_TEST);
+                  glScissor(0, 0, 0, 0);
+               }
+          }
+        if ((gc->pipe[i].shader.clip) && (!setclip))
+          {
+             if ((gc->pipe[i].shader.cx != gc->state.current.cx) ||
+                 (gc->pipe[i].shader.cy != gc->state.current.cy) ||
+                 (gc->pipe[i].shader.cw != gc->state.current.cw) ||
+                 (gc->pipe[i].shader.ch != gc->state.current.ch))
+               {
+                  cy = gh - gc->pipe[i].shader.cy - gc->pipe[i].shader.ch;
+                  if (fbo) cy = gc->pipe[i].shader.cy;
+                  if (!fbo)
+                     scissor_rot(gc, gc->rot, gw, gh,
+                                 gc->pipe[i].shader.cx,
+                                 cy,
+                                 gc->pipe[i].shader.cw,
+                                 gc->pipe[i].shader.ch);
+                  else
+                     glScissor(gc->pipe[i].shader.cx, cy,
+                               gc->pipe[i].shader.cw, gc->pipe[i].shader.ch);
+               }
+          }
+
         glVertexAttribPointer(SHAD_VERTEX, 3, GL_SHORT, GL_FALSE, 0, gc->pipe[i].array.vertex);
         GLERR(__FUNCTION__, __FILE__, __LINE__, "");
         glVertexAttribPointer(SHAD_COLOR, 4, GL_UNSIGNED_BYTE, GL_TRUE, 0, gc->pipe[i].array.color);
@@ -2317,12 +2549,12 @@ shader_array_flush(Evas_GL_Context *gc)
              glDisableVertexAttribArray(SHAD_TEXUV);
              GLERR(__FUNCTION__, __FILE__, __LINE__, "");
           }
-        
+
         if (gc->pipe[i].array.line)
           {
              glDisableVertexAttribArray(SHAD_TEXUV);
              GLERR(__FUNCTION__, __FILE__, __LINE__, "");
-             glDisableVertexAttribArray(SHAD_TEXUV2); 
+             glDisableVertexAttribArray(SHAD_TEXUV2);
              GLERR(__FUNCTION__, __FILE__, __LINE__, "");
              glDisableVertexAttribArray(SHAD_TEXUV3);
              GLERR(__FUNCTION__, __FILE__, __LINE__, "");
@@ -2331,6 +2563,23 @@ shader_array_flush(Evas_GL_Context *gc)
           }
         else
           {
+            if (gc->pipe[i].array.use_texm)
+              {
+                 glEnableVertexAttribArray(SHAD_TEXM);
+                  GLERR(__FUNCTION__, __FILE__, __LINE__, "");
+                  glVertexAttribPointer(SHAD_TEXM, 2, GL_FLOAT, GL_FALSE, 0, gc->pipe[i].array.texm);
+                  GLERR(__FUNCTION__, __FILE__, __LINE__, "");
+                  glActiveTexture(GL_TEXTURE1);
+                  GLERR(__FUNCTION__, __FILE__, __LINE__, "");
+                  glBindTexture(GL_TEXTURE_2D, gc->pipe[i].shader.cur_texm);
+                  GLERR(__FUNCTION__, __FILE__, __LINE__, "");
+                  glActiveTexture(GL_TEXTURE0);
+                  GLERR(__FUNCTION__, __FILE__, __LINE__, "");
+              }
+            else
+              {
+                  glDisableVertexAttribArray(SHAD_TEXM);
+              }
              if ((gc->pipe[i].array.use_texuv2) && (gc->pipe[i].array.use_texuv3))
                {
                   glEnableVertexAttribArray(SHAD_TEXUV2);
@@ -2341,14 +2590,24 @@ shader_array_flush(Evas_GL_Context *gc)
                   GLERR(__FUNCTION__, __FILE__, __LINE__, "");
                   glVertexAttribPointer(SHAD_TEXUV3, 2, GL_FLOAT, GL_FALSE, 0, gc->pipe[i].array.texuv3);
                   GLERR(__FUNCTION__, __FILE__, __LINE__, "");
+
                   glActiveTexture(GL_TEXTURE1);
                   GLERR(__FUNCTION__, __FILE__, __LINE__, "");
                   glBindTexture(GL_TEXTURE_2D, gc->pipe[i].shader.cur_texu);
                   GLERR(__FUNCTION__, __FILE__, __LINE__, "");
+#if defined (GLES_VARIETY_S3C6410) || defined (GLES_VARIETY_SGX)
+                  if (gc->pipe[i].shader.cur_texu_dyn)
+                   secsym_glEGLImageTargetTexture2DOES(GL_TEXTURE_2D, gc->pipe[i].shader.cur_texu_dyn);
+#endif
+                  
                   glActiveTexture(GL_TEXTURE2);
                   GLERR(__FUNCTION__, __FILE__, __LINE__, "");
                   glBindTexture(GL_TEXTURE_2D, gc->pipe[i].shader.cur_texv);
                   GLERR(__FUNCTION__, __FILE__, __LINE__, "");
+#if defined (GLES_VARIETY_S3C6410) || defined (GLES_VARIETY_SGX)
+                 if (gc->pipe[i].shader.cur_texv_dyn)
+                   secsym_glEGLImageTargetTexture2DOES(GL_TEXTURE_2D, gc->pipe[i].shader.cur_texv_dyn);
+#endif
                   glActiveTexture(GL_TEXTURE0);
                   GLERR(__FUNCTION__, __FILE__, __LINE__, "");
                }
@@ -2358,6 +2617,17 @@ shader_array_flush(Evas_GL_Context *gc)
                   GLERR(__FUNCTION__, __FILE__, __LINE__, "");
                   glVertexAttribPointer(SHAD_TEXUV2, 2, GL_FLOAT, GL_FALSE, 0, gc->pipe[i].array.texuv2);
                   GLERR(__FUNCTION__, __FILE__, __LINE__, "");
+
+                  glActiveTexture(GL_TEXTURE1);
+                  GLERR(__FUNCTION__, __FILE__, __LINE__, "");
+                  glBindTexture(GL_TEXTURE_2D, gc->pipe[i].shader.cur_texu);
+                  GLERR(__FUNCTION__, __FILE__, __LINE__, "");
+#if defined (GLES_VARIETY_S3C6410) || defined (GLES_VARIETY_SGX)
+                 if (gc->pipe[i].shader.cur_texu_dyn)
+                   secsym_glEGLImageTargetTexture2DOES(GL_TEXTURE_2D, gc->pipe[i].shader.cur_texu_dyn);
+#endif
+                  glActiveTexture(GL_TEXTURE0);
+                  GLERR(__FUNCTION__, __FILE__, __LINE__, "");
                }
              else
                {
@@ -2366,7 +2636,21 @@ shader_array_flush(Evas_GL_Context *gc)
                   glDisableVertexAttribArray(SHAD_TEXUV3);
                   GLERR(__FUNCTION__, __FILE__, __LINE__, "");
                }
-             
+             if (dbgflushnum)
+               {
+                  const char *types[6] =
+                    {"----", "RECT", "IMAG", "FONT", "YUV-", "MAP"};
+                  printf("  DRAW#%3i %4i -> %p[%4ix%4i] @ %4ix%4i -{ tex %4i type %s }-\n",
+                         i,
+                         gc->pipe[i].array.num / 6,
+                         gc->pipe[0].shader.surface,
+                         gc->pipe[0].shader.surface->w,
+                         gc->pipe[0].shader.surface->h,
+                         gw, gh,
+                         gc->pipe[i].shader.cur_tex,
+                         types[gc->pipe[i].region.type]
+                        );
+               }
              glDrawArrays(GL_TRIANGLES, 0, gc->pipe[i].array.num);
              GLERR(__FUNCTION__, __FILE__, __LINE__, "");
           }
@@ -2375,43 +2659,72 @@ shader_array_flush(Evas_GL_Context *gc)
              if (!gc->pipe[i].array.im->native.loose)
                {
                   if (gc->pipe[i].array.im->native.func.unbind)
-                     gc->pipe[i].array.im->native.func.unbind(gc->pipe[i].array.im->native.func.data, 
+                     gc->pipe[i].array.im->native.func.unbind(gc->pipe[i].array.im->native.func.data,
                                                               gc->pipe[i].array.im);
                }
              gc->pipe[i].array.im = NULL;
           }
-        
-        gc->state.current.cur_prog = gc->pipe[i].shader.cur_prog;
-        gc->state.current.cur_tex = gc->pipe[i].shader.cur_tex;
-        gc->state.current.blend = gc->pipe[i].shader.blend;
-        gc->state.current.smooth = gc->pipe[i].shader.smooth;
+
+        gc->state.current.cur_prog  = gc->pipe[i].shader.cur_prog;
+        gc->state.current.cur_tex   = gc->pipe[i].shader.cur_tex;
         gc->state.current.render_op = gc->pipe[i].shader.render_op;
-        gc->state.current.clip = gc->pipe[i].shader.clip;
-        gc->state.current.cx = gc->pipe[i].shader.cx;
-        gc->state.current.cy = gc->pipe[i].shader.cy;
-        gc->state.current.cw = gc->pipe[i].shader.cw;
-        gc->state.current.ch = gc->pipe[i].shader.ch;
-        
+        gc->state.current.cx        = gc->pipe[i].shader.cx;
+        gc->state.current.cy        = gc->pipe[i].shader.cy;
+        gc->state.current.cw        = gc->pipe[i].shader.cw;
+        gc->state.current.ch        = gc->pipe[i].shader.ch;
+        gc->state.current.smooth    = gc->pipe[i].shader.smooth;
+        gc->state.current.blend     = gc->pipe[i].shader.blend;
+        gc->state.current.clip      = gc->pipe[i].shader.clip;
+
         if (gc->pipe[i].array.vertex) free(gc->pipe[i].array.vertex);
         if (gc->pipe[i].array.color) free(gc->pipe[i].array.color);
         if (gc->pipe[i].array.texuv) free(gc->pipe[i].array.texuv);
+        if (gc->pipe[i].array.texm) free(gc->pipe[i].array.texm);
         if (gc->pipe[i].array.texuv2) free(gc->pipe[i].array.texuv2);
         if (gc->pipe[i].array.texuv3) free(gc->pipe[i].array.texuv3);
-        
+
         gc->pipe[i].array.vertex = NULL;
         gc->pipe[i].array.color = NULL;
         gc->pipe[i].array.texuv = NULL;
+        gc->pipe[i].array.texm = NULL;
         gc->pipe[i].array.texuv2 = NULL;
         gc->pipe[i].array.texuv3 = NULL;
 
         gc->pipe[i].array.num = 0;
         gc->pipe[i].array.alloc = 0;
-        
+
         gc->pipe[i].region.x = 0;
         gc->pipe[i].region.y = 0;
         gc->pipe[i].region.w = 0;
         gc->pipe[i].region.h = 0;
         gc->pipe[i].region.type = 0;
      }
-    gc->state.top_pipe = 0;
+   gc->state.top_pipe = 0;
+   if (dbgflushnum)
+     {
+        if (done > 0) printf("DONE (pipes): %i\n", done);
+     }
+   gc->havestuff = EINA_FALSE;
+}
+
+Eina_Bool
+evas_gl_common_module_open(void)
+{
+   if (_evas_engine_GL_common_log_dom < 0)
+     _evas_engine_GL_common_log_dom = eina_log_domain_register
+       ("evas-gl_common", EVAS_DEFAULT_LOG_COLOR);
+   if (_evas_engine_GL_common_log_dom < 0)
+     {
+        EINA_LOG_ERR("Can not create a module log domain.");
+        return EINA_FALSE;
+     }
+   return EINA_TRUE;
+}
+
+void
+evas_gl_common_module_close(void)
+{
+   if (_evas_engine_GL_common_log_dom < 0) return;
+   eina_log_domain_unregister(_evas_engine_GL_common_log_dom);
+   _evas_engine_GL_common_log_dom = -1;
 }