add pre/post swap callbacks. need them! :(
[profile/ivi/evas.git] / src / modules / engines / gl_common / evas_gl_context.c
1 #include "evas_gl_private.h"
2
3 static int sym_done = 0;
4
5 void (*glsym_glGenFramebuffers)      (GLsizei a, GLuint *b) = NULL;
6 void (*glsym_glBindFramebuffer)      (GLenum a, GLuint b) = NULL;
7 void (*glsym_glFramebufferTexture2D) (GLenum a, GLenum b, GLenum c, GLuint d, GLint e) = NULL;
8 void (*glsym_glDeleteFramebuffers)   (GLsizei a, const GLuint *b) = NULL;
9
10 static void
11 sym_missing(void)
12 {
13    printf("EVAS ERROR - GL symbols missing!\n");
14 }
15
16 static void
17 gl_symbols(void)
18 {
19    if (sym_done) return;
20    sym_done = 1;
21
22 #define FINDSYM(dst, sym) if (!dst) dst = dlsym(RTLD_DEFAULT, sym)
23 #define FALLBAK(dst) if (!dst) dst = (void *)sym_missing;
24    
25    FINDSYM(glsym_glGenFramebuffers, "glGenFramebuffers");
26    FINDSYM(glsym_glGenFramebuffers, "glGenFramebuffersEXT");
27    FINDSYM(glsym_glGenFramebuffers, "glGenFramebuffersARB");
28    FALLBAK(glsym_glGenFramebuffers);
29    
30    FINDSYM(glsym_glBindFramebuffer, "glBindFramebuffer");
31    FINDSYM(glsym_glBindFramebuffer, "glBindFramebufferEXT");
32    FINDSYM(glsym_glBindFramebuffer, "glBindFramebufferARB");
33    FALLBAK(glsym_glBindFramebuffer);
34    
35    FINDSYM(glsym_glFramebufferTexture2D, "glFramebufferTexture2D");
36    FINDSYM(glsym_glFramebufferTexture2D, "glFramebufferTexture2DEXT");
37    FINDSYM(glsym_glFramebufferTexture2D, "glFramebufferTexture2DARB");
38    FALLBAK(glsym_glFramebufferTexture2D);
39
40    FINDSYM(glsym_glDeleteFramebuffers, "glDeleteFramebuffers");
41    FINDSYM(glsym_glDeleteFramebuffers, "glDeleteFramebuffersEXT");
42    FINDSYM(glsym_glDeleteFramebuffers, "glDeleteFramebuffersARB");
43    FALLBAK(glsym_glDeleteFramebuffers);
44 }
45
46 static void shader_array_flush(Evas_GL_Context *gc);
47
48 static Evas_GL_Context *_evas_gl_common_context = NULL;
49 static Evas_GL_Shared *shared = NULL;
50
51 void
52 glerr(const char *file, const char *func, int line, const char *op)
53 {
54    GLenum err = glGetError();
55    if (err != GL_NO_ERROR)
56      {
57         fprintf(stderr, "GLERR: %s:%i %s(), %s: ", file, line, func, op);
58         switch (err)
59           {
60           case GL_INVALID_ENUM:
61              fprintf(stderr, "GL_INVALID_ENUM\n");
62              break;
63           case GL_INVALID_VALUE:
64              fprintf(stderr, "GL_INVALID_VALUE\n");
65              break;
66           case GL_INVALID_OPERATION:
67              fprintf(stderr, "GL_INVALID_OPERATION\n");
68              break;
69           case GL_OUT_OF_MEMORY:
70              fprintf(stderr, "GL_OUT_OF_MEMORY\n");
71              break;
72           default:
73              fprintf(stderr, "0x%x\n", err);
74           }
75      }
76 }
77
78 static void
79 matrix_ident(GLfloat *m)
80 {
81    memset(m, 0, 16 * sizeof(GLfloat));
82    m[0] = m[5] = m[10] = m[15] = 1.0;
83 }
84
85 static void
86 matrix_ortho(GLfloat *m, 
87              GLfloat l, GLfloat r, 
88              GLfloat t, GLfloat b, 
89              GLfloat near, GLfloat far)
90 {
91    m[0] = 2.0 / (r - l);
92    m[1] = m[2] = m[3] = 0.0;
93    
94    m[4] = 0.0;
95    m[5] = 2.0 / (t - b);
96    m[6] = m[7] = 0.0;
97    
98    m[8] = m[9] = 0.0;
99    m[10] = -(2.0 / (far - near));
100    m[11] = 0.0;
101    
102    m[12] = -((r + l)/(r - l));
103    m[13] = -((t + b)/(t - b));
104    m[14] = -((near + far)/(far - near));
105    m[15] = 1.0;
106 }
107
108 static void
109 _evas_gl_common_viewport_set(Evas_GL_Context *gc)
110 {
111    GLfloat proj[16];
112    int w = 1, h = 1, m = 1;
113
114    if ((gc->shader.surface == gc->def_surface) ||
115        (!gc->shader.surface))
116      {
117         w = gc->w;
118         h = gc->h;
119      }
120    else
121      {
122         w = gc->shader.surface->w;
123         h = gc->shader.surface->h;
124         m = -1;
125      }
126
127    if ((!gc->change.size) || 
128        ((gc->shared->w == w) && (gc->shared->h == h)))
129      return;
130    
131    gc->shared->w = w;
132    gc->shared->h = h;
133    gc->change.size = 0;
134    
135    glViewport(0, 0, w, h);
136    
137    matrix_ident(proj);
138    if (m == 1) matrix_ortho(proj, 0, w, 0, h, -1.0, 1.0);
139    else matrix_ortho(proj, 0, w, h, 0, -1.0, 1.0);
140    
141    glUseProgram(gc->shared->shader.rect.prog);
142    glUniformMatrix4fv(glGetUniformLocation(gc->shared->shader.rect.prog, "mvp"), 1,
143                       GL_FALSE, proj);
144    glUseProgram(gc->shared->shader.img.prog);
145    glUniformMatrix4fv(glGetUniformLocation(gc->shared->shader.img.prog, "mvp"), 1,
146                       GL_FALSE, proj);
147    glUseProgram(gc->shared->shader.font.prog);
148    glUniformMatrix4fv(glGetUniformLocation(gc->shared->shader.font.prog, "mvp"), 1,
149                       GL_FALSE, proj);
150    glUseProgram(gc->shared->shader.yuv.prog);
151    glUniformMatrix4fv(glGetUniformLocation(gc->shared->shader.yuv.prog, "mvp"), 1,
152                       GL_FALSE, proj);
153    glUseProgram(gc->shared->shader.tex.prog);
154    glUniformMatrix4fv(glGetUniformLocation(gc->shared->shader.tex.prog, "mvp"), 1,
155                       GL_FALSE, proj);
156    glUseProgram(gc->shader.cur_prog);
157 }
158
159 Evas_GL_Context *
160 evas_gl_common_context_new(void)
161 {
162    Evas_GL_Context *gc;
163
164    gl_symbols();
165 #if 1
166    if (_evas_gl_common_context)
167      {
168         _evas_gl_common_context->references++;
169         return _evas_gl_common_context;
170      }
171 #endif   
172    gc = calloc(1, sizeof(Evas_GL_Context));
173    if (!gc) return NULL;
174
175    gc->references = 1;
176    
177    _evas_gl_common_context = gc;
178
179    if (!shared)
180      {
181         GLint linked;
182         unsigned int pixel = 0xffffffff;
183         const GLubyte *ext;
184
185         shared = calloc(1, sizeof(Evas_GL_Shared));
186         ext = glGetString(GL_EXTENSIONS);
187         if (ext)
188           {
189              fprintf(stderr, "EXT:\n%s\n", ext);
190              if ((strstr((char*) ext, "GL_ARB_texture_non_power_of_two")) ||
191                  (strstr((char*) ext, "OES_texture_npot")) ||
192                  (strstr((char*) ext, "GL_IMG_texture_npot")))
193                shared->info.tex_npo2 = 1;
194              if ((strstr((char*) ext, "GL_NV_texture_rectangle")) ||
195                  (strstr((char*) ext, "GL_EXT_texture_rectangle")) ||
196                  (strstr((char*) ext, "GL_ARB_texture_rectangle"))
197                  )
198                shared->info.tex_rect = 1;
199           }
200         glGetIntegerv(GL_MAX_TEXTURE_IMAGE_UNITS,
201                       &(shared->info.max_texture_units));
202         glGetIntegerv(GL_MAX_TEXTURE_SIZE,
203                       &(shared->info.max_texture_size));
204         
205         fprintf(stderr, "max tex size %ix%i\n"
206                 "max units %i\n"
207                 "non-power-2 tex %i\n"
208                 "rect tex %i\n"
209                 , 
210                 shared->info.max_texture_size, shared->info.max_texture_size,
211                 shared->info.max_texture_units,
212                 (int)shared->info.tex_npo2,
213                 (int)shared->info.tex_rect
214                 );
215         
216         glDisable(GL_DEPTH_TEST);
217         glEnable(GL_DITHER);
218         glDisable(GL_BLEND);
219         glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
220         // no dest alpha
221 //        glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); // dest alpha
222 //        glBlendFunc(GL_SRC_ALPHA, GL_ONE); // ???
223         glDepthMask(GL_FALSE);
224         
225         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
226         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
227         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
228         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
229 #ifdef GL_TEXTURE_MAX_ANISOTROPY_EXT        
230         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, 16);
231 #endif
232         
233         glEnableVertexAttribArray(SHAD_VERTEX);
234         glEnableVertexAttribArray(SHAD_COLOR);
235         
236         evas_gl_common_shader_program_init(&(shared->shader.rect), 
237                                            &(shader_rect_vert_src), 
238                                            &(shader_rect_frag_src),
239                                            "rect");
240         evas_gl_common_shader_program_init(&(shared->shader.img),
241                                            &(shader_img_vert_src),
242                                            &(shader_img_frag_src),
243                                            "img");
244         evas_gl_common_shader_program_init(&(shared->shader.font),
245                                            &(shader_font_vert_src), 
246                                            &(shader_font_frag_src),
247                                            "font");
248         evas_gl_common_shader_program_init(&(shared->shader.yuv),
249                                            &(shader_yuv_vert_src), 
250                                            &(shader_yuv_frag_src),
251                                            "yuv");
252         evas_gl_common_shader_program_init(&(shared->shader.tex),
253                                            &(shader_tex_vert_src), 
254                                            &(shader_tex_frag_src),
255                                            "tex");
256         glUseProgram(shared->shader.yuv.prog);
257         glUniform1i(glGetUniformLocation(shared->shader.yuv.prog, "tex"), 0);
258         glUniform1i(glGetUniformLocation(shared->shader.yuv.prog, "texu"), 1);
259         glUniform1i(glGetUniformLocation(shared->shader.yuv.prog, "texv"), 2);
260         glUseProgram(gc->shader.cur_prog);
261         // in shader:
262         // uniform sampler2D tex[8];
263         // 
264         // in code:
265         // GLuint texes[8];
266         // GLint loc = glGetUniformLocation(prog, "tex");
267         // glUniform1iv(loc, 8, texes);
268      }
269    gc->shared = shared;
270    gc->shared->references++;
271    _evas_gl_common_viewport_set(gc);
272    
273    gc->def_surface = evas_gl_common_image_surface_new(gc, 1, 1, 1);
274    
275    return gc;
276 }
277
278 void
279 evas_gl_common_context_free(Evas_GL_Context *gc)
280 {
281    int i, j;
282    
283    gc->references--;
284    if (gc->references > 0) return;
285    gc->shared->references--;
286    
287    evas_gl_common_image_free(gc->def_surface);
288    
289    if (gc->shared->references == 0)
290      {
291         while (gc->shared->images)
292           {
293              evas_gl_common_image_free(gc->shared->images->data);
294           }
295         while (gc->shared->tex.whole)
296           {
297              evas_gl_common_texture_free(gc->shared->tex.whole->data);
298           }
299         for (i = 0; i < 33; i++)
300           {
301              for (j = 0; j < 3; j++)
302                {
303                   while (gc->shared->tex.atlas[i][j])
304                     evas_gl_common_texture_free
305                     ((Evas_GL_Texture *)gc->shared->tex.atlas[i][j]);
306                }
307           }
308         free(gc->shared);
309         shared = NULL;
310      }
311    
312
313    if (gc->array.vertex) free(gc->array.vertex);
314    if (gc->array.color) free(gc->array.color);
315    if (gc->array.texuv) free(gc->array.texuv);
316    if (gc->array.texuv2) free(gc->array.texuv2);
317    if (gc->array.texuv3) free(gc->array.texuv3);
318    
319    if (gc == _evas_gl_common_context) _evas_gl_common_context = NULL;
320    free(gc);
321 }
322
323 void
324 evas_gl_common_context_use(Evas_GL_Context *gc)
325 {
326 //   if (_evas_gl_common_context == gc) return;
327    _evas_gl_common_context = gc;
328    _evas_gl_common_viewport_set(gc);
329 }
330
331 void
332 evas_gl_common_context_resize(Evas_GL_Context *gc, int w, int h)
333 {
334    if ((gc->w == w) && (gc->h == h)) return;
335    gc->change.size = 1;
336    gc->w = w;
337    gc->h = h;
338    if (_evas_gl_common_context == gc) _evas_gl_common_viewport_set(gc);
339 }
340
341 void
342 evas_gl_common_context_target_surface_set(Evas_GL_Context *gc,
343                                           Evas_GL_Image *surface)
344 {
345    if (surface == gc->shader.surface) return;
346    
347    evas_gl_common_context_flush(gc);
348
349    gc->shader.surface = surface;
350    gc->change.size = 1;
351 #if defined (GLES_VARIETY_S3C6410) || defined (GLES_VARIETY_SGX)
352 # ifndef GL_FRAMEBUFFER
353 #  define GL_FRAMEBUFFER GL_FRAMEBUFFER_OES
354 # endif   
355 #else
356 # ifndef GL_FRAMEBUFFER
357 #  define GL_FRAMEBUFFER GL_FRAMEBUFFER_EXT
358 # endif   
359 #endif   
360    if (gc->shader.surface == gc->def_surface)
361      glsym_glBindFramebuffer(GL_FRAMEBUFFER, 0);
362    else
363      glsym_glBindFramebuffer(GL_FRAMEBUFFER, surface->tex->pt->fb);
364    _evas_gl_common_viewport_set(gc);
365 }
366
367 #define PUSH_VERTEX(x, y, z) \
368    gc->array.vertex[nv++] = x; \
369    gc->array.vertex[nv++] = y; \
370    gc->array.vertex[nv++] = z
371 #define PUSH_COLOR(r, g, b, a) \
372    gc->array.color[nc++] = r; \
373    gc->array.color[nc++] = g; \
374    gc->array.color[nc++] = b; \
375    gc->array.color[nc++] = a
376 #define PUSH_TEXUV(u, v) \
377    gc->array.texuv[nu++] = u; \
378    gc->array.texuv[nu++] = v
379 #define PUSH_TEXUV2(u, v) \
380    gc->array.texuv2[nu2++] = u; \
381    gc->array.texuv2[nu2++] = v
382 #define PUSH_TEXUV3(u, v) \
383    gc->array.texuv3[nu3++] = u; \
384    gc->array.texuv3[nu3++] = v
385
386 static inline void
387 _evas_gl_common_context_array_alloc(Evas_GL_Context *gc)
388 {
389    if (gc->array.num <= gc->array.alloc) return;
390    gc->array.alloc += 6 * 1024;
391    if (gc->array.use_vertex)
392      gc->array.vertex = realloc(gc->array.vertex,
393                                 gc->array.alloc * sizeof(GLshort) * 3);
394    if (gc->array.use_color)
395      gc->array.color  = realloc(gc->array.color,
396                                 gc->array.alloc * sizeof(GLubyte) * 4);
397    if (gc->array.use_texuv)
398      gc->array.texuv  = realloc(gc->array.texuv,
399                                 gc->array.alloc * sizeof(GLfloat) * 2);
400    if (gc->array.use_texuv2)
401      gc->array.texuv2  = realloc(gc->array.texuv2,
402                                gc->array.alloc * sizeof(GLfloat) * 2);
403    if (gc->array.use_texuv3)
404      gc->array.texuv3  = realloc(gc->array.texuv3,
405                                  gc->array.alloc * sizeof(GLfloat) * 2);
406 }
407
408 void
409 evas_gl_common_context_line_push(Evas_GL_Context *gc, 
410                                  int x1, int y1, int x2, int y2,
411                                  int clip, int cx, int cy, int cw, int ch,
412                                  int r, int g, int b, int a)
413 {
414    int pnum, nv, nc, nu, nt, i;
415    Eina_Bool blend = 0;
416    
417    shader_array_flush(gc);
418    
419    if (a < 255) blend = 1;
420    if (gc->dc->render_op == EVAS_RENDER_COPY) blend = 0;
421    gc->shader.cur_tex = 0;
422    gc->shader.cur_prog = gc->shared->shader.rect.prog;
423    gc->shader.blend = 1;
424    gc->shader.render_op = gc->dc->render_op;
425    gc->shader.clip = clip;
426    gc->shader.cx = cx;
427    gc->shader.cy = cy;
428    gc->shader.cw = cw;
429    gc->shader.ch = ch;
430    
431    gc->array.line = 1;
432    gc->array.use_vertex = 1;
433    gc->array.use_color = 1;
434    gc->array.use_texuv = 0;
435    gc->array.use_texuv2 = 0;
436    gc->array.use_texuv3 = 0;
437    
438    pnum = gc->array.num;
439    nv = pnum * 3; nc = pnum * 4; nu = pnum * 2; nt = pnum * 4;
440    gc->array.num += 1;
441    _evas_gl_common_context_array_alloc(gc);
442   
443    PUSH_VERTEX(x1, y1, 0);
444    PUSH_VERTEX(x2, y2, 0);
445    
446    for (i = 0; i < 2; i++)
447      {
448         PUSH_COLOR(r, g, b, a);
449      }
450    
451    shader_array_flush(gc);
452    gc->array.line = 0;
453    gc->array.use_vertex = 0;
454    gc->array.use_color = 0;
455    gc->array.use_texuv = 0;
456    gc->array.use_texuv2 = 0;
457    gc->array.use_texuv3 = 0;
458 }
459
460 void
461 evas_gl_common_context_rectangle_push(Evas_GL_Context *gc, 
462                                       int x, int y, int w, int h,
463                                       int r, int g, int b, int a)
464 {
465    int pnum, nv, nc, nu, nt, i;
466    Eina_Bool blend = 0;
467    
468    if (a < 255) blend = 1;
469    if (gc->dc->render_op == EVAS_RENDER_COPY) blend = 0;
470    
471    gc->shader.blend = 1;
472    
473    if ((gc->shader.cur_tex != 0)
474        || (gc->shader.cur_prog != gc->shared->shader.rect.prog)
475 //       || (gc->shader.blend != blend)
476        || (gc->shader.render_op != gc->dc->render_op)
477        || (gc->shader.clip != 0)
478        )
479      {
480         shader_array_flush(gc);
481         gc->shader.cur_tex = 0;
482         gc->shader.cur_prog = gc->shared->shader.rect.prog;
483         gc->shader.blend = 1;
484         gc->shader.render_op = gc->dc->render_op;
485         gc->shader.clip = 0;
486
487      }
488    gc->array.line = 0;
489    gc->array.use_vertex = 1;
490    gc->array.use_color = 1;
491    gc->array.use_texuv = 0;
492    gc->array.use_texuv2 = 0;
493    gc->array.use_texuv3 = 0;
494    
495    pnum = gc->array.num;
496    nv = pnum * 3; nc = pnum * 4; nu = pnum * 2; nt = pnum * 4;
497    gc->array.num += 6;
498    _evas_gl_common_context_array_alloc(gc);
499   
500    PUSH_VERTEX(x    , y    , 0);
501    PUSH_VERTEX(x + w, y    , 0);
502    PUSH_VERTEX(x    , y + h, 0);
503    
504    PUSH_VERTEX(x + w, y    , 0);
505    PUSH_VERTEX(x + w, y + h, 0);
506    PUSH_VERTEX(x    , y + h, 0);
507    
508    for (i = 0; i < 6; i++)
509      {
510         PUSH_COLOR(r, g, b, a);
511      }
512 }
513
514 void
515 evas_gl_common_context_image_push(Evas_GL_Context *gc,
516                                   Evas_GL_Texture *tex,
517                                   double sx, double sy, double sw, double sh,
518                                   int x, int y, int w, int h,
519                                   int r, int g, int b, int a,
520                                   Eina_Bool smooth, Eina_Bool tex_only)
521 {
522    int pnum, nv, nc, nu, nu2, nt, i;
523    GLfloat tx1, tx2, ty1, ty2;
524    GLfloat bl = 1.0;
525    Eina_Bool blend = 1;
526
527    if (tex->pt->format == GL_RGB) blend = 0;
528 //   if (a < 255) blend = 1;
529    
530    gc->shader.blend = 1;
531    
532    if ((gc->shader.cur_tex != tex->pt->texture)
533        || ((tex_only) && (gc->shader.cur_prog != gc->shared->shader.tex.prog))
534        || ((!tex_only) && (gc->shader.cur_prog != gc->shared->shader.img.prog))
535        || (gc->shader.smooth != smooth)
536 //       || (gc->shader.blend != blend)
537        || (gc->shader.render_op != gc->dc->render_op)
538        || (gc->shader.clip != 0)
539        )
540      {
541         shader_array_flush(gc);
542         gc->shader.cur_tex = tex->pt->texture;
543         if (tex_only)
544           gc->shader.cur_prog = gc->shared->shader.tex.prog;
545         else
546           gc->shader.cur_prog =gc->shared->shader.img.prog;
547         gc->shader.smooth = smooth;
548         gc->shader.blend = 1;
549         gc->shader.render_op = gc->dc->render_op;
550         gc->shader.clip = 0;
551      } 
552    if ((tex->im) && (tex->im->native.data))
553      {
554         shader_array_flush(gc);
555         gc->array.im = tex->im;
556      }
557    gc->array.line = 0;
558    gc->array.use_vertex = 1;
559    gc->array.use_color = 1;
560    gc->array.use_texuv = 1;
561    gc->array.use_texuv2 = 1;
562    gc->array.use_texuv3 = 0;
563
564   
565    pnum = gc->array.num;
566    nv = pnum * 3; nc = pnum * 4; nu = pnum * 2; nu2 = pnum * 2;
567    nt = pnum * 4;
568    gc->array.num += 6;
569    _evas_gl_common_context_array_alloc(gc);
570
571    // yinvert!
572    if ((tex->im) && (tex->im->native.data) && (!tex->im->native.yinvert))
573      {
574         tx1 = ((double)(tex->x) + sx) / (double)tex->pt->w;
575         ty1 = ((double)(tex->y) + sy + sh) / (double)tex->pt->h;
576         tx2 = ((double)(tex->x) + sx + sw) / (double)tex->pt->w;
577         ty2 = ((double)(tex->y) + sy) / (double)tex->pt->h;
578      }
579    else
580      {
581         tx1 = ((double)(tex->x) + sx) / (double)tex->pt->w;
582         ty1 = ((double)(tex->y) + sy) / (double)tex->pt->h;
583         tx2 = ((double)(tex->x) + sx + sw) / (double)tex->pt->w;
584         ty2 = ((double)(tex->y) + sy + sh) / (double)tex->pt->h;
585      }
586    if (blend) bl = 0.0;
587
588    PUSH_VERTEX(x    , y    , 0);
589    PUSH_VERTEX(x + w, y    , 0);
590    PUSH_VERTEX(x    , y + h, 0);
591    
592    PUSH_TEXUV(tx1, ty1);
593    PUSH_TEXUV(tx2, ty1);
594    PUSH_TEXUV(tx1, ty2);
595    
596    PUSH_TEXUV2(bl, 0.0);
597    PUSH_TEXUV2(bl, 0.0);
598    PUSH_TEXUV2(bl, 0.0);
599    
600    PUSH_VERTEX(x + w, y    , 0);
601    PUSH_VERTEX(x + w, y + h, 0);
602    PUSH_VERTEX(x    , y + h, 0);
603    
604    PUSH_TEXUV(tx2, ty1);
605    PUSH_TEXUV(tx2, ty2);
606    PUSH_TEXUV(tx1, ty2);
607
608    PUSH_TEXUV2(bl, 0.0);
609    PUSH_TEXUV2(bl, 0.0);
610    PUSH_TEXUV2(bl, 0.0);
611    
612    for (i = 0; i < 6; i++)
613      {
614         PUSH_COLOR(r, g, b, a);
615      }
616
617    if ((tex->im) && (tex->im->native.data))
618      {
619         shader_array_flush(gc);
620         gc->array.im = NULL;
621      }
622 }
623
624 void
625 evas_gl_common_context_font_push(Evas_GL_Context *gc,
626                                  Evas_GL_Texture *tex,
627                                  double sx, double sy, double sw, double sh,
628                                  int x, int y, int w, int h,
629                                  int r, int g, int b, int a)
630 {
631    int pnum, nv, nc, nu, nt, i;
632    GLfloat tx1, tx2, ty1, ty2;
633
634    gc->shader.blend = 1;
635    
636    if ((gc->shader.cur_tex != tex->pt->texture)
637        || (gc->shader.cur_prog != gc->shared->shader.font.prog)
638        || (gc->shader.smooth != 0)
639 //       || (gc->shader.blend != 1)
640        || (gc->shader.render_op != gc->dc->render_op)
641        || (gc->shader.clip != 0)
642        )
643      {
644         shader_array_flush(gc);
645         gc->shader.cur_tex = tex->pt->texture;
646         gc->shader.cur_prog = gc->shared->shader.font.prog;
647         gc->shader.smooth = 0;
648         gc->shader.blend = 1;
649         gc->shader.render_op = gc->dc->render_op;
650         gc->shader.clip = 0;
651      }
652    gc->array.line = 0;
653    gc->array.use_vertex = 1;
654    gc->array.use_color = 1;
655    gc->array.use_texuv = 1;
656    gc->array.use_texuv2 = 0;
657    gc->array.use_texuv3 = 0;
658    
659    pnum = gc->array.num;
660    nv = pnum * 3; nc = pnum * 4; nu = pnum * 2; nt = pnum * 4;
661    gc->array.num += 6;
662    _evas_gl_common_context_array_alloc(gc);
663
664    if (sw == 0.0)
665      {
666         tx1 = tex->sx1;
667         ty1 = tex->sy1;
668         tx2 = tex->sx2;
669         ty2 = tex->sy2;
670      }
671    else
672      {
673         tx1 = ((double)(tex->x) + sx) / (double)tex->pt->w;
674         ty1 = ((double)(tex->y) + sy) / (double)tex->pt->h;
675         tx2 = ((double)(tex->x) + sx + sw) / (double)tex->pt->w;
676         ty2 = ((double)(tex->y) + sy + sh) / (double)tex->pt->h;
677      }
678    
679    PUSH_VERTEX(x    , y    , 0);
680    PUSH_VERTEX(x + w, y    , 0);
681    PUSH_VERTEX(x    , y + h, 0);
682    
683    PUSH_TEXUV(tx1, ty1);
684    PUSH_TEXUV(tx2, ty1);
685    PUSH_TEXUV(tx1, ty2);
686    
687    PUSH_VERTEX(x + w, y    , 0);
688    PUSH_VERTEX(x + w, y + h, 0);
689    PUSH_VERTEX(x    , y + h, 0);
690    
691    PUSH_TEXUV(tx2, ty1);
692    PUSH_TEXUV(tx2, ty2);
693    PUSH_TEXUV(tx1, ty2);
694
695    for (i = 0; i < 6; i++)
696      {
697         PUSH_COLOR(r, g, b, a);
698      }
699 }
700
701 void
702 evas_gl_common_context_yuv_push(Evas_GL_Context *gc,
703                                 Evas_GL_Texture *tex, 
704                                 double sx, double sy, double sw, double sh,
705                                 int x, int y, int w, int h,
706                                 int r, int g, int b, int a,
707                                 Eina_Bool smooth)
708 {
709    int pnum, nv, nc, nu, nu2, nu3, nt, i;
710    GLfloat tx1, tx2, ty1, ty2, t2x1, t2x2, t2y1, t2y2;
711    Eina_Bool blend = 0;
712
713    if (a < 255) blend = 1;
714    
715    gc->shader.blend = 1;
716    
717    if ((gc->shader.cur_tex != tex->pt->texture)
718        || (gc->shader.cur_prog != gc->shared->shader.yuv.prog)
719        || (gc->shader.smooth != smooth)
720 //       || (gc->shader.blend != blend)
721        || (gc->shader.render_op != gc->dc->render_op)
722        || (gc->shader.clip != 0)
723        )
724      {
725         shader_array_flush(gc);
726         gc->shader.cur_tex = tex->pt->texture;
727         gc->shader.cur_texu = tex->ptu->texture;
728         gc->shader.cur_texv = tex->ptv->texture;
729         gc->shader.cur_prog = gc->shared->shader.yuv.prog;
730         gc->shader.smooth = smooth;
731         gc->shader.blend = 1;
732         gc->shader.render_op = gc->dc->render_op;
733         gc->shader.clip = 0;
734      }
735    gc->array.line = 0;
736    gc->array.use_vertex = 1;
737    gc->array.use_color = 1;
738    gc->array.use_texuv = 1;
739    gc->array.use_texuv2 = 1;
740    gc->array.use_texuv3 = 1;
741    
742    pnum = gc->array.num;
743    nv = pnum * 3; nc = pnum * 4; nu = pnum * 2; 
744    nu2 = pnum * 2; nu3 = pnum * 2; nt = pnum * 4;
745    gc->array.num += 6;
746    _evas_gl_common_context_array_alloc(gc);
747
748    tx1 = (sx) / (double)tex->pt->w;
749    ty1 = (sy) / (double)tex->pt->h;
750    tx2 = (sx + sw) / (double)tex->pt->w;
751    ty2 = (sy + sh) / (double)tex->pt->h;
752    
753    t2x1 = ((sx) / 2) / (double)tex->ptu->w;
754    t2y1 = ((sy) / 2) / (double)tex->ptu->h;
755    t2x2 = ((sx + sw) / 2) / (double)tex->ptu->w;
756    t2y2 = ((sy + sh) / 2) / (double)tex->ptu->h;
757    
758    PUSH_VERTEX(x    , y    , 0);
759    PUSH_VERTEX(x + w, y    , 0);
760    PUSH_VERTEX(x    , y + h, 0);
761    
762    PUSH_TEXUV(tx1, ty1);
763    PUSH_TEXUV(tx2, ty1);
764    PUSH_TEXUV(tx1, ty2);
765    
766    PUSH_TEXUV2(t2x1, t2y1);
767    PUSH_TEXUV2(t2x2, t2y1);
768    PUSH_TEXUV2(t2x1, t2y2);
769    
770    PUSH_TEXUV3(t2x1, t2y1);
771    PUSH_TEXUV3(t2x2, t2y1);
772    PUSH_TEXUV3(t2x1, t2y2);
773    
774    PUSH_VERTEX(x + w, y    , 0);
775    PUSH_VERTEX(x + w, y + h, 0);
776    PUSH_VERTEX(x    , y + h, 0);
777    
778    PUSH_TEXUV(tx2, ty1);
779    PUSH_TEXUV(tx2, ty2);
780    PUSH_TEXUV(tx1, ty2);
781
782    PUSH_TEXUV2(t2x2, t2y1);
783    PUSH_TEXUV2(t2x2, t2y2);
784    PUSH_TEXUV2(t2x1, t2y2);
785
786    PUSH_TEXUV3(t2x2, t2y1);
787    PUSH_TEXUV3(t2x2, t2y2);
788    PUSH_TEXUV3(t2x1, t2y2);
789
790    for (i = 0; i < 6; i++)
791      {
792         PUSH_COLOR(r, g, b, a);
793      }
794 }
795
796 void
797 evas_gl_common_context_image_map4_push(Evas_GL_Context *gc,
798                                        Evas_GL_Texture *tex,
799                                        RGBA_Map_Point *p,
800                                        int clip, int cx, int cy, int cw, int ch,
801                                        int r, int g, int b, int a,
802                                        Eina_Bool smooth, Eina_Bool tex_only)
803 {
804    int pnum, nv, nc, nu, nu2, nt, i;
805    const int points[6] = { 0, 1, 2, 0, 2, 3 };
806    GLfloat tx[4], ty[4];
807    GLfloat bl = 1.0;
808    Eina_Bool blend = 1;
809    RGBA_Map_Point *pt;
810    DATA32 cmul;
811
812    gc->shader.blend = 1;
813    
814    if (tex->pt->format == GL_RGB) blend = 0;
815 //   if (a < 255) blend = 1;
816    
817    if ((gc->shader.cur_tex != tex->pt->texture)
818        || ((tex_only) && (gc->shader.cur_prog != gc->shared->shader.tex.prog))
819        || ((!tex_only) && (gc->shader.cur_prog != gc->shared->shader.img.prog))
820        || (gc->shader.smooth != smooth)
821 //       || (gc->shader.blend != blend)
822        || (gc->shader.render_op != gc->dc->render_op)
823        || (gc->shader.clip != clip)
824        || (gc->shader.cx != cx)
825        || (gc->shader.cy != cy)
826        || (gc->shader.cw != cw)
827        || (gc->shader.ch != ch)
828        )
829      {
830         shader_array_flush(gc);
831         gc->shader.cur_tex = tex->pt->texture;
832         if (tex_only)
833           gc->shader.cur_prog = gc->shared->shader.tex.prog;
834         else
835           gc->shader.cur_prog =gc->shared->shader.img.prog; 
836         gc->shader.smooth = smooth;
837         gc->shader.blend = 1;
838         gc->shader.render_op = gc->dc->render_op;
839         gc->shader.clip = clip;
840         gc->shader.cx = cx;
841         gc->shader.cy = cy;
842         gc->shader.cw = cw;
843         gc->shader.ch = ch;
844      }
845    gc->array.line = 0;
846    gc->array.use_vertex = 1;
847    gc->array.use_color = 1;
848    gc->array.use_texuv = 1;
849    gc->array.use_texuv2 = 1;
850    gc->array.use_texuv3 = 0;
851    
852    pnum = gc->array.num;
853    nv = pnum * 3; nc = pnum * 4; nu = pnum * 2; nu2 = pnum * 2;
854    nt = pnum * 4;
855    gc->array.num += 6;
856    _evas_gl_common_context_array_alloc(gc);
857
858    // FIXME: handle yinvert
859    for (i = 0; i < 4; i++)
860      {
861         tx[i] = ((double)(tex->x) + (((double)p[i].u) / FP1)) /
862           (double)tex->pt->w;
863         ty[i] = ((double)(tex->y) + (((double)p[i].v) / FP1)) / 
864           (double)tex->pt->h;
865      }
866    
867    if (blend) bl = 0.0;
868    
869    cmul = ARGB_JOIN(a, r, g, b);
870    for (i = 0; i < 6; i++)
871      {
872         DATA32 cl = MUL4_SYM(cmul, p[points[i]].col);
873         PUSH_VERTEX((p[points[i]].x >> FP), 
874                     (p[points[i]].y >> FP),
875                     0);
876 //                    (p[points[i]].y >> FP) + 4096);
877 //                    (p[points[i]].z >> FP));
878         PUSH_TEXUV(tx[points[i]],
879                    ty[points[i]]);
880         
881         PUSH_TEXUV2(bl, 0.0);
882    
883         PUSH_COLOR(R_VAL(&cl),
884                    G_VAL(&cl),
885                    B_VAL(&cl),
886                    A_VAL(&cl));
887      }
888 }
889
890 void
891 evas_gl_common_context_flush(Evas_GL_Context *gc)
892 {
893    shader_array_flush(gc);
894 //   fprintf(stderr, "------------FRAME: done\n");
895 }
896
897 static void
898 shader_array_flush(Evas_GL_Context *gc)
899 {
900    if (gc->array.num <= 0) return;
901
902 //   fprintf(stderr, "  flush array %i\n", gc->array.num);
903    if (gc->shader.cur_prog != gc->shader.current.cur_prog)
904      glUseProgram(gc->shader.cur_prog);
905
906    if (gc->shader.cur_tex != gc->shader.current.cur_tex)
907      {
908         if (gc->shader.cur_tex) glEnable(GL_TEXTURE_2D);
909         else glDisable(GL_TEXTURE_2D);
910         glActiveTexture(GL_TEXTURE0);
911         glBindTexture(GL_TEXTURE_2D, gc->shader.cur_tex);
912      }
913    if (gc->array.im)
914      {
915         if (gc->array.im->native.func.bind)
916           gc->array.im->native.func.bind(gc->array.im->native.func.data, 
917                                          gc->array.im);
918      }
919    if (gc->shader.render_op != gc->shader.current.render_op)
920      {
921         switch (gc->shader.render_op)
922           {
923           case EVAS_RENDER_BLEND: /**< default op: d = d*(1-sa) + s */
924              glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
925              break;
926           case EVAS_RENDER_COPY: /**< d = s */
927              gc->shader.blend = 0;
928              glBlendFunc(GL_ONE, GL_ONE);
929              break;
930              // FIXME: fix blend funcs below!
931           case EVAS_RENDER_BLEND_REL: /**< d = d*(1 - sa) + s*da */
932           case EVAS_RENDER_COPY_REL: /**< d = s*da */
933           case EVAS_RENDER_ADD: /**< d = d + s */
934           case EVAS_RENDER_ADD_REL: /**< d = d + s*da */
935           case EVAS_RENDER_SUB: /**< d = d - s */
936           case EVAS_RENDER_SUB_REL: /**< d = d - s*da */
937           case EVAS_RENDER_TINT: /**< d = d*s + d*(1 - sa) + s*(1 - da) */
938           case EVAS_RENDER_TINT_REL: /**< d = d*(1 - sa + s) */
939           case EVAS_RENDER_MASK: /**< d = d*sa */
940           case EVAS_RENDER_MUL: /**< d = d*s */
941           default:
942              glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
943              break;
944           }
945      }
946    if (gc->shader.blend != gc->shader.current.blend)
947      {
948         if (gc->shader.blend) glEnable(GL_BLEND);
949         else  glDisable(GL_BLEND);
950      }
951    if (gc->shader.smooth != gc->shader.current.smooth)
952      {
953         if (gc->shader.smooth)
954           {
955 #ifdef GL_TEXTURE_MAX_ANISOTROPY_EXT
956              glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, 16);
957 #endif
958              glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
959              glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
960              glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
961              glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
962           }
963         else
964           {
965 #ifdef GL_TEXTURE_MAX_ANISOTROPY_EXT
966              glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, 1);
967 #endif
968              glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
969              glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
970              glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
971              glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
972           }
973      }
974 /* hmmm this breaks things. must find out why!   
975    if (gc->shader.clip != gc->shader.current.clip)
976      {
977         if (gc->shader.clip)
978           glEnable(GL_SCISSOR_TEST);
979         else
980           {
981              glDisable(GL_SCISSOR_TEST);
982 //             glScissor(0, 0, 0, 0);
983           }
984      }
985    if (gc->shader.clip)
986      {
987         if ((gc->shader.cx != gc->shader.current.cx) ||
988             (gc->shader.cx != gc->shader.current.cx) ||
989             (gc->shader.cx != gc->shader.current.cx) ||
990             (gc->shader.cx != gc->shader.current.cx))
991           {
992              glScissor(gc->shader.cx, 
993                        gc->h - gc->shader.cy - gc->shader.ch,
994                        gc->shader.cw,
995                        gc->shader.ch);
996           }
997 //                    gc->clip.x,
998 //                    gc->h - gc->clip.y - gc->clip.h,
999 //                    gc->clip.w,
1000 //                    gc->clip.h);
1001         
1002      }
1003  */
1004    glVertexAttribPointer(SHAD_VERTEX, 3, GL_SHORT, GL_FALSE, 0, gc->array.vertex);
1005    glVertexAttribPointer(SHAD_COLOR, 4, GL_UNSIGNED_BYTE, GL_TRUE, 0, gc->array.color);
1006    if (gc->array.use_texuv)
1007      {
1008         glEnableVertexAttribArray(SHAD_TEXUV);
1009         glVertexAttribPointer(SHAD_TEXUV, 2, GL_FLOAT, GL_FALSE, 0, gc->array.texuv);
1010      }
1011    else
1012      glDisableVertexAttribArray(SHAD_TEXUV);
1013    
1014    if (gc->array.line)
1015      {
1016         glDisableVertexAttribArray(SHAD_TEXUV);
1017         glDisableVertexAttribArray(SHAD_TEXUV2); 
1018         glDisableVertexAttribArray(SHAD_TEXUV3);
1019         glDrawArrays(GL_LINES, 0, gc->array.num);
1020      }
1021    else
1022      {
1023         if ((gc->array.use_texuv2) && (gc->array.use_texuv3))
1024           {
1025              glEnableVertexAttribArray(SHAD_TEXUV2);
1026              glEnableVertexAttribArray(SHAD_TEXUV3);
1027              glVertexAttribPointer(SHAD_TEXUV2, 2, GL_FLOAT, GL_FALSE, 0, gc->array.texuv2);
1028              glVertexAttribPointer(SHAD_TEXUV3, 2, GL_FLOAT, GL_FALSE, 0, gc->array.texuv3);
1029              glActiveTexture(GL_TEXTURE1);
1030              glBindTexture(GL_TEXTURE_2D, gc->shader.cur_texu);
1031              glActiveTexture(GL_TEXTURE2);
1032              glBindTexture(GL_TEXTURE_2D, gc->shader.cur_texv);
1033              glActiveTexture(GL_TEXTURE0);
1034           }
1035         else if (gc->array.use_texuv2)
1036           {
1037              glEnableVertexAttribArray(SHAD_TEXUV2);
1038              glVertexAttribPointer(SHAD_TEXUV2, 2, GL_FLOAT, GL_FALSE, 0, gc->array.texuv2);
1039           }
1040         else
1041           {
1042              glDisableVertexAttribArray(SHAD_TEXUV2);
1043              glDisableVertexAttribArray(SHAD_TEXUV3);
1044           }
1045    
1046         glDrawArrays(GL_TRIANGLES, 0, gc->array.num);
1047      }
1048    if (gc->array.im)
1049      {
1050         if (gc->array.im->native.func.unbind)
1051           gc->array.im->native.func.unbind(gc->array.im->native.func.data, 
1052                                            gc->array.im);
1053 /*        
1054         gc->shader.cur_tex = 0;
1055         glBindTexture(GL_TEXTURE_2D, gc->shader.cur_tex);
1056         if (gc->shader.cur_tex) glEnable(GL_TEXTURE_2D);
1057         else glDisable(GL_TEXTURE_2D);
1058  */
1059      }
1060
1061    gc->shader.current.cur_prog = gc->shader.cur_prog;
1062    gc->shader.current.cur_tex = gc->shader.cur_tex;
1063    gc->shader.current.blend = gc->shader.blend;
1064    gc->shader.current.smooth = gc->shader.smooth;
1065    gc->shader.current.render_op = gc->shader.render_op;
1066    gc->shader.current.clip = gc->shader.clip;
1067    gc->shader.current.cx = gc->shader.cx;
1068    gc->shader.current.cy = gc->shader.cy;
1069    gc->shader.current.cw = gc->shader.cw;
1070    gc->shader.current.ch = gc->shader.ch;
1071    
1072    if (gc->array.vertex) free(gc->array.vertex);
1073    if (gc->array.color) free(gc->array.color);
1074    if (gc->array.texuv) free(gc->array.texuv);
1075    if (gc->array.texuv2) free(gc->array.texuv2);
1076    if (gc->array.texuv3) free(gc->array.texuv3);
1077    
1078    gc->array.vertex = NULL;
1079    gc->array.color = NULL;
1080    gc->array.texuv = NULL;
1081    gc->array.texuv2 = NULL;
1082    gc->array.texuv3 = NULL;
1083    
1084    gc->array.num = 0;
1085    gc->array.alloc = 0;
1086 }