cd4d2cd98bb947d6ce527e5e1e384d3a9993df1d
[framework/uifw/evas.git] / src / modules / engines / gl_common / evas_gl_context.c
1 #include "evas_gl_private.h"
2
3 #define GLPIPES 1
4
5 static int sym_done = 0;
6 int _evas_engine_GL_common_log_dom = -1;
7
8 typedef void    (*glsym_func_void) ();
9
10 void (*glsym_glGenFramebuffers)      (GLsizei a, GLuint *b) = NULL;
11 void (*glsym_glBindFramebuffer)      (GLenum a, GLuint b) = NULL;
12 void (*glsym_glFramebufferTexture2D) (GLenum a, GLenum b, GLenum c, GLuint d, GLint e) = NULL;
13 void (*glsym_glDeleteFramebuffers)   (GLsizei a, const GLuint *b) = NULL;
14
15 #if defined (GLES_VARIETY_S3C6410) || defined (GLES_VARIETY_SGX)
16 // just used for finding symbols :)
17 typedef void (*_eng_fn) (void);
18
19 typedef _eng_fn       (*secsym_func_eng_fn) ();
20 typedef unsigned int  (*secsym_func_uint) ();
21 typedef void         *(*secsym_func_void_ptr) ();
22
23 static _eng_fn  (*secsym_eglGetProcAddress)          (const char *a) = NULL;
24
25 void          *(*secsym_eglCreateImage)               (void *a, void *b, GLenum c, void *d, const int *e) = NULL;
26 unsigned int   (*secsym_eglDestroyImage)              (void *a, void *b) = NULL;
27 void           (*secsym_glEGLImageTargetTexture2DOES) (int a, void *b) = NULL;
28 void          *(*secsym_eglMapImageSEC)               (void *a, void *b) = NULL;
29 unsigned int   (*secsym_eglUnmapImageSEC)             (void *a, void *b) = NULL;
30 unsigned int   (*secsym_eglGetImageAttribSEC)         (void *a, void *b, int c, int *d) = NULL;
31 #endif
32
33 static int dbgflushnum = -1;
34
35 static void
36 sym_missing(void)
37 {
38    ERR("GL symbols missing!");
39 }
40
41 static void
42 gl_symbols(void)
43 {
44    if (sym_done) return;
45    sym_done = 1;
46
47 #ifdef _EVAS_ENGINE_SDL_H
48 # define FINDSYM(dst, sym, typ) if (!dst) dst = (typ)SDL_GL_GetProcAddress(sym)
49 #else
50 # define FINDSYM(dst, sym, typ) if (!dst) dst = (typ)dlsym(RTLD_DEFAULT, sym)
51 #endif
52 #define FALLBAK(dst, typ) if (!dst) dst = (typ)sym_missing;
53    
54    FINDSYM(glsym_glGenFramebuffers, "glGenFramebuffers", glsym_func_void);
55    FINDSYM(glsym_glGenFramebuffers, "glGenFramebuffersEXT", glsym_func_void);
56    FINDSYM(glsym_glGenFramebuffers, "glGenFramebuffersARB", glsym_func_void);
57    FALLBAK(glsym_glGenFramebuffers, glsym_func_void);
58    
59    FINDSYM(glsym_glBindFramebuffer, "glBindFramebuffer", glsym_func_void);
60    FINDSYM(glsym_glBindFramebuffer, "glBindFramebufferEXT", glsym_func_void);
61    FINDSYM(glsym_glBindFramebuffer, "glBindFramebufferARB", glsym_func_void);
62    FALLBAK(glsym_glBindFramebuffer, glsym_func_void);
63    
64    FINDSYM(glsym_glFramebufferTexture2D, "glFramebufferTexture2D", glsym_func_void);
65    FINDSYM(glsym_glFramebufferTexture2D, "glFramebufferTexture2DEXT", glsym_func_void);
66    FINDSYM(glsym_glFramebufferTexture2D, "glFramebufferTexture2DARB", glsym_func_void);
67    FALLBAK(glsym_glFramebufferTexture2D, glsym_func_void);
68
69    FINDSYM(glsym_glDeleteFramebuffers, "glDeleteFramebuffers", glsym_func_void);
70    FINDSYM(glsym_glDeleteFramebuffers, "glDeleteFramebuffersEXT", glsym_func_void);
71    FINDSYM(glsym_glDeleteFramebuffers, "glDeleteFramebuffersARB", glsym_func_void);
72    FALLBAK(glsym_glDeleteFramebuffers, glsym_func_void);
73
74 #if defined (GLES_VARIETY_S3C6410) || defined (GLES_VARIETY_SGX)
75 #undef FINDSYM
76 #define FINDSYM(dst, sym, typ) \
77    if ((!dst) && (secsym_eglGetProcAddress)) dst = (typ)secsym_eglGetProcAddress(sym); \
78    if (!dst) dst = (typ)dlsym(RTLD_DEFAULT, sym)
79 // yes - gl core looking for egl stuff. i know it's odd. a reverse-layer thing
80 // but it will work as the egl/glx layer calls gl core common stuff and thus
81 // these symbols will work. making the glx/egl + x11 layer do this kind-of is
82 // wrong as this is not x11 (output) layer specific like the native surface
83 // stuff. this is generic zero-copy textures for gl
84
85    FINDSYM(secsym_eglGetProcAddress, "eglGetProcAddress", secsym_func_eng_fn);
86    FINDSYM(secsym_eglGetProcAddress, "eglGetProcAddressEXT", secsym_func_eng_fn);
87    FINDSYM(secsym_eglGetProcAddress, "eglGetProcAddressARB", secsym_func_eng_fn);
88    FINDSYM(secsym_eglGetProcAddress, "eglGetProcAddressKHR", secsym_func_eng_fn);
89    
90    FINDSYM(secsym_eglCreateImage, "eglCreateImage", secsym_func_void_ptr);
91    FINDSYM(secsym_eglCreateImage, "eglCreateImageEXT", secsym_func_void_ptr);
92    FINDSYM(secsym_eglCreateImage, "eglCreateImageARB", secsym_func_void_ptr);
93    FINDSYM(secsym_eglCreateImage, "eglCreateImageKHR", secsym_func_void_ptr);
94    
95    FINDSYM(secsym_eglDestroyImage, "eglDestroyImage", secsym_func_uint);
96    FINDSYM(secsym_eglDestroyImage, "eglDestroyImageEXT", secsym_func_uint);
97    FINDSYM(secsym_eglDestroyImage, "eglDestroyImageARB", secsym_func_uint);
98    FINDSYM(secsym_eglDestroyImage, "eglDestroyImageKHR", secsym_func_uint);
99    
100    FINDSYM(secsym_glEGLImageTargetTexture2DOES, "glEGLImageTargetTexture2DOES", glsym_func_void);
101    
102    FINDSYM(secsym_eglMapImageSEC, "eglMapImageSEC", secsym_func_void_ptr);
103    
104    FINDSYM(secsym_eglUnmapImageSEC, "eglUnmapImageSEC", secsym_func_uint);
105    
106    FINDSYM(secsym_eglGetImageAttribSEC, "eglGetImageAttribSEC", secsym_func_uint);
107 #endif   
108 }
109
110 static void shader_array_flush(Evas_GL_Context *gc);
111
112 static Evas_GL_Context *_evas_gl_common_context = NULL;
113 static Evas_GL_Shared *shared = NULL;
114
115 void
116 glerr(int err, const char *file, const char *func, int line, const char *op)
117 {
118    const char *errmsg;
119    char buf[32];
120
121    switch (err)
122      {
123      case GL_INVALID_ENUM:
124         errmsg = "GL_INVALID_ENUM";
125         break;
126      case GL_INVALID_VALUE:
127         errmsg = "GL_INVALID_VALUE";
128         break;
129      case GL_INVALID_OPERATION:
130         errmsg = "GL_INVALID_OPERATION";
131         break;
132      case GL_OUT_OF_MEMORY:
133         errmsg = "GL_OUT_OF_MEMORY";
134         break;
135      default:
136         snprintf(buf, sizeof(buf), "%#x", err);
137         errmsg = buf;
138      }
139
140    eina_log_print(_evas_engine_GL_common_log_dom, EINA_LOG_LEVEL_ERR,
141                   file, func, line, "%s: %s", op, errmsg);
142 }
143
144 static void
145 matrix_ortho(GLfloat *m,
146              GLfloat l, GLfloat r,
147              GLfloat t, GLfloat b,
148              GLfloat near, GLfloat far,
149              int rot, int vw, int vh,
150              int foc, GLfloat orth)
151 {
152    GLfloat rotf;
153    GLfloat cosv, sinv;
154    GLfloat tx, ty;
155    
156    rotf = (((rot / 90) & 0x3) * M_PI) / 2.0;
157    
158    tx = -0.5 * (1.0 - orth);
159    ty = -0.5 * (1.0 - orth);
160    
161    if (rot == 90)
162      {
163         tx += -(vw * 1.0);
164         ty += -(vh * 0.0);
165      }
166    if (rot == 180)
167      {
168         tx += -(vw * 1.0);
169         ty += -(vh * 1.0);
170      }
171    if (rot == 270)
172      {
173         tx += -(vw * 0.0);
174         ty += -(vh * 1.0);
175      }
176    
177    cosv = cos(rotf);
178    sinv = sin(rotf);
179    
180    m[0] = (2.0 / (r - l)) * ( cosv);
181    m[1] = (2.0 / (r - l)) * ( sinv);
182    m[2] = 0.0;
183    m[3] = 0.0;
184    
185    m[4] = (2.0 / (t - b)) * (-sinv);
186    m[5] = (2.0 / (t - b)) * ( cosv);
187    m[6] = 0.0;
188    m[7] = 0.0;
189    
190    m[8] = 0.0;
191    m[9] = 0.0;
192    m[10] = -(2.0 / (far - near));
193    m[11] = 1.0 / (GLfloat)foc;
194    
195    m[12] = (m[0] * tx) + (m[4] * ty) - ((r + l) / (r - l));
196    m[13] = (m[1] * tx) + (m[5] * ty) - ((t + b) / (t - b));
197    m[14] = (m[2] * tx) + (m[6] * ty) - ((near + far) / (far - near));
198    m[15] = (m[3] * tx) + (m[7] * ty) + orth;
199 }
200
201 static int
202 _evas_gl_common_version_check()
203 {
204    char *version;
205    char *tmp;
206    char *tmp2;
207    int major;
208    int minor;
209
210   /*
211    * glGetString returns a string describing the current GL connection.
212    * GL_VERSION is used to get the version of the connection
213    */
214
215    version = (char *)glGetString(GL_VERSION);
216
217   /*
218    * OpengL ES
219    *
220    * 1.* : The form is:
221    *
222    * OpenGL ES-<profile> <major>.<minor>
223    *
224    * where <profile> is either "CM" or "CL". The minor can be followed by the vendor
225    * specific information
226    *
227    * 2.0 : The form is:
228    *
229    * OpenGL<space>ES<space><version number><space><vendor-specific information>
230    */
231
232    /* OpenGL ES 1.* ? */
233
234    if ((tmp = strstr(version, "OpenGL ES-CM ")) || (tmp = strstr(version, "OpenGL ES-CL ")))
235      {
236         /* Not supported */
237         return 0;
238      }
239
240    /* OpenGL ES 2.* ? */
241
242    if ((tmp = strstr(version, "OpenGL ES ")))
243      {
244         /* Supported */
245         return 1;
246      }
247
248   /*
249    * OpenGL
250    *
251    * The GL_VERSION and GL_SHADING_LANGUAGE_VERSION strings begin with a
252    * version number. The version number uses one of these forms:
253    *
254    * major_number.minor_number
255    * major_number.minor_number.release_number
256    *
257    * Vendor-specific information may follow the version number. Its format
258    * depends on the implementation, but a space always separates the
259    * version number and the vendor-specific information.
260    */
261
262    /* glGetString() returns a static string, and we are going to */
263    /* modify it, so we get a copy first */
264    version = strdup(version);
265    if (!version)
266      return 0;
267
268    tmp = strchr(version, '.');
269    /* the first '.' always exists */
270    *tmp = '\0';
271    major = atoi(version);
272    /* FIXME: maybe we can assume that minor in only a cipher */
273    tmp2 = ++tmp;
274    while ((*tmp != '.') && (*tmp != ' ') && (*tmp != '\0'))
275      tmp++;
276    /* *tmp is '\0' : version is major_number.minor_number */
277    /* *tmp is '.'  : version is major_number.minor_number.release_number */
278    /* *tmp is ' '  : version is major_number.minor_number followed by vendor */
279    *tmp = '\0';
280    minor = atoi(tmp2);
281    free(version);
282
283    if (((major == 1) && (minor >= 4)) || (major >= 2))
284      return 1;
285
286    return 0;
287 }
288
289 static void
290 _evas_gl_common_viewport_set(Evas_GL_Context *gc)
291 {
292    GLfloat proj[16];
293    int w = 1, h = 1, m = 1, rot = 1, foc = 0;
294
295    foc = gc->foc;
296    // surface in pipe 0 will be the same as all pipes
297    if ((gc->pipe[0].shader.surface == gc->def_surface) ||
298        (!gc->pipe[0].shader.surface))
299      {
300         w = gc->w;
301         h = gc->h;
302         rot = gc->rot;
303      }
304    else
305      {
306         w = gc->pipe[0].shader.surface->w;
307         h = gc->pipe[0].shader.surface->h;
308         rot = 0;
309         m = -1;
310      }
311    
312    if ((!gc->change.size) || 
313        ((gc->shared->w == w) && (gc->shared->h == h) &&
314            (gc->shared->rot == rot) && (gc->shared->foc == gc->foc) &&
315            (gc->shared->mflip == m)))
316       return;
317    
318    gc->shared->w = w;
319    gc->shared->h = h;
320    gc->shared->rot = rot;
321    gc->shared->mflip = m;
322    gc->shared->foc = foc;
323    gc->shared->z0 = gc->z0;
324    gc->shared->px = gc->px;
325    gc->shared->py = gc->py;
326    gc->change.size = 0;
327
328    if (foc == 0)
329      {
330         if ((rot == 0) || (rot == 180))
331            glViewport(0, 0, w, h);
332         else
333            glViewport(0, 0, h, w);
334         GLERR(__FUNCTION__, __FILE__, __LINE__, "");
335         // std matrix
336         if (m == 1)
337            matrix_ortho(proj, 
338                         0, w, 0, h, 
339                         -1000000.0, 1000000.0,
340                         rot, w, h,
341                         1, 1.0);
342         // v flipped matrix for render-to-texture
343         else
344            matrix_ortho(proj, 
345                         0, w, h, 0, 
346                         -1000000.0, 1000000.0,
347                         rot, w, h,
348                         1, 1.0);
349      }
350    else
351      {
352         int px, py, vx, vy, vw = 0, vh = 0, ax = 0, ay = 0, ppx = 0, ppy = 0;
353         
354         px = gc->shared->px;
355         py = gc->shared->py;
356         
357         if      ((rot == 0  ) || (rot == 90 )) ppx = px;
358         else if ((rot == 180) || (rot == 270)) ppx = w - px;
359         if      ((rot == 0  ) || (rot == 270)) ppy = py;
360         else if ((rot == 90 ) || (rot == 180)) ppy = h - py;
361         
362         vx = ((w / 2) - ppx);
363         if (vx >= 0)
364           {
365              vw = w + (2 * vx);
366              if      ((rot == 0  ) || (rot == 90 )) ax = 2 * vx;
367              else if ((rot == 180) || (rot == 270)) ax = 0;
368           }
369         else
370           {
371              vw = w - (2 * vx);
372              if      ((rot == 0  ) || (rot == 90 )) ax = 0;
373              else if ((rot == 180) || (rot == 270)) ax = ppx - px;
374              vx = 0;
375           }
376         
377         vy = ((h / 2) - ppy);
378         if (vy < 0)
379           {
380              vh = h - (2 * vy);
381              if      ((rot == 0  ))                                 ay = 0;
382              else if ((rot == 90 ) || (rot == 180) || (rot == 270)) ay = ppy - py;
383              vy = -vy;
384           }
385         else
386           {
387              vh = h + (2 * vy);
388              if      ((rot == 0  ) || (rot == 270)) ay = 2 * vy;
389              else if ((rot == 90 ) || (rot == 180)) ay = 0;
390              vy = 0;
391           }
392         
393         if (m == -1) ay = vy * 2;
394         
395         if ((rot == 0) || (rot == 180))
396            glViewport(-2 * vx, -2 * vy, vw, vh);
397         else
398            glViewport(-2 * vy, -2 * vx, vh, vw);
399         if (m == 1)
400            matrix_ortho(proj, 0, vw, 0, vh,
401                         -1000000.0, 1000000.0,
402                         rot, vw, vh,
403                         foc, 0.0);
404         else
405            matrix_ortho(proj, 0, vw, vh, 0,
406                         -1000000.0, 1000000.0,
407                         rot, vw, vh,
408                         foc, 0.0);
409         gc->shared->ax = ax;
410         gc->shared->ay = ay;
411      }
412    
413    glUseProgram(gc->shared->shader.rect.prog);
414    GLERR(__FUNCTION__, __FILE__, __LINE__, "");
415    glUniformMatrix4fv(glGetUniformLocation(gc->shared->shader.rect.prog, "mvp"), 1,
416                       GL_FALSE, proj);
417    GLERR(__FUNCTION__, __FILE__, __LINE__, "");
418    glUseProgram(gc->shared->shader.font.prog);
419    GLERR(__FUNCTION__, __FILE__, __LINE__, "");
420    glUniformMatrix4fv(glGetUniformLocation(gc->shared->shader.font.prog, "mvp"), 1,
421                       GL_FALSE, proj);
422    GLERR(__FUNCTION__, __FILE__, __LINE__, "");
423    
424    glUseProgram(gc->shared->shader.yuv.prog);
425    GLERR(__FUNCTION__, __FILE__, __LINE__, "");
426    glUniformMatrix4fv(glGetUniformLocation(gc->shared->shader.yuv.prog, "mvp"), 1,
427                       GL_FALSE, proj);
428    GLERR(__FUNCTION__, __FILE__, __LINE__, "");
429    glUseProgram(gc->shared->shader.yuv_nomul.prog);
430    GLERR(__FUNCTION__, __FILE__, __LINE__, "");
431    glUniformMatrix4fv(glGetUniformLocation(gc->shared->shader.yuv_nomul.prog, "mvp"), 1,
432                       GL_FALSE, proj);
433    GLERR(__FUNCTION__, __FILE__, __LINE__, "");
434    
435    glUseProgram(gc->shared->shader.tex.prog);
436    GLERR(__FUNCTION__, __FILE__, __LINE__, "");
437    glUniformMatrix4fv(glGetUniformLocation(gc->shared->shader.tex.prog, "mvp"), 1,
438                       GL_FALSE, proj);
439    GLERR(__FUNCTION__, __FILE__, __LINE__, "");
440    glUseProgram(gc->shared->shader.tex_nomul.prog);
441    GLERR(__FUNCTION__, __FILE__, __LINE__, "");
442    glUniformMatrix4fv(glGetUniformLocation(gc->shared->shader.tex_nomul.prog, "mvp"), 1,
443                       GL_FALSE, proj);
444    GLERR(__FUNCTION__, __FILE__, __LINE__, "");
445    
446    glUseProgram(gc->shared->shader.img.prog);
447    GLERR(__FUNCTION__, __FILE__, __LINE__, "");
448    glUniformMatrix4fv(glGetUniformLocation(gc->shared->shader.img.prog, "mvp"), 1,
449                       GL_FALSE, proj);
450    GLERR(__FUNCTION__, __FILE__, __LINE__, "");
451    glUseProgram(gc->shared->shader.img_nomul.prog);
452    GLERR(__FUNCTION__, __FILE__, __LINE__, "");
453    glUniformMatrix4fv(glGetUniformLocation(gc->shared->shader.img_nomul.prog, "mvp"), 1,
454                       GL_FALSE, proj);
455    GLERR(__FUNCTION__, __FILE__, __LINE__, "");
456
457    glUseProgram(gc->shared->shader.img_bgra.prog);
458    GLERR(__FUNCTION__, __FILE__, __LINE__, "");
459    glUniformMatrix4fv(glGetUniformLocation(gc->shared->shader.img_bgra.prog, "mvp"), 1,
460                       GL_FALSE, proj);
461    GLERR(__FUNCTION__, __FILE__, __LINE__, "");
462    glUseProgram(gc->shared->shader.img_bgra_nomul.prog);
463    GLERR(__FUNCTION__, __FILE__, __LINE__, "");
464    glUniformMatrix4fv(glGetUniformLocation(gc->shared->shader.img_bgra_nomul.prog, "mvp"), 1,
465                       GL_FALSE, proj);
466    GLERR(__FUNCTION__, __FILE__, __LINE__, "");
467
468    glUseProgram(gc->pipe[0].shader.cur_prog);
469    GLERR(__FUNCTION__, __FILE__, __LINE__, "");
470 }
471
472 Evas_GL_Context *
473 evas_gl_common_context_new(void)
474 {
475    Evas_GL_Context *gc;
476    const char *s;
477    int i;
478
479 #if 1
480    if (_evas_gl_common_context)
481      {
482         _evas_gl_common_context->references++;
483         return _evas_gl_common_context;
484      }
485 #endif
486    if (!_evas_gl_common_version_check())
487      return NULL;
488    gc = calloc(1, sizeof(Evas_GL_Context));
489    if (!gc) return NULL;
490
491    gl_symbols();
492    
493    gc->references = 1;
494    
495    _evas_gl_common_context = gc;
496    
497    for (i = 0; i < MAX_PIPES; i++)
498       gc->pipe[i].shader.render_op = EVAS_RENDER_BLEND;
499    
500    if (!shared)
501      {
502         const GLubyte *ext;
503
504         shared = calloc(1, sizeof(Evas_GL_Shared));
505         ext = glGetString(GL_EXTENSIONS);
506         if (ext)
507           {
508              if (getenv("EVAS_GL_INFO"))
509                 fprintf(stderr, "EXT:\n%s\n", ext);
510              if ((strstr((char *)ext, "GL_ARB_texture_non_power_of_two")) ||
511                  (strstr((char *)ext, "OES_texture_npot")) ||
512                  (strstr((char *)ext, "GL_IMG_texture_npot")))
513                shared->info.tex_npo2 = 1;
514              if ((strstr((char *)ext, "GL_NV_texture_rectangle")) ||
515                  (strstr((char *)ext, "GL_EXT_texture_rectangle")) ||
516                  (strstr((char *)ext, "GL_ARB_texture_rectangle")))
517                shared->info.tex_rect = 1;
518 #ifdef GL_TEXTURE_MAX_ANISOTROPY_EXT
519              if ((strstr((char *)ext, "GL_EXT_texture_filter_anisotropic")))
520                glGetFloatv(GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT, 
521                            &(shared->info.anisotropic));
522 #endif
523 #ifdef GL_BGRA
524              if ((strstr((char *)ext, "GL_EXT_bgra")) ||
525                  (strstr((char *)ext, "GL_EXT_texture_format_BGRA8888")))
526                shared->info.bgra = 1;
527 #endif
528 #if defined (GLES_VARIETY_S3C6410) || defined (GLES_VARIETY_SGX)
529              // FIXME: there should be an extension name/string to check for
530              // not just symbols in the lib
531              i = 0;
532              s = getenv("EVAS_GL_NO_MAP_IMAGE_SEC");
533              if (s) i = atoi(s);
534              if (!i)
535                {
536                   // test for all needed symbols - be "conservative" and
537                   // need all of it
538                   if ((secsym_eglCreateImage) &&
539                       (secsym_eglDestroyImage) &&
540                       (secsym_glEGLImageTargetTexture2DOES) &&
541                       (secsym_eglMapImageSEC) &&
542                       (secsym_eglUnmapImageSEC) &&
543                       (secsym_eglGetImageAttribSEC))
544                      shared->info.sec_image_map = 1;
545                }
546 #endif             
547           }
548         glGetIntegerv(GL_MAX_TEXTURE_IMAGE_UNITS,
549                       &(shared->info.max_texture_units));
550         glGetIntegerv(GL_MAX_TEXTURE_SIZE,
551                       &(shared->info.max_texture_size));
552         shared->info.max_vertex_elements = 6 * 10000;
553 #ifdef GL_MAX_ELEMENTS_VERTICES
554         glGetIntegerv(GL_MAX_ELEMENTS_VERTICES,
555                       &(shared->info.max_vertex_elements));
556 #endif
557         s = getenv("EVAS_GL_VERTEX_MAX");
558         if (s) shared->info.max_vertex_elements = atoi(s);
559         if (shared->info.max_vertex_elements < 6)
560            shared->info.max_vertex_elements = 6;
561         
562         // magic numbers that are a result of imperical testing and getting
563         // "best case" performance across a range of systems
564         shared->info.tune.cutout.max                 = DEF_CUTOUT;
565         shared->info.tune.pipes.max                  = DEF_PIPES;
566         shared->info.tune.atlas.max_alloc_size       = DEF_ATLAS_ALLOC;
567         shared->info.tune.atlas.max_alloc_alpha_size = DEF_ATLAS_ALLOC_ALPHA;
568         shared->info.tune.atlas.max_w                = DEF_ATLAS_W;
569         shared->info.tune.atlas.max_h                = DEF_ATLAS_H;
570         shared->info.tune.atlas.slot_size            = DEF_ATLAS_SLOT;
571         
572         // per gpu hacks. based on impirical measurement of some known gpu's
573         s = (const char *)glGetString(GL_RENDERER);
574         if (s)
575           {
576              if      (strstr(s, "PowerVR SGX 540"))
577                 shared->info.tune.pipes.max = DEF_PIPES_SGX_540;
578              else if (strstr(s, "NVIDIA Tegra"))
579                 shared->info.tune.pipes.max = DEF_PIPES_TEGRA_2;
580           }
581         
582 #define GETENVOPT(name, tune_param, min, max) \
583         do { \
584            const char *__v = getenv(name); \
585            if (__v) { \
586               shared->info.tune.tune_param = atoi(__v); \
587               if (shared->info.tune.tune_param > max) \
588                  shared->info.tune.tune_param = max; \
589               else if (shared->info.tune.tune_param < min) \
590                  shared->info.tune.tune_param = min; \
591            } \
592         } while (0)
593
594         GETENVOPT("EVAS_GL_CUTOUT_MAX", cutout.max, -1, 0x7fffffff);
595         GETENVOPT("EVAS_GL_PIPES_MAX", pipes.max, 1, MAX_PIPES);
596         GETENVOPT("EVAS_GL_ATLAS_ALLOC_SIZE", atlas.max_alloc_size, MIN_ATLAS_ALLOC, MAX_ATLAS_ALLOC);
597         GETENVOPT("EVAS_GL_ATLAS_ALLOC_ALPHA_SIZE", atlas.max_alloc_alpha_size, MIN_ATLAS_ALLOC_ALPHA, MAX_ATLAS_ALLOC_ALPHA);
598         GETENVOPT("EVAS_GL_ATLAS_MAX_W", atlas.max_w, 0, MAX_ATLAS_W);
599         GETENVOPT("EVAS_GL_ATLAS_MAX_H", atlas.max_h, 0, MAX_ATLAS_H);
600         GETENVOPT("EVAS_GL_ATLAS_SLOT_SIZE", atlas.slot_size, MIN_ATLAS_SLOT, MAX_ATLAS_SLOT);
601
602         if (getenv("EVAS_GL_INFO"))
603            fprintf(stderr,
604                    "max tex size %ix%i\n"
605                    "max units %i\n"
606                    "non-power-2 tex %i\n"
607                    "rect tex %i\n"
608                    "bgra : %i\n"
609                    "max ansiotropic filtering: %3.3f\n"
610                    "egl sec map image: %i\n"
611                    "max vertex count: %i\n"
612                    "\n"
613                    "(can set EVAS_GL_VERTEX_MAX  EVAS_GL_NO_MAP_IMAGE_SEC  EVAS_GL_INFO  EVAS_GL_MEMINFO )\n"
614                    "\n"
615                    "EVAS_GL_CUTOUT_MAX: %i\n"
616                    "EVAS_GL_PIPES_MAX: %i\n"
617                    "EVAS_GL_ATLAS_ALLOC_SIZE: %i\n"
618                    "EVAS_GL_ATLAS_ALLOC_ALPHA_SIZE: %i\n"
619                    "EVAS_GL_ATLAS_MAX_W x EVAS_GL_ATLAS_MAX_H: %i x %i\n"
620                    "EVAS_GL_ATLAS_SLOT_SIZE: %i\n"
621                    , 
622                    (int)shared->info.max_texture_size, (int)shared->info.max_texture_size,
623                    (int)shared->info.max_texture_units,
624                    (int)shared->info.tex_npo2,
625                    (int)shared->info.tex_rect,
626                    (int)shared->info.bgra,
627                    (double)shared->info.anisotropic,
628                    (int)shared->info.sec_image_map,
629                    (int)shared->info.max_vertex_elements,
630                    
631                    (int)shared->info.tune.cutout.max,
632                    (int)shared->info.tune.pipes.max,
633                    (int)shared->info.tune.atlas.max_alloc_size,
634                    (int)shared->info.tune.atlas.max_alloc_alpha_size,
635                    (int)shared->info.tune.atlas.max_w, (int)shared->info.tune.atlas.max_h,
636                    (int)shared->info.tune.atlas.slot_size
637                   );
638         
639         glDisable(GL_DEPTH_TEST);
640         GLERR(__FUNCTION__, __FILE__, __LINE__, "");
641         glEnable(GL_DITHER);
642         GLERR(__FUNCTION__, __FILE__, __LINE__, "");
643         glDisable(GL_BLEND);
644         GLERR(__FUNCTION__, __FILE__, __LINE__, "");
645         glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
646         GLERR(__FUNCTION__, __FILE__, __LINE__, "");
647         // no dest alpha
648 //        glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); // dest alpha
649 //        glBlendFunc(GL_SRC_ALPHA, GL_ONE); // ???
650         glDepthMask(GL_FALSE);
651         GLERR(__FUNCTION__, __FILE__, __LINE__, "");
652         
653         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
654         GLERR(__FUNCTION__, __FILE__, __LINE__, "");
655         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
656         GLERR(__FUNCTION__, __FILE__, __LINE__, "");
657         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
658         GLERR(__FUNCTION__, __FILE__, __LINE__, "");
659         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
660         GLERR(__FUNCTION__, __FILE__, __LINE__, "");
661 #ifdef GL_TEXTURE_MAX_ANISOTROPY_EXT
662         if (shared->info.anisotropic > 0.0)
663           {
664              glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, 1.0);
665              GLERR(__FUNCTION__, __FILE__, __LINE__, "");
666           }
667 #endif
668         
669         glEnableVertexAttribArray(SHAD_VERTEX);
670         GLERR(__FUNCTION__, __FILE__, __LINE__, "");
671         glEnableVertexAttribArray(SHAD_COLOR);
672         GLERR(__FUNCTION__, __FILE__, __LINE__, "");
673
674         if (!evas_gl_common_shader_program_init(&(shared->shader.rect), 
675                                                 &(shader_rect_vert_src), 
676                                                 &(shader_rect_frag_src),
677                                                 "rect")) goto error;
678         if (!evas_gl_common_shader_program_init(&(shared->shader.font),
679                                                 &(shader_font_vert_src), 
680                                                 &(shader_font_frag_src),
681                                                 "font")) goto error;
682         if (!evas_gl_common_shader_program_init(&(shared->shader.img),
683                                                 &(shader_img_vert_src),
684                                                 &(shader_img_frag_src),
685                                                 "img")) goto error;
686         if (!evas_gl_common_shader_program_init(&(shared->shader.img_nomul),
687                                                 &(shader_img_nomul_vert_src),
688                                                 &(shader_img_nomul_frag_src),
689                                                 "img_nomul")) goto error;
690         if (!evas_gl_common_shader_program_init(&(shared->shader.img_bgra),
691                                                 &(shader_img_bgra_vert_src),
692                                                 &(shader_img_bgra_frag_src),
693                                                 "img_bgra")) goto error;
694         if (!evas_gl_common_shader_program_init(&(shared->shader.img_bgra_nomul),
695                                                 &(shader_img_bgra_nomul_vert_src),
696                                                 &(shader_img_bgra_nomul_frag_src),
697                                                 "img_bgra_nomul")) goto error;
698         if (!evas_gl_common_shader_program_init(&(shared->shader.tex),
699                                                 &(shader_tex_vert_src), 
700                                                 &(shader_tex_frag_src),
701                                                 "tex")) goto error;
702         if (!evas_gl_common_shader_program_init(&(shared->shader.tex_nomul),
703                                                 &(shader_tex_nomul_vert_src), 
704                                                 &(shader_tex_nomul_frag_src),
705                                                 "tex_nomul")) goto error;
706         if (!evas_gl_common_shader_program_init(&(shared->shader.yuv),
707                                                 &(shader_yuv_vert_src), 
708                                                 &(shader_yuv_frag_src),
709                                                 "yuv")) goto error;
710         if (!evas_gl_common_shader_program_init(&(shared->shader.yuv_nomul),
711                                                 &(shader_yuv_nomul_vert_src), 
712                                                 &(shader_yuv_nomul_frag_src),
713                                                 "yuv_nomul")) goto error;
714         
715         glUseProgram(shared->shader.yuv.prog);
716         GLERR(__FUNCTION__, __FILE__, __LINE__, "");
717         glUniform1i(glGetUniformLocation(shared->shader.yuv.prog, "tex"), 0);
718         GLERR(__FUNCTION__, __FILE__, __LINE__, "");
719         glUniform1i(glGetUniformLocation(shared->shader.yuv.prog, "texu"), 1);
720         GLERR(__FUNCTION__, __FILE__, __LINE__, "");
721         glUniform1i(glGetUniformLocation(shared->shader.yuv.prog, "texv"), 2);
722         GLERR(__FUNCTION__, __FILE__, __LINE__, "");
723         
724         glUseProgram(shared->shader.yuv_nomul.prog);
725         GLERR(__FUNCTION__, __FILE__, __LINE__, "");
726         glUniform1i(glGetUniformLocation(shared->shader.yuv_nomul.prog, "tex"), 0);
727         GLERR(__FUNCTION__, __FILE__, __LINE__, "");
728         glUniform1i(glGetUniformLocation(shared->shader.yuv_nomul.prog, "texu"), 1);
729         GLERR(__FUNCTION__, __FILE__, __LINE__, "");
730         glUniform1i(glGetUniformLocation(shared->shader.yuv_nomul.prog, "texv"), 2);
731         GLERR(__FUNCTION__, __FILE__, __LINE__, "");
732         
733         glUseProgram(gc->pipe[0].shader.cur_prog);
734         GLERR(__FUNCTION__, __FILE__, __LINE__, "");
735         // in shader:
736         // uniform sampler2D tex[8];
737         // 
738         // in code:
739         // GLuint texes[8];
740         // GLint loc = glGetUniformLocation(prog, "tex");
741         // glUniform1iv(loc, 8, texes);
742
743         shared->native_hash = eina_hash_int32_new(NULL);
744      }
745    gc->shared = shared;
746    gc->shared->references++;
747    _evas_gl_common_viewport_set(gc);
748    
749    gc->def_surface = evas_gl_common_image_surface_new(gc, 1, 1, 1);
750    
751    return gc;
752    error:
753    evas_gl_common_context_free(gc);
754    return NULL;
755 }
756
757 void
758 evas_gl_common_context_free(Evas_GL_Context *gc)
759 {
760    int i, j;
761    
762    gc->references--;
763    if (gc->references > 0) return;
764    if (gc->shared) gc->shared->references--;
765    
766    if (gc->def_surface) evas_gl_common_image_free(gc->def_surface);
767
768    if (gc->shared)
769      {
770         for (i = 0; i < gc->shared->info.tune.pipes.max; i++)
771           {
772              if (gc->pipe[i].array.vertex) free(gc->pipe[i].array.vertex);
773              if (gc->pipe[i].array.color) free(gc->pipe[i].array.color);
774              if (gc->pipe[i].array.texuv) free(gc->pipe[i].array.texuv);
775              if (gc->pipe[i].array.texuv2) free(gc->pipe[i].array.texuv2);
776              if (gc->pipe[i].array.texuv3) free(gc->pipe[i].array.texuv3);
777           }
778      }
779    
780    if ((gc->shared) && (gc->shared->references == 0))
781      {
782         evas_gl_common_shader_program_shutdown(&(gc->shared->shader.rect));
783         evas_gl_common_shader_program_shutdown(&(gc->shared->shader.font));
784         evas_gl_common_shader_program_shutdown(&(gc->shared->shader.img));
785         evas_gl_common_shader_program_shutdown(&(gc->shared->shader.img_nomul));
786         evas_gl_common_shader_program_shutdown(&(gc->shared->shader.img_bgra));
787         evas_gl_common_shader_program_shutdown(&(gc->shared->shader.img_bgra_nomul));
788         evas_gl_common_shader_program_shutdown(&(gc->shared->shader.yuv));
789         evas_gl_common_shader_program_shutdown(&(gc->shared->shader.yuv_nomul));
790         evas_gl_common_shader_program_shutdown(&(gc->shared->shader.tex));
791         evas_gl_common_shader_program_shutdown(&(gc->shared->shader.tex_nomul));
792         
793         while (gc->shared->images)
794           {
795              evas_gl_common_image_free(gc->shared->images->data);
796           }
797         while (gc->shared->tex.whole)
798           {
799              evas_gl_common_texture_free(gc->shared->tex.whole->data);
800           }
801         for (i = 0; i < 33; i++)
802           {
803              for (j = 0; j < 3; j++)
804                {
805                   while (gc->shared->tex.atlas[i][j])
806                     {
807                        evas_gl_common_texture_free
808                          ((Evas_GL_Texture *)gc->shared->tex.atlas[i][j]);
809                        gc->shared->tex.atlas[i][j] = NULL;
810                     }
811                }
812           }
813         eina_hash_free(gc->shared->native_hash);
814         free(gc->shared);
815         shared = NULL;
816      }
817    if (gc == _evas_gl_common_context) _evas_gl_common_context = NULL;
818    free(gc);
819 }
820
821 void
822 evas_gl_common_context_use(Evas_GL_Context *gc)
823 {
824    if (_evas_gl_common_context == gc) return;
825    _evas_gl_common_context = gc;
826    _evas_gl_common_viewport_set(gc);
827 }
828
829 void
830 evas_gl_common_context_newframe(Evas_GL_Context *gc)
831 {
832    int i;
833
834    if (dbgflushnum < 0)
835      {
836         dbgflushnum = 0;
837         if (getenv("EVAS_GL_DBG")) dbgflushnum = 1;
838      }
839    if (dbgflushnum) printf("----prev-flushnum: %i -----------------------------------\n", gc->flushnum);
840    
841    gc->flushnum = 0;
842    gc->state.current.cur_prog = 0;
843    gc->state.current.cur_tex = 0;
844    gc->state.current.cur_texu = 0;
845    gc->state.current.cur_texv = 0;
846    gc->state.current.render_op = 0;
847    gc->state.current.smooth = 0;
848    gc->state.current.blend = 0;
849    gc->state.current.clip = 0;
850    gc->state.current.cx = 0;
851    gc->state.current.cy = 0;
852    gc->state.current.cw = 0;
853    gc->state.current.ch = 0;
854    
855    for (i = 0; i < gc->shared->info.tune.pipes.max; i++)
856      {
857         gc->pipe[i].region.x = 0;
858         gc->pipe[i].region.y = 0;
859         gc->pipe[i].region.w = 0;
860         gc->pipe[i].region.h = 0;
861         gc->pipe[i].region.type = 0;
862         gc->pipe[i].clip.active = 0;
863         gc->pipe[i].clip.x = 0;
864         gc->pipe[i].clip.y = 0;
865         gc->pipe[i].clip.w = 0;
866         gc->pipe[i].clip.h = 0;
867         gc->pipe[i].shader.surface = NULL;
868         gc->pipe[i].shader.cur_prog = 0;
869         gc->pipe[i].shader.cur_tex = 0;
870         gc->pipe[i].shader.cur_texu = 0;
871         gc->pipe[i].shader.cur_texv = 0;
872         gc->pipe[i].shader.render_op = EVAS_RENDER_BLEND;
873         gc->pipe[i].shader.smooth = 0;
874         gc->pipe[i].shader.blend = 0;
875         gc->pipe[i].shader.clip = 0;
876         gc->pipe[i].shader.cx = 0;
877         gc->pipe[i].shader.cy = 0;
878         gc->pipe[i].shader.cw = 0;
879         gc->pipe[i].shader.ch = 0;
880      }
881    gc->change.size = 1;
882    
883    glDisable(GL_SCISSOR_TEST);
884    GLERR(__FUNCTION__, __FILE__, __LINE__, "");
885    glScissor(0, 0, 0, 0);
886    GLERR(__FUNCTION__, __FILE__, __LINE__, "");
887    
888    glDisable(GL_DEPTH_TEST);
889    GLERR(__FUNCTION__, __FILE__, __LINE__, "");
890    glEnable(GL_DITHER);
891    GLERR(__FUNCTION__, __FILE__, __LINE__, "");
892    glDisable(GL_BLEND);
893    GLERR(__FUNCTION__, __FILE__, __LINE__, "");
894    glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
895    GLERR(__FUNCTION__, __FILE__, __LINE__, "");
896    // no dest alpha
897 //   glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); // dest alpha
898 //   glBlendFunc(GL_SRC_ALPHA, GL_ONE); // ???
899    glDepthMask(GL_FALSE);
900    GLERR(__FUNCTION__, __FILE__, __LINE__, "");
901         
902    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
903    GLERR(__FUNCTION__, __FILE__, __LINE__, "");
904    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
905    GLERR(__FUNCTION__, __FILE__, __LINE__, "");
906    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
907    GLERR(__FUNCTION__, __FILE__, __LINE__, "");
908    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
909    GLERR(__FUNCTION__, __FILE__, __LINE__, "");
910 #ifdef GL_TEXTURE_MAX_ANISOTROPY_EXT
911    if (shared->info.anisotropic > 0.0)
912      {
913         glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, 1.0);
914         GLERR(__FUNCTION__, __FILE__, __LINE__, "");
915      }
916 #endif
917    
918    glEnableVertexAttribArray(SHAD_VERTEX);
919    GLERR(__FUNCTION__, __FILE__, __LINE__, "");
920    glEnableVertexAttribArray(SHAD_COLOR);
921    GLERR(__FUNCTION__, __FILE__, __LINE__, "");
922    glUseProgram(gc->pipe[0].shader.cur_prog);
923    GLERR(__FUNCTION__, __FILE__, __LINE__, "");
924    
925    glActiveTexture(GL_TEXTURE0);
926    GLERR(__FUNCTION__, __FILE__, __LINE__, "");
927    glBindTexture(GL_TEXTURE_2D, gc->pipe[0].shader.cur_tex);
928    GLERR(__FUNCTION__, __FILE__, __LINE__, "");
929
930    _evas_gl_common_viewport_set(gc);
931 }
932
933 void
934 evas_gl_common_context_resize(Evas_GL_Context *gc, int w, int h, int rot)
935 {
936    if ((gc->w == w) && (gc->h == h) && (gc->rot == rot)) return;
937    evas_gl_common_context_flush(gc);
938    gc->change.size = 1;
939    gc->rot = rot;
940    gc->w = w;
941    gc->h = h;
942    if (_evas_gl_common_context == gc) _evas_gl_common_viewport_set(gc);
943 }
944
945 void
946 evas_gl_common_context_target_surface_set(Evas_GL_Context *gc,
947                                           Evas_GL_Image *surface)
948 {
949    if (surface == gc->pipe[0].shader.surface) return;
950    
951    evas_gl_common_context_flush(gc);
952    
953    gc->state.current.cur_prog = -1;
954    gc->state.current.cur_tex = -1;
955    gc->state.current.cur_texu = -1;
956    gc->state.current.cur_texv = -1;
957    gc->state.current.render_op = -1;
958    gc->state.current.smooth = -1;
959    gc->state.current.blend = -1;
960    gc->state.current.clip = -1;
961    gc->state.current.cx = -1;
962    gc->state.current.cy = -1;
963    gc->state.current.cw = -1;
964    gc->state.current.ch = -1;
965
966    gc->pipe[0].shader.surface = surface;
967    gc->change.size = 1;
968 #if defined (GLES_VARIETY_S3C6410) || defined (GLES_VARIETY_SGX)
969 # ifndef GL_FRAMEBUFFER
970 #  define GL_FRAMEBUFFER GL_FRAMEBUFFER_OES
971 # endif   
972 #else
973 # ifndef GL_FRAMEBUFFER
974 #  define GL_FRAMEBUFFER GL_FRAMEBUFFER_EXT
975 # endif   
976 #endif   
977    if (gc->pipe[0].shader.surface == gc->def_surface)
978      {
979         glsym_glBindFramebuffer(GL_FRAMEBUFFER, 0);
980         GLERR(__FUNCTION__, __FILE__, __LINE__, "");
981      }
982    else
983      {
984         glsym_glBindFramebuffer(GL_FRAMEBUFFER, surface->tex->pt->fb);
985         GLERR(__FUNCTION__, __FILE__, __LINE__, "");
986      }
987    _evas_gl_common_viewport_set(gc);
988 }
989
990 #define PUSH_VERTEX(n, x, y, z) \
991    gc->pipe[n].array.vertex[nv++] = x; \
992    gc->pipe[n].array.vertex[nv++] = y; \
993    gc->pipe[n].array.vertex[nv++] = z
994 #define PUSH_COLOR(n, r, g, b, a) \
995    gc->pipe[n].array.color[nc++] = r; \
996    gc->pipe[n].array.color[nc++] = g; \
997    gc->pipe[n].array.color[nc++] = b; \
998    gc->pipe[n].array.color[nc++] = a
999 #define PUSH_TEXUV(n, u, v) \
1000    gc->pipe[n].array.texuv[nu++] = u; \
1001    gc->pipe[n].array.texuv[nu++] = v
1002 #define PUSH_TEXUV2(n, u, v) \
1003    gc->pipe[n].array.texuv2[nu2++] = u; \
1004    gc->pipe[n].array.texuv2[nu2++] = v
1005 #define PUSH_TEXUV3(n, u, v) \
1006    gc->pipe[n].array.texuv3[nu3++] = u; \
1007    gc->pipe[n].array.texuv3[nu3++] = v
1008
1009 static inline void
1010 array_alloc(Evas_GL_Context *gc, int n)
1011 {
1012    if (gc->pipe[n].array.num <= gc->pipe[n].array.alloc) return;
1013    gc->pipe[n].array.alloc += 6 * 1024;
1014    if (gc->pipe[n].array.use_vertex)
1015      gc->pipe[n].array.vertex = realloc(gc->pipe[n].array.vertex,
1016                                 gc->pipe[n].array.alloc * sizeof(GLshort) * 3);
1017    if (gc->pipe[n].array.use_color)
1018      gc->pipe[n].array.color  = realloc(gc->pipe[n].array.color,
1019                                 gc->pipe[n].array.alloc * sizeof(GLubyte) * 4);
1020    if (gc->pipe[n].array.use_texuv)
1021      gc->pipe[n].array.texuv  = realloc(gc->pipe[n].array.texuv,
1022                                 gc->pipe[n].array.alloc * sizeof(GLfloat) * 2);
1023    if (gc->pipe[n].array.use_texuv2)
1024      gc->pipe[n].array.texuv2  = realloc(gc->pipe[n].array.texuv2,
1025                                gc->pipe[n].array.alloc * sizeof(GLfloat) * 2);
1026    if (gc->pipe[n].array.use_texuv3)
1027      gc->pipe[n].array.texuv3  = realloc(gc->pipe[n].array.texuv3,
1028                                  gc->pipe[n].array.alloc * sizeof(GLfloat) * 2);
1029 }
1030
1031 static int
1032 pipe_region_intersects(Evas_GL_Context *gc, int n,
1033                        int x, int y, int w, int h)
1034 {
1035    int i, rx, ry, rw, rh, ii;
1036    
1037    rx = gc->pipe[n].region.x;
1038    ry = gc->pipe[n].region.y;
1039    rw = gc->pipe[n].region.w;
1040    rh = gc->pipe[n].region.h;
1041    if (!RECTS_INTERSECT(x, y, w, h, rx, ry, rw, rh))
1042       return 0;
1043    
1044    // a hack for now. map pipes use their whole bounding box for intersects
1045    // which at worst case reduces to old pipeline flushes, but cheaper than
1046    // full quad region or triangle intersects right now
1047    if (gc->pipe[n].region.type == RTYPE_MAP) return 1;
1048    
1049    for (i = 0, 
1050         ii = 0; 
1051         
1052         i < gc->pipe[n].array.num; 
1053         
1054         i += (3 * 2), 
1055         ii += (3 * 3 * 2))
1056      {  // tri 1...
1057         // 0, 1, 2 < top left
1058         // 3, 4, 5 < top right
1059         // 6. 7, 8 < bottom left
1060         rx = gc->pipe[n].array.vertex[ii + 0];
1061         ry = gc->pipe[n].array.vertex[ii + 1];
1062         rw = gc->pipe[n].array.vertex[ii + 3] - rx;
1063         rh = gc->pipe[n].array.vertex[ii + 7] - ry;
1064         if (RECTS_INTERSECT(x, y, w, h, rx, ry, rw, rh))
1065            return 1;
1066      }
1067    return 0;
1068 }
1069
1070 static void
1071 pipe_region_expand(Evas_GL_Context *gc, int n,
1072                    int x, int y, int w, int h)
1073 {
1074    int x1, y1, x2, y2;
1075    
1076    if (gc->pipe[n].region.w <= 0)
1077      {
1078         gc->pipe[n].region.x = x;
1079         gc->pipe[n].region.y = y;
1080         gc->pipe[n].region.w = w;
1081         gc->pipe[n].region.h = h;
1082         return;
1083      }
1084    x1 = gc->pipe[n].region.x;
1085    y1 = gc->pipe[n].region.y;
1086    x2 = gc->pipe[n].region.x + gc->pipe[n].region.w;
1087    y2 = gc->pipe[n].region.y + gc->pipe[n].region.h;
1088    if (x < x1) x1 = x;
1089    if (y < y1) y1 = y;
1090    if ((x + w) > x2) x2 = x + w;
1091    if ((y + h) > y2) y2 = y + h;
1092    gc->pipe[n].region.x = x1;
1093    gc->pipe[n].region.y = y1;
1094    gc->pipe[n].region.w = x2 - x1;
1095    gc->pipe[n].region.h = y2 - y1;
1096 }
1097
1098 static Eina_Bool
1099 vertex_array_size_check(Evas_GL_Context *gc, int pn, int n)
1100 {
1101    return 1;
1102 // this fixup breaks for expedite test 32. why?
1103    if ((gc->pipe[pn].array.num + n) > gc->shared->info.max_vertex_elements)
1104      {
1105         shader_array_flush(gc);
1106         return 0;
1107      }
1108    return 1;
1109 }
1110
1111 void
1112 evas_gl_common_context_line_push(Evas_GL_Context *gc, 
1113                                  int x1, int y1, int x2, int y2,
1114                                  int clip, int cx, int cy, int cw, int ch,
1115                                  int r, int g, int b, int a)
1116 {
1117    int pnum, nv, nc, nu, nt, i;
1118    Eina_Bool blend = 0;
1119    GLuint prog = gc->shared->shader.rect.prog;
1120    int pn = 0;
1121    
1122    if (a < 255) blend = 1;
1123    if (gc->dc->render_op == EVAS_RENDER_COPY) blend = 0;
1124    
1125    shader_array_flush(gc);
1126    vertex_array_size_check(gc, gc->state.top_pipe, 2);
1127    pn = gc->state.top_pipe;
1128    gc->pipe[pn].shader.cur_tex = 0;
1129    gc->pipe[pn].shader.cur_prog = prog;
1130    gc->pipe[pn].shader.blend = blend;
1131    gc->pipe[pn].shader.render_op = gc->dc->render_op;
1132    gc->pipe[pn].shader.clip = clip;
1133    gc->pipe[pn].shader.cx = cx;
1134    gc->pipe[pn].shader.cy = cy;
1135    gc->pipe[pn].shader.cw = cw;
1136    gc->pipe[pn].shader.ch = ch;
1137    
1138    gc->pipe[pn].array.line = 1;
1139    gc->pipe[pn].array.use_vertex = 1;
1140    gc->pipe[pn].array.use_color = 1;
1141    gc->pipe[pn].array.use_texuv = 0;
1142    gc->pipe[pn].array.use_texuv2 = 0;
1143    gc->pipe[pn].array.use_texuv3 = 0;
1144    
1145    pnum = gc->pipe[pn].array.num;
1146    nv = pnum * 3; nc = pnum * 4; nu = pnum * 2; nt = pnum * 4;
1147    gc->pipe[pn].array.num += 2;
1148    array_alloc(gc, pn);
1149   
1150    PUSH_VERTEX(pn, x1, y1, 0);
1151    PUSH_VERTEX(pn, x2, y2, 0);
1152    
1153    for (i = 0; i < 2; i++)
1154      {
1155         PUSH_COLOR(pn, r, g, b, a);
1156      }
1157    
1158    shader_array_flush(gc);
1159    gc->pipe[pn].array.line = 0;
1160    gc->pipe[pn].array.use_vertex = 0;
1161    gc->pipe[pn].array.use_color = 0;
1162    gc->pipe[pn].array.use_texuv = 0;
1163    gc->pipe[pn].array.use_texuv2 = 0;
1164    gc->pipe[pn].array.use_texuv3 = 0;
1165 }
1166
1167 void
1168 evas_gl_common_context_rectangle_push(Evas_GL_Context *gc, 
1169                                       int x, int y, int w, int h,
1170                                       int r, int g, int b, int a)
1171 {
1172    int pnum, nv, nc, nu, nt, i;
1173    Eina_Bool blend = 0;
1174    GLuint prog = gc->shared->shader.rect.prog;
1175    int pn = 0;
1176    
1177    if (a < 255) blend = 1;
1178    if (gc->dc->render_op == EVAS_RENDER_COPY) blend = 0;
1179    
1180 again:
1181    vertex_array_size_check(gc, gc->state.top_pipe, 6);
1182    pn = gc->state.top_pipe;
1183 #ifdef GLPIPES
1184    if ((pn == 0) && (gc->pipe[pn].array.num == 0))
1185      {
1186         gc->pipe[pn].region.type = RTYPE_RECT;
1187         gc->pipe[pn].shader.cur_tex = 0;
1188         gc->pipe[pn].shader.cur_prog = prog;
1189         gc->pipe[pn].shader.blend = blend;
1190         gc->pipe[pn].shader.render_op = gc->dc->render_op;
1191         gc->pipe[pn].shader.clip = 0;
1192         gc->pipe[pn].shader.cx = 0;
1193         gc->pipe[pn].shader.cy = 0;
1194         gc->pipe[pn].shader.cw = 0;
1195         gc->pipe[pn].shader.ch = 0;
1196         gc->pipe[pn].array.line = 0;
1197         gc->pipe[pn].array.use_vertex = 1;
1198         gc->pipe[pn].array.use_color = 1;
1199         gc->pipe[pn].array.use_texuv = 0;
1200         gc->pipe[pn].array.use_texuv2 = 0;
1201         gc->pipe[pn].array.use_texuv3 = 0;
1202      }
1203    else
1204      {
1205         int found = 0;
1206         
1207         for (i = pn; i >= 0; i--)
1208           {
1209              if ((gc->pipe[i].region.type == RTYPE_RECT)
1210                  && (gc->pipe[i].shader.cur_tex == 0)
1211                  && (gc->pipe[i].shader.cur_prog == prog)
1212                  && (gc->pipe[i].shader.blend == blend)
1213                  && (gc->pipe[i].shader.render_op == gc->dc->render_op)
1214                  && (gc->pipe[i].shader.clip == 0)
1215                 )
1216                {
1217                   found = 1;
1218                   pn = i;
1219                   break;
1220                }
1221              if (pipe_region_intersects(gc, i, x, y, w, h)) break;
1222           }
1223         if (!found)
1224           {
1225              pn = gc->state.top_pipe + 1;
1226              if (pn >= gc->shared->info.tune.pipes.max)
1227                {
1228                   shader_array_flush(gc);
1229                   goto again;
1230                }
1231              gc->state.top_pipe = pn;
1232              gc->pipe[pn].region.type = RTYPE_RECT;
1233              gc->pipe[pn].shader.cur_tex = 0;
1234              gc->pipe[pn].shader.cur_prog = prog;
1235              gc->pipe[pn].shader.blend = blend;
1236              gc->pipe[pn].shader.render_op = gc->dc->render_op;
1237              gc->pipe[pn].shader.clip = 0;
1238              gc->pipe[pn].shader.cx = 0;
1239              gc->pipe[pn].shader.cy = 0;
1240              gc->pipe[pn].shader.cw = 0;
1241              gc->pipe[pn].shader.ch = 0;
1242              gc->pipe[pn].array.line = 0;
1243              gc->pipe[pn].array.use_vertex = 1;
1244              gc->pipe[pn].array.use_color = 1;
1245              gc->pipe[pn].array.use_texuv = 0;
1246              gc->pipe[pn].array.use_texuv2 = 0;
1247              gc->pipe[pn].array.use_texuv3 = 0;
1248          }
1249      }
1250 #else   
1251    if ((gc->pipe[pn].shader.cur_tex != 0)
1252        || (gc->pipe[pn].shader.cur_prog != prog)
1253        || (gc->pipe[pn].shader.blend != blend)
1254        || (gc->pipe[pn].shader.render_op != gc->dc->render_op)
1255        || (gc->pipe[pn].shader.clip != 0)
1256        )
1257      {
1258         shader_array_flush(gc);
1259         pn = gc->state.top_pipe;
1260         gc->pipe[pn].shader.cur_tex = 0;
1261         gc->pipe[pn].shader.cur_prog = prog;
1262         gc->pipe[pn].shader.blend = blend;
1263         gc->pipe[pn].shader.render_op = gc->dc->render_op;
1264         gc->pipe[pn].shader.clip = 0;
1265         gc->pipe[pn].shader.cx = 0;
1266         gc->pipe[pn].shader.cy = 0;
1267         gc->pipe[pn].shader.cw = 0;
1268         gc->pipe[pn].shader.ch = 0;
1269      }
1270    
1271    gc->pipe[pn].region.type = RTYPE_RECT;
1272    gc->pipe[pn].array.line = 0;
1273    gc->pipe[pn].array.use_vertex = 1;
1274    gc->pipe[pn].array.use_color = 1;
1275    gc->pipe[pn].array.use_texuv = 0;
1276    gc->pipe[pn].array.use_texuv2 = 0;
1277    gc->pipe[pn].array.use_texuv3 = 0;
1278 #endif
1279    
1280    pipe_region_expand(gc, pn, x, y, w, h);
1281    
1282    pnum = gc->pipe[pn].array.num;
1283    nv = pnum * 3; nc = pnum * 4; nu = pnum * 2; nt = pnum * 4;
1284    gc->pipe[pn].array.num += 6;
1285    array_alloc(gc, pn);
1286   
1287    PUSH_VERTEX(pn, x    , y    , 0);
1288    PUSH_VERTEX(pn, x + w, y    , 0);
1289    PUSH_VERTEX(pn, x    , y + h, 0);
1290    
1291    PUSH_VERTEX(pn, x + w, y    , 0);
1292    PUSH_VERTEX(pn, x + w, y + h, 0);
1293    PUSH_VERTEX(pn, x    , y + h, 0);
1294    
1295    for (i = 0; i < 6; i++)
1296      {
1297         PUSH_COLOR(pn, r, g, b, a);
1298      }
1299 }
1300
1301 void
1302 evas_gl_common_context_image_push(Evas_GL_Context *gc,
1303                                   Evas_GL_Texture *tex,
1304                                   double sx, double sy, double sw, double sh,
1305                                   int x, int y, int w, int h,
1306                                   int r, int g, int b, int a,
1307                                   Eina_Bool smooth, Eina_Bool tex_only)
1308 {
1309    int pnum, nv, nc, nu, nu2, nt, i;
1310    GLfloat tx1, tx2, ty1, ty2;
1311    Eina_Bool blend = 1;
1312    GLuint prog = gc->shared->shader.img.prog;
1313    int pn = 0;
1314
1315    if (!tex->alpha) blend = 0;
1316    if (a < 255) blend = 1;
1317    
1318    if (tex_only)
1319      {
1320         if (tex->pt->dyn.img)
1321           {
1322              if ((a == 255) && (r == 255) && (g == 255) && (b == 255))
1323                 prog = gc->shared->shader.img_nomul.prog;
1324              else
1325                 prog = gc->shared->shader.img.prog;
1326           }
1327         else
1328           {
1329              if ((a == 255) && (r == 255) && (g == 255) && (b == 255))
1330                 prog = gc->shared->shader.tex_nomul.prog;
1331              else
1332                 prog = gc->shared->shader.tex.prog;
1333           }
1334      }
1335    else
1336      {
1337         if (tex->gc->shared->info.bgra)
1338           {
1339              if ((a == 255) && (r == 255) && (g == 255) && (b == 255))
1340                prog = gc->shared->shader.img_bgra_nomul.prog;
1341              else
1342                prog = gc->shared->shader.img_bgra.prog;
1343           }
1344         else
1345           {
1346              if ((a == 255) && (r == 255) && (g == 255) && (b == 255))
1347                prog = gc->shared->shader.img_nomul.prog;
1348              else
1349                prog = gc->shared->shader.img.prog;
1350           }
1351      }
1352
1353 again:
1354    vertex_array_size_check(gc, gc->state.top_pipe, 6);
1355    pn = gc->state.top_pipe;
1356 #ifdef GLPIPES
1357    if ((pn == 0) && (gc->pipe[pn].array.num == 0))
1358      {
1359         gc->pipe[pn].region.type = RTYPE_IMAGE;
1360         gc->pipe[pn].shader.cur_tex = tex->pt->texture;
1361         gc->pipe[pn].shader.cur_prog = prog;
1362         gc->pipe[pn].shader.smooth = smooth;
1363         gc->pipe[pn].shader.blend = blend;
1364         gc->pipe[pn].shader.render_op = gc->dc->render_op;
1365         gc->pipe[pn].shader.clip = 0;
1366         gc->pipe[pn].shader.cx = 0;
1367         gc->pipe[pn].shader.cy = 0;
1368         gc->pipe[pn].shader.cw = 0;
1369         gc->pipe[pn].shader.ch = 0;
1370         gc->pipe[pn].array.line = 0;
1371         gc->pipe[pn].array.use_vertex = 1;
1372         // if nomul... dont need this
1373         gc->pipe[pn].array.use_color = 1;
1374         gc->pipe[pn].array.use_texuv = 1;
1375         gc->pipe[pn].array.use_texuv2 = 0;
1376         gc->pipe[pn].array.use_texuv3 = 0;
1377      }
1378    else
1379      {
1380         int found = 0;
1381         
1382         for (i = pn; i >= 0; i--)
1383           {
1384              if ((gc->pipe[i].region.type == RTYPE_IMAGE)
1385                  && (gc->pipe[i].shader.cur_tex == tex->pt->texture)
1386                  && (gc->pipe[i].shader.cur_prog == prog)
1387                  && (gc->pipe[i].shader.smooth == smooth)
1388                  && (gc->pipe[i].shader.blend == blend)
1389                  && (gc->pipe[i].shader.render_op == gc->dc->render_op)
1390                  && (gc->pipe[i].shader.clip == 0)
1391                 )
1392                {
1393                   found = 1;
1394                   pn = i;
1395                   break;
1396                }
1397              if (pipe_region_intersects(gc, i, x, y, w, h)) break;
1398           }
1399         if (!found)
1400           {
1401              pn = gc->state.top_pipe + 1;
1402              if (pn >= gc->shared->info.tune.pipes.max)
1403                {
1404                   shader_array_flush(gc);
1405                   goto again;
1406                }
1407              gc->state.top_pipe = pn;
1408              gc->pipe[pn].region.type = RTYPE_IMAGE;
1409              gc->pipe[pn].shader.cur_tex = tex->pt->texture;
1410              gc->pipe[pn].shader.cur_prog = prog;
1411              gc->pipe[pn].shader.smooth = smooth;
1412              gc->pipe[pn].shader.blend = blend;
1413              gc->pipe[pn].shader.render_op = gc->dc->render_op;
1414              gc->pipe[pn].shader.clip = 0;
1415              gc->pipe[pn].shader.cx = 0;
1416              gc->pipe[pn].shader.cy = 0;
1417              gc->pipe[pn].shader.cw = 0;
1418              gc->pipe[pn].shader.ch = 0;
1419              gc->pipe[pn].array.line = 0;
1420              gc->pipe[pn].array.use_vertex = 1;
1421              // if nomul... dont need this
1422              gc->pipe[pn].array.use_color = 1;
1423              gc->pipe[pn].array.use_texuv = 1;
1424              gc->pipe[pn].array.use_texuv2 = 0;
1425              gc->pipe[pn].array.use_texuv3 = 0;
1426    
1427          }
1428      }
1429    if ((tex->im) && (tex->im->native.data))
1430      {
1431         if (gc->pipe[pn].array.im != tex->im)
1432           {
1433              shader_array_flush(gc);
1434              pn = gc->state.top_pipe;
1435              gc->pipe[pn].array.im = tex->im;
1436              goto again;
1437           }
1438      }
1439    if (tex->pt->dyn.img)
1440      {
1441         if (gc->pipe[pn].array.im != tex->im)
1442           {
1443              shader_array_flush(gc);
1444              pn = gc->state.top_pipe;
1445              gc->pipe[pn].array.im = tex->im;
1446              goto again;
1447           }
1448      }
1449 #else   
1450    if ((gc->pipe[pn].shader.cur_tex != tex->pt->texture)
1451        || (gc->pipe[pn].shader.cur_prog != prog)
1452        || (gc->pipe[pn].shader.smooth != smooth)
1453        || (gc->pipe[pn].shader.blend != blend)
1454        || (gc->pipe[pn].shader.render_op != gc->dc->render_op)
1455        || (gc->pipe[pn].shader.clip != 0)
1456        )
1457      {
1458         shader_array_flush(gc);
1459         gc->pipe[pn].shader.cur_tex = tex->pt->texture;
1460         gc->pipe[pn].shader.cur_prog = prog;
1461         gc->pipe[pn].shader.smooth = smooth;
1462         gc->pipe[pn].shader.blend = blend;
1463         gc->pipe[pn].shader.render_op = gc->dc->render_op;
1464         gc->pipe[pn].shader.clip = 0;
1465         gc->pipe[pn].shader.cx = 0;
1466         gc->pipe[pn].shader.cy = 0;
1467         gc->pipe[pn].shader.cw = 0;
1468         gc->pipe[pn].shader.ch = 0;
1469      } 
1470    if ((tex->im) && (tex->im->native.data))
1471      {
1472         if (gc->pipe[pn].array.im != tex->im)
1473           {
1474              shader_array_flush(gc);
1475              gc->pipe[pn].array.im = tex->im;
1476           }
1477      }
1478    if (tex->pt->dyn.img)
1479      {
1480         if (gc->pipe[pn].array.im != tex->im)
1481           {
1482              shader_array_flush(gc);
1483              gc->pipe[pn].array.im = tex->im;
1484           }
1485      }
1486
1487    gc->pipe[pn].array.line = 0;
1488    gc->pipe[pn].array.use_vertex = 1;
1489    // if nomul... dont need this
1490    gc->pipe[pn].array.use_color = 1;
1491    gc->pipe[pn].array.use_texuv = 1;
1492    gc->pipe[pn].array.use_texuv2 = 0;
1493    gc->pipe[pn].array.use_texuv3 = 0;
1494 #endif
1495
1496    pipe_region_expand(gc, pn, x, y, w, h);
1497   
1498    pnum = gc->pipe[pn].array.num;
1499    nv = pnum * 3; nc = pnum * 4; nu = pnum * 2; nu2 = pnum * 2;
1500    nt = pnum * 4;
1501    gc->pipe[pn].array.num += 6;
1502    array_alloc(gc, pn);
1503
1504    if ((tex->im) && (tex->im->native.data) && (!tex->im->native.yinvert))
1505      {
1506         tx1 = ((double)(tex->x) + sx) / (double)tex->pt->w;
1507         ty1 = ((double)(tex->y) + sy + sh) / (double)tex->pt->h;
1508         tx2 = ((double)(tex->x) + sx + sw) / (double)tex->pt->w;
1509         ty2 = ((double)(tex->y) + sy) / (double)tex->pt->h;
1510      }
1511    else
1512      {
1513         tx1 = ((double)(tex->x) + sx) / (double)tex->pt->w;
1514         ty1 = ((double)(tex->y) + sy) / (double)tex->pt->h;
1515         tx2 = ((double)(tex->x) + sx + sw) / (double)tex->pt->w;
1516         ty2 = ((double)(tex->y) + sy + sh) / (double)tex->pt->h;
1517      }
1518
1519    PUSH_VERTEX(pn, x    , y    , 0);
1520    PUSH_VERTEX(pn, x + w, y    , 0);
1521    PUSH_VERTEX(pn, x    , y + h, 0);
1522    
1523    PUSH_TEXUV(pn, tx1, ty1);
1524    PUSH_TEXUV(pn, tx2, ty1);
1525    PUSH_TEXUV(pn, tx1, ty2);
1526    
1527    PUSH_VERTEX(pn, x + w, y    , 0);
1528    PUSH_VERTEX(pn, x + w, y + h, 0);
1529    PUSH_VERTEX(pn, x    , y + h, 0);
1530    
1531    PUSH_TEXUV(pn, tx2, ty1);
1532    PUSH_TEXUV(pn, tx2, ty2);
1533    PUSH_TEXUV(pn, tx1, ty2);
1534
1535    // if nomul... dont need this
1536    for (i = 0; i < 6; i++)
1537      {
1538         PUSH_COLOR(pn, r, g, b, a);
1539      }
1540 }
1541
1542 void
1543 evas_gl_common_context_font_push(Evas_GL_Context *gc,
1544                                  Evas_GL_Texture *tex,
1545                                  double sx, double sy, double sw, double sh,
1546                                  int x, int y, int w, int h,
1547                                  int r, int g, int b, int a)
1548 {
1549    int pnum, nv, nc, nu, nt, i;
1550    GLfloat tx1, tx2, ty1, ty2;
1551    int pn = 0;
1552
1553 again:
1554    vertex_array_size_check(gc, gc->state.top_pipe, 6);
1555    pn = gc->state.top_pipe;
1556 #ifdef GLPIPES
1557    if ((pn == 0) && (gc->pipe[pn].array.num == 0))
1558      {
1559         gc->pipe[pn].region.type = RTYPE_FONT;
1560         gc->pipe[pn].shader.cur_tex = tex->pt->texture;
1561         gc->pipe[pn].shader.cur_prog = gc->shared->shader.font.prog;
1562         gc->pipe[pn].shader.smooth = 0;
1563         gc->pipe[pn].shader.blend = 1;
1564         gc->pipe[pn].shader.render_op = gc->dc->render_op;
1565         gc->pipe[pn].shader.clip = 0;
1566         gc->pipe[pn].shader.cx = 0;
1567         gc->pipe[pn].shader.cy = 0;
1568         gc->pipe[pn].shader.cw = 0;
1569         gc->pipe[pn].shader.ch = 0;
1570         gc->pipe[pn].array.line = 0;
1571         gc->pipe[pn].array.use_vertex = 1;
1572         gc->pipe[pn].array.use_color = 1;
1573         gc->pipe[pn].array.use_texuv = 1;
1574         gc->pipe[pn].array.use_texuv2 = 0;
1575         gc->pipe[pn].array.use_texuv3 = 0;
1576      }
1577    else
1578      {
1579         int found = 0;
1580         
1581         for (i = pn; i >= 0; i--)
1582           {
1583              if ((gc->pipe[i].region.type == RTYPE_FONT)
1584                  && (gc->pipe[i].shader.cur_tex == tex->pt->texture)
1585                  && (gc->pipe[i].shader.cur_prog == gc->shared->shader.font.prog)
1586                  && (gc->pipe[i].shader.smooth == 0)
1587                  && (gc->pipe[i].shader.blend == 1)
1588                  && (gc->pipe[i].shader.render_op == gc->dc->render_op)
1589                  && (gc->pipe[i].shader.clip == 0)
1590                 )
1591                {
1592                   found = 1;
1593                   pn = i;
1594                   break;
1595                }
1596              if (pipe_region_intersects(gc, i, x, y, w, h)) break;
1597           }
1598         if (!found)
1599           {
1600              pn = gc->state.top_pipe + 1;
1601              if (pn >= gc->shared->info.tune.pipes.max)
1602                {
1603                   shader_array_flush(gc);
1604                   goto again;
1605                }
1606              gc->state.top_pipe = pn;
1607              gc->pipe[pn].region.type = RTYPE_FONT;
1608              gc->pipe[pn].shader.cur_tex = tex->pt->texture;
1609              gc->pipe[pn].shader.cur_prog = gc->shared->shader.font.prog;
1610              gc->pipe[pn].shader.smooth = 0;
1611              gc->pipe[pn].shader.blend = 1;
1612              gc->pipe[pn].shader.render_op = gc->dc->render_op;
1613              gc->pipe[pn].shader.clip = 0;
1614              gc->pipe[pn].shader.cx = 0;
1615              gc->pipe[pn].shader.cy = 0;
1616              gc->pipe[pn].shader.cw = 0;
1617              gc->pipe[pn].shader.ch = 0;
1618              gc->pipe[pn].array.line = 0;
1619              gc->pipe[pn].array.use_vertex = 1;
1620              gc->pipe[pn].array.use_color = 1;
1621              gc->pipe[pn].array.use_texuv = 1;
1622              gc->pipe[pn].array.use_texuv2 = 0;
1623              gc->pipe[pn].array.use_texuv3 = 0;
1624          }
1625      }
1626 #else   
1627    if ((gc->pipe[pn].shader.cur_tex != tex->pt->texture)
1628        || (gc->pipe[pn].shader.cur_prog != gc->shared->shader.font.prog)
1629        || (gc->pipe[pn].shader.smooth != 0)
1630        || (gc->pipe[pn].shader.blend != 1)
1631        || (gc->pipe[pn].shader.render_op != gc->dc->render_op)
1632        || (gc->pipe[pn].shader.clip != 0)
1633        )
1634      {
1635         shader_array_flush(gc);
1636         gc->pipe[pn].shader.cur_tex = tex->pt->texture;
1637         gc->pipe[pn].shader.cur_prog = gc->shared->shader.font.prog;
1638         gc->pipe[pn].shader.smooth = 0;
1639         gc->pipe[pn].shader.blend = 1;
1640         gc->pipe[pn].shader.render_op = gc->dc->render_op;
1641         gc->pipe[pn].shader.clip = 0;
1642         gc->pipe[pn].shader.cx = 0;
1643         gc->pipe[pn].shader.cy = 0;
1644         gc->pipe[pn].shader.cw = 0;
1645         gc->pipe[pn].shader.ch = 0;
1646      }
1647
1648    gc->pipe[pn].region.type = RTYPE_FONT;
1649    gc->pipe[pn].array.line = 0;
1650    gc->pipe[pn].array.use_vertex = 1;
1651    gc->pipe[pn].array.use_color = 1;
1652    gc->pipe[pn].array.use_texuv = 1;
1653    gc->pipe[pn].array.use_texuv2 = 0;
1654    gc->pipe[pn].array.use_texuv3 = 0;
1655 #endif
1656    
1657    pipe_region_expand(gc, pn, x, y, w, h);
1658    
1659    pnum = gc->pipe[pn].array.num;
1660    nv = pnum * 3; nc = pnum * 4; nu = pnum * 2; nt = pnum * 4;
1661    gc->pipe[pn].array.num += 6;
1662    array_alloc(gc, pn);
1663
1664    if (sw == 0.0)
1665      {
1666         tx1 = tex->sx1;
1667         ty1 = tex->sy1;
1668         tx2 = tex->sx2;
1669         ty2 = tex->sy2;
1670      }
1671    else
1672      {
1673         tx1 = ((double)(tex->x) + sx) / (double)tex->pt->w;
1674         ty1 = ((double)(tex->y) + sy) / (double)tex->pt->h;
1675         tx2 = ((double)(tex->x) + sx + sw) / (double)tex->pt->w;
1676         ty2 = ((double)(tex->y) + sy + sh) / (double)tex->pt->h;
1677      }
1678    
1679    PUSH_VERTEX(pn, x    , y    , 0);
1680    PUSH_VERTEX(pn, x + w, y    , 0);
1681    PUSH_VERTEX(pn, x    , y + h, 0);
1682    
1683    PUSH_TEXUV(pn, tx1, ty1);
1684    PUSH_TEXUV(pn, tx2, ty1);
1685    PUSH_TEXUV(pn, tx1, ty2);
1686    
1687    PUSH_VERTEX(pn, x + w, y    , 0);
1688    PUSH_VERTEX(pn, x + w, y + h, 0);
1689    PUSH_VERTEX(pn, x    , y + h, 0);
1690    
1691    PUSH_TEXUV(pn, tx2, ty1);
1692    PUSH_TEXUV(pn, tx2, ty2);
1693    PUSH_TEXUV(pn, tx1, ty2);
1694
1695    for (i = 0; i < 6; i++)
1696      {
1697         PUSH_COLOR(pn, r, g, b, a);
1698      }
1699 }
1700
1701 void
1702 evas_gl_common_context_yuv_push(Evas_GL_Context *gc,
1703                                 Evas_GL_Texture *tex, 
1704                                 double sx, double sy, double sw, double sh,
1705                                 int x, int y, int w, int h,
1706                                 int r, int g, int b, int a,
1707                                 Eina_Bool smooth)
1708 {
1709    int pnum, nv, nc, nu, nu2, nu3, nt, i;
1710    GLfloat tx1, tx2, ty1, ty2, t2x1, t2x2, t2y1, t2y2;
1711    Eina_Bool blend = 0;
1712    GLuint prog = gc->shared->shader.yuv.prog;
1713    int pn = 0;
1714
1715    if (a < 255) blend = 1;
1716    
1717    if ((a == 255) && (r == 255) && (g == 255) && (b == 255))
1718      prog = gc->shared->shader.yuv_nomul.prog;
1719    else
1720      prog = gc->shared->shader.yuv.prog;
1721    
1722 again:
1723    vertex_array_size_check(gc, gc->state.top_pipe, 6);
1724    pn = gc->state.top_pipe;
1725 #ifdef GLPIPES
1726    if ((pn == 0) && (gc->pipe[pn].array.num == 0))
1727      {
1728         gc->pipe[pn].region.type = RTYPE_YUV;
1729         gc->pipe[pn].shader.cur_tex = tex->pt->texture;
1730         gc->pipe[pn].shader.cur_texu = tex->ptu->texture;
1731         gc->pipe[pn].shader.cur_texv = tex->ptv->texture;
1732         gc->pipe[pn].shader.cur_prog = prog;
1733         gc->pipe[pn].shader.smooth = smooth;
1734         gc->pipe[pn].shader.blend = blend;
1735         gc->pipe[pn].shader.render_op = gc->dc->render_op;
1736         gc->pipe[pn].shader.clip = 0;
1737         gc->pipe[pn].shader.cx = 0;
1738         gc->pipe[pn].shader.cy = 0;
1739         gc->pipe[pn].shader.cw = 0;
1740         gc->pipe[pn].shader.ch = 0;
1741         gc->pipe[pn].array.line = 0;
1742         gc->pipe[pn].array.use_vertex = 1;
1743         gc->pipe[pn].array.use_color = 1;
1744         gc->pipe[pn].array.use_texuv = 1;
1745         gc->pipe[pn].array.use_texuv2 = 1;
1746         gc->pipe[pn].array.use_texuv3 = 1;
1747      }
1748    else
1749      {
1750         int found = 0;
1751         
1752         for (i = pn; i >= 0; i--)
1753           {
1754              if ((gc->pipe[i].region.type == RTYPE_YUV)
1755                  && (gc->pipe[i].shader.cur_tex == tex->pt->texture)
1756                  && (gc->pipe[i].shader.cur_prog == gc->shared->shader.font.prog)
1757                  && (gc->pipe[i].shader.smooth == smooth)
1758                  && (gc->pipe[i].shader.blend == blend)
1759                  && (gc->pipe[i].shader.render_op == gc->dc->render_op)
1760                  && (gc->pipe[i].shader.clip == 0)
1761                 )
1762                {
1763                   found = 1;
1764                   pn = i;
1765                   break;
1766                }
1767              if (pipe_region_intersects(gc, i, x, y, w, h)) break;
1768           }
1769         if (!found)
1770           {
1771              pn = gc->state.top_pipe + 1;
1772              if (pn >= gc->shared->info.tune.pipes.max)
1773                {
1774                   shader_array_flush(gc);
1775                   goto again;
1776                }
1777              gc->state.top_pipe = pn;
1778              gc->pipe[pn].region.type = RTYPE_YUV;
1779              gc->pipe[pn].shader.cur_tex = tex->pt->texture;
1780              gc->pipe[pn].shader.cur_texu = tex->ptu->texture;
1781              gc->pipe[pn].shader.cur_texv = tex->ptv->texture;
1782              gc->pipe[pn].shader.cur_prog = prog;
1783              gc->pipe[pn].shader.smooth = smooth;
1784              gc->pipe[pn].shader.blend = blend;
1785              gc->pipe[pn].shader.render_op = gc->dc->render_op;
1786              gc->pipe[pn].shader.clip = 0;
1787              gc->pipe[pn].shader.cx = 0;
1788              gc->pipe[pn].shader.cy = 0;
1789              gc->pipe[pn].shader.cw = 0;
1790              gc->pipe[pn].shader.ch = 0;
1791              gc->pipe[pn].array.line = 0;
1792              gc->pipe[pn].array.use_vertex = 1;
1793              gc->pipe[pn].array.use_color = 1;
1794              gc->pipe[pn].array.use_texuv = 1;
1795              gc->pipe[pn].array.use_texuv2 = 1;
1796              gc->pipe[pn].array.use_texuv3 = 1;
1797          }
1798      }
1799 #else   
1800    if ((gc->pipe[pn].shader.cur_tex != tex->pt->texture)
1801        || (gc->pipe[pn].shader.cur_prog != prog)
1802        || (gc->pipe[pn].shader.smooth != smooth)
1803        || (gc->pipe[pn].shader.blend != blend)
1804        || (gc->pipe[pn].shader.render_op != gc->dc->render_op)
1805        || (gc->pipe[pn].shader.clip != 0)
1806        )
1807      {
1808         shader_array_flush(gc);
1809         gc->pipe[pn].shader.cur_tex = tex->pt->texture;
1810         gc->pipe[pn].shader.cur_texu = tex->ptu->texture;
1811         gc->pipe[pn].shader.cur_texv = tex->ptv->texture;
1812         gc->pipe[pn].shader.cur_prog = prog;
1813         gc->pipe[pn].shader.smooth = smooth;
1814         gc->pipe[pn].shader.blend = blend;
1815         gc->pipe[pn].shader.render_op = gc->dc->render_op;
1816         gc->pipe[pn].shader.clip = 0;
1817         gc->pipe[pn].shader.cx = 0;
1818         gc->pipe[pn].shader.cy = 0;
1819         gc->pipe[pn].shader.cw = 0;
1820         gc->pipe[pn].shader.ch = 0;
1821      }
1822    
1823    gc->pipe[pn].region.type = RTYPE_YUV;
1824    gc->pipe[pn].array.line = 0;
1825    gc->pipe[pn].array.use_vertex = 1;
1826    gc->pipe[pn].array.use_color = 1;
1827    gc->pipe[pn].array.use_texuv = 1;
1828    gc->pipe[pn].array.use_texuv2 = 1;
1829    gc->pipe[pn].array.use_texuv3 = 1;
1830 #endif
1831    
1832    pipe_region_expand(gc, pn, x, y, w, h);
1833    
1834    pnum = gc->pipe[pn].array.num;
1835    nv = pnum * 3; nc = pnum * 4; nu = pnum * 2; 
1836    nu2 = pnum * 2; nu3 = pnum * 2; nt = pnum * 4;
1837    gc->pipe[pn].array.num += 6;
1838    array_alloc(gc, pn);
1839
1840    tx1 = (sx) / (double)tex->pt->w;
1841    ty1 = (sy) / (double)tex->pt->h;
1842    tx2 = (sx + sw) / (double)tex->pt->w;
1843    ty2 = (sy + sh) / (double)tex->pt->h;
1844    
1845    t2x1 = ((sx) / 2) / (double)tex->ptu->w;
1846    t2y1 = ((sy) / 2) / (double)tex->ptu->h;
1847    t2x2 = ((sx + sw) / 2) / (double)tex->ptu->w;
1848    t2y2 = ((sy + sh) / 2) / (double)tex->ptu->h;
1849    
1850    PUSH_VERTEX(pn, x    , y    , 0);
1851    PUSH_VERTEX(pn, x + w, y    , 0);
1852    PUSH_VERTEX(pn, x    , y + h, 0);
1853    
1854    PUSH_TEXUV(pn, tx1, ty1);
1855    PUSH_TEXUV(pn, tx2, ty1);
1856    PUSH_TEXUV(pn, tx1, ty2);
1857    
1858    PUSH_TEXUV2(pn, t2x1, t2y1);
1859    PUSH_TEXUV2(pn, t2x2, t2y1);
1860    PUSH_TEXUV2(pn, t2x1, t2y2);
1861    
1862    PUSH_TEXUV3(pn, t2x1, t2y1);
1863    PUSH_TEXUV3(pn, t2x2, t2y1);
1864    PUSH_TEXUV3(pn, t2x1, t2y2);
1865    
1866    PUSH_VERTEX(pn, x + w, y    , 0);
1867    PUSH_VERTEX(pn, x + w, y + h, 0);
1868    PUSH_VERTEX(pn, x    , y + h, 0);
1869    
1870    PUSH_TEXUV(pn, tx2, ty1);
1871    PUSH_TEXUV(pn, tx2, ty2);
1872    PUSH_TEXUV(pn, tx1, ty2);
1873
1874    PUSH_TEXUV2(pn, t2x2, t2y1);
1875    PUSH_TEXUV2(pn, t2x2, t2y2);
1876    PUSH_TEXUV2(pn, t2x1, t2y2);
1877
1878    PUSH_TEXUV3(pn, t2x2, t2y1);
1879    PUSH_TEXUV3(pn, t2x2, t2y2);
1880    PUSH_TEXUV3(pn, t2x1, t2y2);
1881
1882    for (i = 0; i < 6; i++)
1883      {
1884         PUSH_COLOR(pn, r, g, b, a);
1885      }
1886 }
1887
1888 void
1889 evas_gl_common_context_image_map4_push(Evas_GL_Context *gc,
1890                                        Evas_GL_Texture *tex,
1891                                        RGBA_Map_Point *p,
1892                                        int clip, int cx, int cy, int cw, int ch,
1893                                        int r, int g, int b, int a,
1894                                        Eina_Bool smooth, Eina_Bool tex_only,
1895                                        Eina_Bool yuv)
1896 {
1897    int pnum, nv, nc, nu, nu2, nu3, nt, i;
1898    const int points[6] = { 0, 1, 2, 0, 2, 3 };
1899    int x = 0, y = 0, w = 0, h = 0, px = 0, py = 0;
1900    GLfloat tx[4], ty[4], t2x[4], t2y[4];
1901    Eina_Bool blend = 1;
1902    DATA32 cmul;
1903    GLuint prog = gc->shared->shader.img.prog;
1904    int pn = 0;
1905    int flat = 0;
1906
1907    if (!tex->alpha) blend = 0;
1908    if (a < 255) blend = 1;
1909    if ((A_VAL(&(p[0].col)) < 0xff) || (A_VAL(&(p[1].col)) < 0xff) ||
1910        (A_VAL(&(p[2].col)) < 0xff) || (A_VAL(&(p[3].col)) < 0xff))
1911      blend = 1;
1912    
1913    if ((p[0].z == p[1].z) && (p[1].z == p[2].z) && (p[2].z == p[3].z))
1914       flat = 1;
1915
1916    if (!clip) cx = cy = cw = ch = 0;
1917    
1918    if (!flat)
1919      {
1920         if (p[0].foc <= 0) flat = 1;
1921      }
1922    if (yuv)
1923      {
1924         prog = gc->shared->shader.yuv.prog;
1925         if ((a == 255) && (r == 255) && (g == 255) && (b == 255))
1926           {
1927              if ((p[0].col == 0xffffffff) && (p[1].col == 0xffffffff) &&
1928                  (p[2].col == 0xffffffff) && (p[3].col == 0xffffffff))
1929                 prog = gc->shared->shader.yuv_nomul.prog;
1930              else
1931                 prog = gc->shared->shader.yuv.prog;
1932           }
1933         else
1934            prog = gc->shared->shader.yuv.prog;
1935      }
1936    else
1937      {
1938         if (tex_only)
1939           {
1940              if (tex->pt->dyn.img)
1941                {
1942                   if ((a == 255) && (r == 255) && (g == 255) && (b == 255))
1943                     {
1944                        if ((p[0].col == 0xffffffff) && (p[1].col == 0xffffffff) &&
1945                            (p[2].col == 0xffffffff) && (p[3].col == 0xffffffff))
1946                           prog = gc->shared->shader.img_nomul.prog;
1947                        else
1948                           prog = gc->shared->shader.img.prog;
1949                     }
1950                   else
1951                      prog = gc->shared->shader.img.prog;
1952                }
1953              else
1954                {
1955                   if ((a == 255) && (r == 255) && (g == 255) && (b == 255))
1956                     {
1957                        if ((p[0].col == 0xffffffff) && (p[1].col == 0xffffffff) &&
1958                            (p[2].col == 0xffffffff) && (p[3].col == 0xffffffff))
1959                           prog = gc->shared->shader.tex_nomul.prog;
1960                        else
1961                           prog = gc->shared->shader.tex.prog;
1962                     }
1963                   else
1964                      prog = gc->shared->shader.tex.prog;
1965                }
1966           }
1967         else
1968           {
1969              if (tex->gc->shared->info.bgra)
1970                {
1971                   if ((a == 255) && (r == 255) && (g == 255) && (b == 255))
1972                     {
1973                        if ((p[0].col == 0xffffffff) && (p[1].col == 0xffffffff) &&
1974                            (p[2].col == 0xffffffff) && (p[3].col == 0xffffffff))
1975                           prog = gc->shared->shader.img_bgra_nomul.prog;
1976                        else
1977                           prog = gc->shared->shader.img_bgra.prog;
1978                     }
1979                   else
1980                      prog = gc->shared->shader.img_bgra.prog;
1981                }
1982              else
1983                {
1984                   if ((a == 255) && (r == 255) && (g == 255) && (b == 255))
1985                     {
1986                        if ((p[0].col == 0xffffffff) && (p[1].col == 0xffffffff) &&
1987                            (p[2].col == 0xffffffff) && (p[3].col == 0xffffffff))
1988                           prog = gc->shared->shader.img_nomul.prog;
1989                        else
1990                           prog = gc->shared->shader.img.prog;
1991                     }
1992                   else
1993                      prog = gc->shared->shader.img.prog;
1994                }
1995           }
1996      }
1997    
1998    if (!flat)
1999      {
2000         shader_array_flush(gc);
2001         gc->foc = p[0].foc >> FP;
2002         gc->z0 = p[0].z0 >> FP;
2003         gc->px = p[0].px >> FP;
2004         gc->py = p[0].py >> FP;
2005         gc->change.size = 1;
2006         _evas_gl_common_viewport_set(gc);
2007      }
2008 again:
2009    vertex_array_size_check(gc, gc->state.top_pipe, 6);
2010    pn = gc->state.top_pipe;
2011 #ifdef GLPIPES
2012    if ((pn == 0) && (gc->pipe[pn].array.num == 0))
2013      {
2014         gc->pipe[pn].region.type = RTYPE_MAP;
2015         gc->pipe[pn].shader.cur_tex = tex->pt->texture;
2016         if (yuv)
2017           {
2018              gc->pipe[pn].shader.cur_texu = tex->ptu->texture;
2019              gc->pipe[pn].shader.cur_texv = tex->ptv->texture;
2020           }
2021         gc->pipe[pn].shader.cur_prog = prog;
2022         gc->pipe[pn].shader.smooth = smooth;
2023         gc->pipe[pn].shader.blend = blend;
2024         gc->pipe[pn].shader.render_op = gc->dc->render_op;
2025         gc->pipe[pn].shader.clip = clip;
2026         gc->pipe[pn].shader.cx = cx;
2027         gc->pipe[pn].shader.cy = cy;
2028         gc->pipe[pn].shader.cw = cw;
2029         gc->pipe[pn].shader.ch = ch;
2030         gc->pipe[pn].array.line = 0;
2031         gc->pipe[pn].array.use_vertex = 1;
2032         gc->pipe[pn].array.use_color = 1;
2033         gc->pipe[pn].array.use_texuv = 1;
2034         if (yuv)
2035           {
2036              gc->pipe[pn].array.use_texuv2 = 1;
2037              gc->pipe[pn].array.use_texuv3 = 1;
2038           }
2039         else
2040           {
2041              gc->pipe[pn].array.use_texuv2 = 0;
2042              gc->pipe[pn].array.use_texuv3 = 0;
2043           }
2044      }
2045    else
2046      {
2047         int found = 0;
2048         
2049         for (i = pn; i >= 0; i--)
2050           {
2051              if ((gc->pipe[i].region.type == RTYPE_MAP)
2052                  && (gc->pipe[i].shader.cur_tex == tex->pt->texture)
2053                  && (gc->pipe[i].shader.cur_prog == prog)
2054                  && (gc->pipe[i].shader.smooth == smooth)
2055                  && (gc->pipe[i].shader.blend == blend)
2056                  && (gc->pipe[i].shader.render_op == gc->dc->render_op)
2057                  && (gc->pipe[i].shader.clip == clip)
2058                  && (gc->pipe[i].shader.cx == cx)
2059                  && (gc->pipe[i].shader.cy == cy)
2060                  && (gc->pipe[i].shader.cw == cw)
2061                  && (gc->pipe[i].shader.ch == ch)
2062                 )
2063                {
2064                   found = 1;
2065                   pn = i;
2066                   break;
2067                }
2068              if (pipe_region_intersects(gc, i, x, y, w, h)) break;
2069           }
2070         if (!found)
2071           {
2072              pn = gc->state.top_pipe + 1;
2073              if (pn >= gc->shared->info.tune.pipes.max)
2074                {
2075                   shader_array_flush(gc);
2076                   goto again;
2077                }
2078              gc->state.top_pipe = pn;
2079              gc->pipe[pn].region.type = RTYPE_MAP;
2080              gc->pipe[pn].shader.cur_tex = tex->pt->texture;
2081              if (yuv)
2082                {
2083                   gc->pipe[pn].shader.cur_texu = tex->ptu->texture;
2084                   gc->pipe[pn].shader.cur_texv = tex->ptv->texture;
2085                }
2086              gc->pipe[pn].shader.cur_prog = prog;
2087              gc->pipe[pn].shader.smooth = smooth;
2088              gc->pipe[pn].shader.blend = blend;
2089              gc->pipe[pn].shader.render_op = gc->dc->render_op;
2090              gc->pipe[pn].shader.clip = clip;
2091              gc->pipe[pn].shader.cx = cx;
2092              gc->pipe[pn].shader.cy = cy;
2093              gc->pipe[pn].shader.cw = cw;
2094              gc->pipe[pn].shader.ch = ch;
2095              gc->pipe[pn].array.line = 0;
2096              gc->pipe[pn].array.use_vertex = 1;
2097              gc->pipe[pn].array.use_color = 1;
2098              gc->pipe[pn].array.use_texuv = 1;
2099              if (yuv)
2100                {
2101                   gc->pipe[pn].array.use_texuv2 = 1;
2102                   gc->pipe[pn].array.use_texuv3 = 1;
2103                }
2104              else
2105                {
2106                   gc->pipe[pn].array.use_texuv2 = 0;
2107                   gc->pipe[pn].array.use_texuv3 = 0;
2108                }
2109          }
2110      }
2111    if ((tex->im) && (tex->im->native.data))
2112      {
2113         if (gc->pipe[pn].array.im != tex->im)
2114           {
2115              shader_array_flush(gc);
2116              pn = gc->state.top_pipe;
2117              gc->pipe[pn].array.im = tex->im;
2118              goto again;
2119           }
2120      }
2121    if (tex->pt->dyn.img)
2122      {
2123         if (gc->pipe[pn].array.im != tex->im)
2124           {
2125              shader_array_flush(gc);
2126              pn = gc->state.top_pipe;
2127              gc->pipe[pn].array.im = tex->im;
2128              goto again;
2129           }
2130      }
2131 #else   
2132    if ((gc->pipe[pn].shader.cur_tex != tex->pt->texture)
2133        || (gc->pipe[pn].shader.cur_prog != prog)
2134        || (gc->pipe[pn].shader.smooth != smooth)
2135        || (gc->pipe[pn].shader.blend != blend)
2136        || (gc->pipe[pn].shader.render_op != gc->dc->render_op)
2137        || (gc->pipe[pn].shader.clip != clip)
2138        || (gc->pipe[pn].shader.cx != cx)
2139        || (gc->pipe[pn].shader.cy != cy)
2140        || (gc->pipe[pn].shader.cw != cw)
2141        || (gc->pipe[pn].shader.ch != ch)
2142        )
2143      {
2144         shader_array_flush(gc);
2145         gc->pipe[pn].shader.cur_tex = tex->pt->texture;
2146         gc->pipe[pn].shader.cur_prog = prog;
2147         gc->pipe[pn].shader.smooth = smooth;
2148         gc->pipe[pn].shader.blend = blend;
2149         gc->pipe[pn].shader.render_op = gc->dc->render_op;
2150         gc->pipe[pn].shader.clip = clip;
2151         gc->pipe[pn].shader.cx = cx;
2152         gc->pipe[pn].shader.cy = cy;
2153         gc->pipe[pn].shader.cw = cw;
2154         gc->pipe[pn].shader.ch = ch;
2155      }
2156    if ((tex->im) && (tex->im->native.data))
2157      {
2158         if (gc->pipe[pn].array.im != tex->im)
2159           {
2160              shader_array_flush(gc);
2161              gc->pipe[pn].array.im = tex->im;
2162           }
2163      }
2164    if (tex->pt->dyn.img)
2165      {
2166         if (gc->pipe[pn].array.im != tex->im)
2167           {
2168              shader_array_flush(gc);
2169              gc->pipe[pn].array.im = tex->im;
2170           }
2171      }
2172
2173    gc->pipe[pn].region.type = RTYPE_MAP;
2174    gc->pipe[pn].array.line = 0;
2175    gc->pipe[pn].array.use_vertex = 1;
2176    gc->pipe[pn].array.use_color = 1;
2177    gc->pipe[pn].array.use_texuv = 1;
2178    if (yuv)
2179      {
2180         gc->pipe[pn].array.use_texuv2 = 1;
2181         gc->pipe[pn].array.use_texuv3 = 1;
2182      }
2183    else
2184      {
2185         gc->pipe[pn].array.use_texuv2 = 0;
2186         gc->pipe[pn].array.use_texuv3 = 0;
2187      }
2188 #endif   
2189    
2190    x = w = (p[points[0]].x >> FP);
2191    y = h = (p[points[0]].y >> FP);
2192    for (i = 0; i < 4; i++)
2193      {
2194         tx[i] = ((double)(tex->x) + (((double)p[i].u) / FP1)) /
2195           (double)tex->pt->w;
2196         ty[i] = ((double)(tex->y) + (((double)p[i].v) / FP1)) / 
2197           (double)tex->pt->h;
2198         px = (p[points[i]].x >> FP);
2199         if      (px < x) x = px;
2200         else if (px > w) w = py;
2201         py = (p[points[i]].y >> FP);
2202         if      (py < y) y = py;
2203         else if (py > h) h = py;
2204         if (yuv)
2205           {
2206              t2x[i] = ((((double)p[i].u / 2) / FP1)) / (double)tex->ptu->w;
2207              t2y[i] = ((((double)p[i].v / 2) / FP1)) / (double)tex->ptu->h;
2208           }
2209      }
2210    w = w - x;
2211    h = h - y;
2212    
2213    pipe_region_expand(gc, pn, x, y, w, h);
2214    
2215    pnum = gc->pipe[pn].array.num;
2216    nv = pnum * 3; nc = pnum * 4; nu = pnum * 2; nu2 = pnum * 2;
2217    nu2 = pnum * 2; nu3 = pnum * 2; nt = pnum * 4;
2218    gc->pipe[pn].array.num += 6;
2219    array_alloc(gc, pn);
2220
2221    if ((tex->im) && (tex->im->native.data) && (!tex->im->native.yinvert))
2222      {
2223         // FIXME: handle yinvert
2224         ERR("not handling inverted y case for map4");
2225      }
2226    
2227    cmul = ARGB_JOIN(a, r, g, b);
2228    for (i = 0; i < 6; i++)
2229      {
2230         DATA32 cl = MUL4_SYM(cmul, p[points[i]].col);
2231         if (flat)
2232           {
2233              PUSH_VERTEX(pn,
2234                          (p[points[i]].x >> FP), 
2235                          (p[points[i]].y >> FP),
2236                          0);
2237           }
2238         else
2239           {
2240              PUSH_VERTEX(pn,
2241                          (p[points[i]].x3 >> FP) + gc->shared->ax, 
2242                          (p[points[i]].y3 >> FP) + gc->shared->ay,
2243                          (p[points[i]].z >> FP) 
2244                          + (gc->shared->foc - gc->shared->z0));
2245           }
2246         PUSH_TEXUV(pn,
2247                    tx[points[i]],
2248                    ty[points[i]]);
2249         if (yuv)
2250           {
2251              PUSH_TEXUV2(pn,
2252                          t2x[points[i]],
2253                          t2y[points[i]]);
2254              PUSH_TEXUV3(pn,
2255                          t2x[points[i]],
2256                          t2y[points[i]]);
2257           }
2258         
2259         PUSH_COLOR(pn,
2260                    R_VAL(&cl),
2261                    G_VAL(&cl),
2262                    B_VAL(&cl),
2263                    A_VAL(&cl));
2264      }
2265    if (!flat)
2266      {
2267         shader_array_flush(gc);
2268         gc->foc = 0;
2269         gc->z0 = 0;
2270         gc->px = 0;
2271         gc->py = 0;
2272         gc->change.size = 1;
2273         _evas_gl_common_viewport_set(gc);
2274      }
2275 }
2276
2277 void
2278 evas_gl_common_context_flush(Evas_GL_Context *gc)
2279 {
2280    shader_array_flush(gc);
2281 }
2282
2283 static void
2284 shader_array_flush(Evas_GL_Context *gc)
2285 {
2286    int i, gw, gh, setclip, cy, fbo = 0, done = 0;
2287    
2288    gw = gc->w;
2289    gh = gc->h;
2290    if (!((gc->pipe[0].shader.surface == gc->def_surface) ||
2291          (!gc->pipe[0].shader.surface)))
2292      {
2293         gw = gc->pipe[0].shader.surface->w;
2294         gh = gc->pipe[0].shader.surface->h;
2295         fbo = 1;
2296      }
2297    for (i = 0; i < gc->shared->info.tune.pipes.max; i++)
2298      {
2299         if (gc->pipe[i].array.num <= 0) break;
2300         setclip = 0;
2301         done++;
2302         gc->flushnum++;
2303         GLERR(__FUNCTION__, __FILE__, __LINE__, "<flush err>");
2304         if (gc->pipe[i].shader.cur_prog != gc->state.current.cur_prog)
2305           {
2306              glUseProgram(gc->pipe[i].shader.cur_prog);
2307              GLERR(__FUNCTION__, __FILE__, __LINE__, "");
2308           }
2309         
2310         if (gc->pipe[i].shader.cur_tex != gc->state.current.cur_tex)
2311           {
2312 #if 0
2313              if (gc->pipe[i].shader.cur_tex)
2314                {
2315                   glEnable(GL_TEXTURE_2D);
2316                   GLERR(__FUNCTION__, __FILE__, __LINE__, "");
2317                }
2318              else
2319                {
2320                   glDisable(GL_TEXTURE_2D);
2321                   GLERR(__FUNCTION__, __FILE__, __LINE__, "");
2322                }
2323 #endif
2324              glActiveTexture(GL_TEXTURE0);
2325              GLERR(__FUNCTION__, __FILE__, __LINE__, "");
2326              glBindTexture(GL_TEXTURE_2D, gc->pipe[i].shader.cur_tex);
2327              GLERR(__FUNCTION__, __FILE__, __LINE__, "");
2328           }
2329         if (gc->pipe[i].array.im)
2330           {
2331 #if defined (GLES_VARIETY_S3C6410) || defined (GLES_VARIETY_SGX)
2332              if (gc->pipe[i].array.im->tex->pt->dyn.img)
2333                {
2334                   secsym_glEGLImageTargetTexture2DOES
2335                      (GL_TEXTURE_2D, gc->pipe[i].array.im->tex->pt->dyn.img);
2336                }
2337              else
2338 #endif                
2339                {
2340                   if (!gc->pipe[i].array.im->native.loose)
2341                     {
2342                        if (gc->pipe[i].array.im->native.func.bind)
2343                           gc->pipe[i].array.im->native.func.bind(gc->pipe[i].array.im->native.func.data, 
2344                                                                  gc->pipe[i].array.im);
2345                     }
2346                }
2347           }
2348         if (gc->pipe[i].shader.render_op != gc->state.current.render_op)
2349           {
2350              switch (gc->pipe[i].shader.render_op)
2351                {
2352                case EVAS_RENDER_BLEND: /**< default op: d = d*(1-sa) + s */
2353                   glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
2354                   GLERR(__FUNCTION__, __FILE__, __LINE__, "");
2355                   break;
2356                case EVAS_RENDER_COPY: /**< d = s */
2357                   gc->pipe[i].shader.blend = 0;
2358                   glBlendFunc(GL_ONE, GL_ONE);
2359                   GLERR(__FUNCTION__, __FILE__, __LINE__, "");
2360                   break;
2361                   // FIXME: fix blend funcs below!
2362                case EVAS_RENDER_BLEND_REL: /**< d = d*(1 - sa) + s*da */
2363                case EVAS_RENDER_COPY_REL: /**< d = s*da */
2364                case EVAS_RENDER_ADD: /**< d = d + s */
2365                case EVAS_RENDER_ADD_REL: /**< d = d + s*da */
2366                case EVAS_RENDER_SUB: /**< d = d - s */
2367                case EVAS_RENDER_SUB_REL: /**< d = d - s*da */
2368                case EVAS_RENDER_TINT: /**< d = d*s + d*(1 - sa) + s*(1 - da) */
2369                case EVAS_RENDER_TINT_REL: /**< d = d*(1 - sa + s) */
2370                case EVAS_RENDER_MASK: /**< d = d*sa */
2371                case EVAS_RENDER_MUL: /**< d = d*s */
2372                default:
2373                   glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
2374                   GLERR(__FUNCTION__, __FILE__, __LINE__, "");
2375                   break;
2376                }
2377           }
2378         if (gc->pipe[i].shader.blend != gc->state.current.blend)
2379           {
2380              if (gc->pipe[i].shader.blend)
2381                {
2382                   glEnable(GL_BLEND);
2383                   GLERR(__FUNCTION__, __FILE__, __LINE__, "");
2384                }
2385              else
2386                {
2387                   glDisable(GL_BLEND);
2388                   GLERR(__FUNCTION__, __FILE__, __LINE__, "");
2389                }
2390           }
2391         if ((gc->pipe[i].shader.smooth != gc->state.current.smooth) ||
2392             (gc->pipe[i].shader.cur_tex != gc->state.current.cur_tex))
2393           {
2394              if (gc->pipe[i].shader.smooth)
2395                {
2396 #ifdef GL_TEXTURE_MAX_ANISOTROPY_EXT
2397                   if (shared->info.anisotropic > 0.0)
2398                     {
2399                        glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, shared->info.anisotropic);
2400                        GLERR(__FUNCTION__, __FILE__, __LINE__, "");
2401                     }
2402 #endif
2403                   glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
2404                   GLERR(__FUNCTION__, __FILE__, __LINE__, "");
2405                   glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
2406                   GLERR(__FUNCTION__, __FILE__, __LINE__, "");
2407                   glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
2408                   GLERR(__FUNCTION__, __FILE__, __LINE__, "");
2409                   glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
2410                   GLERR(__FUNCTION__, __FILE__, __LINE__, "");
2411                }
2412              else
2413                {
2414 #ifdef GL_TEXTURE_MAX_ANISOTROPY_EXT
2415                   if (shared->info.anisotropic > 0.0)
2416                     {
2417                        glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, 1.0);
2418                        GLERR(__FUNCTION__, __FILE__, __LINE__, "");
2419                     }
2420 #endif
2421                   glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
2422                   GLERR(__FUNCTION__, __FILE__, __LINE__, "");
2423                   glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
2424                   GLERR(__FUNCTION__, __FILE__, __LINE__, "");
2425                   glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
2426                   GLERR(__FUNCTION__, __FILE__, __LINE__, "");
2427                   glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
2428                   GLERR(__FUNCTION__, __FILE__, __LINE__, "");
2429                }
2430           }
2431         if (gc->pipe[i].shader.clip != gc->state.current.clip)
2432           {
2433              
2434              if (gc->pipe[i].shader.clip)
2435                {
2436                   cy = gh - gc->pipe[i].shader.cy - gc->pipe[i].shader.ch;
2437                   if (fbo) cy = gc->pipe[i].shader.cy;
2438                   glEnable(GL_SCISSOR_TEST);
2439                   glScissor(gc->pipe[i].shader.cx, cy,
2440                             gc->pipe[i].shader.cw, gc->pipe[i].shader.ch);
2441                   setclip = 1;
2442                }
2443              else
2444                {
2445                   glDisable(GL_SCISSOR_TEST);
2446                   glScissor(0, 0, 0, 0);
2447                }
2448           }
2449         if ((gc->pipe[i].shader.clip) && (!setclip))
2450           {
2451              if ((gc->pipe[i].shader.cx != gc->state.current.cx) ||
2452                  (gc->pipe[i].shader.cy != gc->state.current.cy) ||
2453                  (gc->pipe[i].shader.cw != gc->state.current.cw) ||
2454                  (gc->pipe[i].shader.ch != gc->state.current.ch))
2455                {
2456                   cy = gh - gc->pipe[i].shader.cy - gc->pipe[i].shader.ch;
2457                   if (fbo) cy = gc->pipe[i].shader.cy;
2458                   glScissor(gc->pipe[i].shader.cx, cy,
2459                             gc->pipe[i].shader.cw, gc->pipe[i].shader.ch);
2460                }
2461           }
2462
2463         glVertexAttribPointer(SHAD_VERTEX, 3, GL_SHORT, GL_FALSE, 0, gc->pipe[i].array.vertex);
2464         GLERR(__FUNCTION__, __FILE__, __LINE__, "");
2465         glVertexAttribPointer(SHAD_COLOR, 4, GL_UNSIGNED_BYTE, GL_TRUE, 0, gc->pipe[i].array.color);
2466         GLERR(__FUNCTION__, __FILE__, __LINE__, "");
2467         if (gc->pipe[i].array.use_texuv)
2468           {
2469              glEnableVertexAttribArray(SHAD_TEXUV);
2470              GLERR(__FUNCTION__, __FILE__, __LINE__, "");
2471              glVertexAttribPointer(SHAD_TEXUV, 2, GL_FLOAT, GL_FALSE, 0, gc->pipe[i].array.texuv);
2472              GLERR(__FUNCTION__, __FILE__, __LINE__, "");
2473           }
2474         else
2475           {
2476              glDisableVertexAttribArray(SHAD_TEXUV);
2477              GLERR(__FUNCTION__, __FILE__, __LINE__, "");
2478           }
2479         
2480         if (gc->pipe[i].array.line)
2481           {
2482              glDisableVertexAttribArray(SHAD_TEXUV);
2483              GLERR(__FUNCTION__, __FILE__, __LINE__, "");
2484              glDisableVertexAttribArray(SHAD_TEXUV2); 
2485              GLERR(__FUNCTION__, __FILE__, __LINE__, "");
2486              glDisableVertexAttribArray(SHAD_TEXUV3);
2487              GLERR(__FUNCTION__, __FILE__, __LINE__, "");
2488              glDrawArrays(GL_LINES, 0, gc->pipe[i].array.num);
2489              GLERR(__FUNCTION__, __FILE__, __LINE__, "");
2490           }
2491         else
2492           {
2493              if ((gc->pipe[i].array.use_texuv2) && (gc->pipe[i].array.use_texuv3))
2494                {
2495                   glEnableVertexAttribArray(SHAD_TEXUV2);
2496                   GLERR(__FUNCTION__, __FILE__, __LINE__, "");
2497                   glEnableVertexAttribArray(SHAD_TEXUV3);
2498                   GLERR(__FUNCTION__, __FILE__, __LINE__, "");
2499                   glVertexAttribPointer(SHAD_TEXUV2, 2, GL_FLOAT, GL_FALSE, 0, gc->pipe[i].array.texuv2);
2500                   GLERR(__FUNCTION__, __FILE__, __LINE__, "");
2501                   glVertexAttribPointer(SHAD_TEXUV3, 2, GL_FLOAT, GL_FALSE, 0, gc->pipe[i].array.texuv3);
2502                   GLERR(__FUNCTION__, __FILE__, __LINE__, "");
2503                   glActiveTexture(GL_TEXTURE1);
2504                   GLERR(__FUNCTION__, __FILE__, __LINE__, "");
2505                   glBindTexture(GL_TEXTURE_2D, gc->pipe[i].shader.cur_texu);
2506                   GLERR(__FUNCTION__, __FILE__, __LINE__, "");
2507                   glActiveTexture(GL_TEXTURE2);
2508                   GLERR(__FUNCTION__, __FILE__, __LINE__, "");
2509                   glBindTexture(GL_TEXTURE_2D, gc->pipe[i].shader.cur_texv);
2510                   GLERR(__FUNCTION__, __FILE__, __LINE__, "");
2511                   glActiveTexture(GL_TEXTURE0);
2512                   GLERR(__FUNCTION__, __FILE__, __LINE__, "");
2513                }
2514              else if (gc->pipe[i].array.use_texuv2)
2515                {
2516                   glEnableVertexAttribArray(SHAD_TEXUV2);
2517                   GLERR(__FUNCTION__, __FILE__, __LINE__, "");
2518                   glVertexAttribPointer(SHAD_TEXUV2, 2, GL_FLOAT, GL_FALSE, 0, gc->pipe[i].array.texuv2);
2519                   GLERR(__FUNCTION__, __FILE__, __LINE__, "");
2520                }
2521              else
2522                {
2523                   glDisableVertexAttribArray(SHAD_TEXUV2);
2524                   GLERR(__FUNCTION__, __FILE__, __LINE__, "");
2525                   glDisableVertexAttribArray(SHAD_TEXUV3);
2526                   GLERR(__FUNCTION__, __FILE__, __LINE__, "");
2527                }
2528              if (dbgflushnum)
2529                {
2530                   const char *types[6] = 
2531                     {"----", "RECT", "IMAG", "FONT", "YUV-", "MAP"};
2532                   printf("  DRAW#%3i %4i -> %p[%4ix%4i] @ %4ix%4i -{ tex %4i type %s }-\n",
2533                          i,
2534                          gc->pipe[i].array.num / 6, 
2535                          gc->pipe[0].shader.surface,
2536                          gc->pipe[0].shader.surface->w,
2537                          gc->pipe[0].shader.surface->h,
2538                          gw, gh,
2539                          gc->pipe[i].shader.cur_tex,
2540                          types[gc->pipe[i].region.type]
2541                         );
2542                }
2543              glDrawArrays(GL_TRIANGLES, 0, gc->pipe[i].array.num);
2544              GLERR(__FUNCTION__, __FILE__, __LINE__, "");
2545           }
2546         if (gc->pipe[i].array.im)
2547           {
2548              if (!gc->pipe[i].array.im->native.loose)
2549                {
2550                   if (gc->pipe[i].array.im->native.func.unbind)
2551                      gc->pipe[i].array.im->native.func.unbind(gc->pipe[i].array.im->native.func.data, 
2552                                                               gc->pipe[i].array.im);
2553                }
2554              gc->pipe[i].array.im = NULL;
2555           }
2556         
2557         gc->state.current.cur_prog  = gc->pipe[i].shader.cur_prog;
2558         gc->state.current.cur_tex   = gc->pipe[i].shader.cur_tex;
2559         gc->state.current.blend     = gc->pipe[i].shader.blend;
2560         gc->state.current.smooth    = gc->pipe[i].shader.smooth;
2561         gc->state.current.render_op = gc->pipe[i].shader.render_op;
2562         gc->state.current.clip      = gc->pipe[i].shader.clip;
2563         gc->state.current.cx        = gc->pipe[i].shader.cx;
2564         gc->state.current.cy        = gc->pipe[i].shader.cy;
2565         gc->state.current.cw        = gc->pipe[i].shader.cw;
2566         gc->state.current.ch        = gc->pipe[i].shader.ch;
2567         
2568         if (gc->pipe[i].array.vertex) free(gc->pipe[i].array.vertex);
2569         if (gc->pipe[i].array.color) free(gc->pipe[i].array.color);
2570         if (gc->pipe[i].array.texuv) free(gc->pipe[i].array.texuv);
2571         if (gc->pipe[i].array.texuv2) free(gc->pipe[i].array.texuv2);
2572         if (gc->pipe[i].array.texuv3) free(gc->pipe[i].array.texuv3);
2573         
2574         gc->pipe[i].array.vertex = NULL;
2575         gc->pipe[i].array.color = NULL;
2576         gc->pipe[i].array.texuv = NULL;
2577         gc->pipe[i].array.texuv2 = NULL;
2578         gc->pipe[i].array.texuv3 = NULL;
2579
2580         gc->pipe[i].array.num = 0;
2581         gc->pipe[i].array.alloc = 0;
2582         
2583         gc->pipe[i].region.x = 0;
2584         gc->pipe[i].region.y = 0;
2585         gc->pipe[i].region.w = 0;
2586         gc->pipe[i].region.h = 0;
2587         gc->pipe[i].region.type = 0;
2588      }
2589    gc->state.top_pipe = 0;
2590    if (dbgflushnum)
2591      {
2592         if (done > 0) printf("DONE (pipes): %i\n", done);
2593      }
2594 }
2595
2596 Eina_Bool
2597 evas_gl_common_module_open(void)
2598 {
2599    if (_evas_engine_GL_common_log_dom < 0)
2600      _evas_engine_GL_common_log_dom = eina_log_domain_register
2601        ("evas-gl_common", EVAS_DEFAULT_LOG_COLOR);
2602    if (_evas_engine_GL_common_log_dom < 0)
2603      {
2604         EINA_LOG_ERR("Can not create a module log domain.");
2605         return EINA_FALSE;
2606      }
2607    return EINA_TRUE;
2608 }
2609
2610 void
2611 evas_gl_common_module_close(void)
2612 {
2613    if (_evas_engine_GL_common_log_dom < 0) return;
2614    eina_log_domain_unregister(_evas_engine_GL_common_log_dom);
2615    _evas_engine_GL_common_log_dom = -1;
2616 }