1 #define _EVAS_GL_CONTEXT_C
2 #include "evas_gl_private.h"
3 
4 #if defined HAVE_DLSYM && ! defined _WIN32
5 # include <dlfcn.h>      /* dlopen,dlclose,etc */
6 #else
7 # error gl_common should not get compiled if dlsym is not found on the system!
8 #endif
9 
10 #define PRG_INVALID NULL
11 
12 static int tbm_sym_done = 0;
13 int _evas_engine_GL_common_log_dom = -1;
14 Cutout_Rects *_evas_gl_common_cutout_rects = NULL;
15 
16 typedef void       (*glsym_func_void) ();
17 typedef void      *(*glsym_func_void_ptr) ();
18 typedef GLboolean  (*glsym_func_boolean) ();
19 typedef const char *(*glsym_func_const_char_ptr) ();
20 
21 void       (*glsym_glGenFramebuffers)      (GLsizei a, GLuint *b) = NULL;
22 void       (*glsym_glBindFramebuffer)      (GLenum a, GLuint b) = NULL;
23 void       (*glsym_glFramebufferTexture2D) (GLenum a, GLenum b, GLenum c, GLuint d, GLint e) = NULL;
24 void       (*glsym_glDeleteFramebuffers)   (GLsizei a, const GLuint *b) = NULL;
25 void       (*glsym_glGetProgramBinary)     (GLuint a, GLsizei b, GLsizei *c, GLenum *d, void *e) = NULL;
26 void       (*glsym_glProgramBinary)        (GLuint a, GLenum b, const void *c, GLint d) = NULL;
27 void       (*glsym_glProgramParameteri)    (GLuint a, GLuint b, GLint d) = NULL;
28 void       (*glsym_glReleaseShaderCompiler)(void) = NULL;
29 void      *(*glsym_glMapBuffer)            (GLenum a, GLenum b) = NULL;
30 GLboolean  (*glsym_glUnmapBuffer)          (GLenum a) = NULL;
31 void       (*glsym_glStartTiling)          (GLuint a, GLuint b, GLuint c, GLuint d, GLuint e) = NULL;
32 void       (*glsym_glEndTiling)            (GLuint a) = NULL;
33 void       (*glsym_glRenderbufferStorageMultisample)(GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height) = NULL;
34 
35 const char *(*glsym_glGetStringi) (GLenum name, GLuint index) = NULL;
36 
37 #ifdef GL_GLES
38 
39 # ifndef GL_LINE_SMOOTH
40 #  define GL_LINE_SMOOTH 0x0B20
41 # endif
42 
43 // just used for finding symbols :)
44 typedef void (*_eng_fn) (void);
45 
46 typedef _eng_fn (*glsym_func_eng_fn) ();
47 typedef int  (*secsym_func_int) ();
48 typedef unsigned int  (*secsym_func_uint) ();
49 typedef void         *(*secsym_func_void_ptr) ();
50 
51 unsigned int   (*eglsym_eglDestroyImage)              (void *a, void *b) = NULL;
52 void           (*secsym_glEGLImageTargetTexture2DOES) (int a, void *b) = NULL;
53 void          *(*secsym_eglMapImageSEC)               (void *a, void *b, int c, int d) = NULL;
54 unsigned int   (*secsym_eglUnmapImageSEC)             (void *a, void *b, int c) = NULL;
55 unsigned int   (*secsym_eglGetImageAttribSEC)         (void *a, void *b, int c, int *d) = NULL;
56 
57 /* This one is now a local wrapper to avoid type mixups */
58 void *        evas_gl_common_eglCreateImage           (EGLDisplay dpy, EGLContext ctx, EGLenum target, EGLClientBuffer buffer, const EGLAttrib *attrib_list);
59 static void * (*eglsym_eglCreateImage)                (EGLDisplay dpy, EGLContext ctx, EGLenum target, EGLClientBuffer buffer, const EGLAttrib *attrib_list) = NULL;
60 static void * (*eglsym_eglCreateImageKHR)             (EGLDisplay dpy, EGLContext ctx, EGLenum target, EGLClientBuffer buffer, const EGLint *e) = NULL;
61 
62 ////////////////////////////////////
63 //libtbm.so.1
64 static void *tbm_lib_handle;
65 
66 void *(*secsym_tbm_surface_create) (int width, int height, unsigned int format) = NULL;
67 int  (*secsym_tbm_surface_destroy) (void *surface) = NULL;
68 int  (*secsym_tbm_surface_map) (void *surface, int opt, void *info) = NULL;
69 int  (*secsym_tbm_surface_unmap) (void *surface) = NULL;
70 int  (*secsym_tbm_surface_get_info) (void *surface, void *info) = NULL;
71 ////////////////////////////////////
72 #else
73 typedef void (*_eng_fn) (void);
74 
75 typedef _eng_fn (*glsym_func_eng_fn) ();
76 #endif
77 
78 static int dbgflushnum = -1;
79 
80 static void
sym_missing(void)81 sym_missing(void)
82 {
83    ERR("GL symbols missing!");
84 }
85 
86 /* This check is based heavily on the check from libepoxy.
87  * Previously we used strstr(), however there are some extensions
88  * whose names are subsets of others.
89  */
90 EAPI Eina_Bool
evas_gl_extension_string_check(const char * exts,const char * ext)91 evas_gl_extension_string_check(const char *exts, const char *ext)
92 {
93    const char *ptr;
94    int len;
95 
96    if (!exts || !ext) return EINA_FALSE;
97    ptr = exts;
98 
99    if (*ptr == '\0')
100      return EINA_FALSE;
101 
102    len = strlen(ext);
103 
104    while (1)
105      {
106         ptr = strstr(ptr, ext);
107         if (!ptr)
108           return EINA_FALSE;
109 
110         if (ptr[len] == ' ' || ptr[len] == '\0')
111           return EINA_TRUE;
112 
113         ptr += len;
114      }
115 }
116 
117 /* Totally gross, but I didn't want to reindent all the
118  * strstr() callers :(
119  */
120 static Evas_Gl_Extension_String_Check _ckext = evas_gl_extension_string_check;
121 
122 static int
_has_ext(const char * ext,const char ** pexts,int * pnum)123 _has_ext(const char *ext, const char **pexts, int *pnum)
124 {
125    if (!ext) return EINA_FALSE;
126 
127    if (glsym_glGetStringi)
128      {
129         GLint num = *pnum, k;
130         if (!num)
131           {
132              glGetIntegerv(GL_NUM_EXTENSIONS, &num);
133              *pnum = num;
134           }
135         for (k = 0; k < num; k++)
136           {
137              const char *support = glsym_glGetStringi(GL_EXTENSIONS, k);
138              if (support && !strcmp(support, ext))
139                return EINA_TRUE;
140           }
141         return EINA_FALSE;
142      }
143    else
144      {
145         const char *exts = *pexts;
146         if (!exts)
147           {
148              exts = (const char *) glGetString(GL_EXTENSIONS);
149              if (!exts) return EINA_FALSE;
150              *pexts = exts;
151           }
152         return _ckext(exts, ext);
153      }
154 }
155 
156 #ifdef GL_GLES
157 
158 EAPI void *
evas_gl_common_eglCreateImage(EGLDisplay dpy,EGLContext ctx,EGLenum target,EGLClientBuffer buffer,const EGLAttrib * attrib_list)159 evas_gl_common_eglCreateImage(EGLDisplay dpy, EGLContext ctx, EGLenum target, EGLClientBuffer buffer, const EGLAttrib *attrib_list)
160 {
161    if (eglsym_eglCreateImageKHR)
162      {
163         int count, i;
164         EGLint *ints = NULL;
165 
166         if (attrib_list)
167           {
168              for (count = 0; attrib_list[count] != EGL_NONE; count += 2);
169              count++;
170              ints = alloca(count * sizeof(EGLint));
171              for (i = 0; i < count; i++)
172                ints[i] = attrib_list[i];
173           }
174         return eglsym_eglCreateImageKHR(dpy, ctx, target, buffer, ints);
175      }
176    if (eglsym_eglCreateImage)
177      return eglsym_eglCreateImage(dpy, ctx, target, buffer, attrib_list);
178    return NULL;
179 }
180 
181 EAPI int
evas_gl_common_eglDestroyImage(EGLDisplay dpy,void * im)182 evas_gl_common_eglDestroyImage(EGLDisplay dpy, void *im)
183 {
184    if (eglsym_eglDestroyImage)
185      return eglsym_eglDestroyImage(dpy, im);
186    return EGL_FALSE;
187 }
188 
189 #endif
190 
191 /* FIXME: return error if a required symbol was not found */
192 EAPI void
evas_gl_symbols(void * (* GetProcAddress)(const char * name),const char * extsn)193 evas_gl_symbols(void *(*GetProcAddress)(const char *name), const char *extsn)
194 {
195    int failed = 0, num = 0;
196    const char *exts = NULL;
197 
198    static int done = 0;
199    if (done) return;
200 
201    if (!extsn) ERR("GL extension string was empty");
202 
203    /* For all extension functions, we need to match with the extension itself
204     * since GetProcAddress() can return a non-NULL value even when the function
205     * does not exist. Drivers can do a runtime mapping depending on the
206     * context. So, we only trust the return value of GetProcAddress() when
207     * we know for sure that the extension exists.
208     *
209     * Thus, if a symbol exists we will always prefer it rather than relying
210     * on GetProcAddress().
211     *
212     * -- jpeg, 2016/08/04
213     */
214 
215    glsym_glGetStringi = dlsym(RTLD_DEFAULT, "glGetStringi");
216 
217 #define FINDSYM(dst, sym, ext, typ) do { \
218    if (!dst) { \
219       if (_has_ext(ext, &exts, &num) && GetProcAddress) \
220         dst = (typ) GetProcAddress(sym); \
221       if (!dst) \
222         dst = (typ) dlsym(RTLD_DEFAULT, sym); \
223    }} while (0)
224 #define FALLBAK(dst, typ) do { \
225    if (!dst) { \
226       ERR("Symbol '%s' could not be found!", (#dst) + 6); \
227       dst = (typ) sym_missing; \
228       failed = EINA_TRUE; \
229    }} while (0)
230 
231 #ifdef GL_GLES
232 
233    FINDSYM(glsym_glGenFramebuffers, "glGenFramebuffers", NULL, glsym_func_void);
234    FALLBAK(glsym_glGenFramebuffers, glsym_func_void);
235 
236    FINDSYM(glsym_glBindFramebuffer, "glBindFramebuffer", NULL, glsym_func_void);
237    FALLBAK(glsym_glBindFramebuffer, glsym_func_void);
238 
239 #else
240 
241    /*
242    Note about FBO APIs (from ARB_framebuffer_object):
243 
244    Framebuffer objects created with the commands defined by the
245    GL_EXT_framebuffer_object extension are defined to be shared, while
246    FBOs created with commands defined by the OpenGL core or
247    GL_ARB_framebuffer_object extension are defined *not* to be shared.
248 
249    [...]
250 
251    Since the above pairs are aliases, the functions of a pair are
252    equivalent.  Note that the functions BindFramebuffer and
253    BindFramebufferEXT are not aliases and neither are the functions
254    BindRenderbuffer and BindRenderbufferEXT.  Because object creation
255    occurs when the framebuffer object is bound for the first time, a
256    framebuffer object can be shared across contexts only if it was first
257    bound with BindFramebufferEXT.  Framebuffers first bound with
258    BindFramebuffer may not be shared across contexts.  Framebuffer
259    objects created with BindFramebufferEXT may subsequently be bound
260    using BindFramebuffer.  Framebuffer objects created with
261    BindFramebuffer may be bound with BindFramebufferEXT provided they are
262    bound to the same context they were created on.
263 
264    Undefined behavior results when using FBOs created by EXT commands
265    through non-EXT interfaces, or vice-versa.
266 
267    Thus, I believe core should come first, then ARB and use EXT as fallback.
268    -- jpeg, 2016/08/04
269 
270    Old note:
271    nvidia tegra3 drivers seem to not expose via getprocaddress, but dlsym finds it:
272    glGenFramebuffers, glBindFramebuffer, glFramebufferTexture2D, glDeleteFramebuffers
273    */
274 
275    FINDSYM(glsym_glGenFramebuffers, "glGenFramebuffers", NULL, glsym_func_void);
276    FINDSYM(glsym_glGenFramebuffers, "glGenFramebuffersARB", "GL_ARB_framebuffer_object", glsym_func_void);
277    FINDSYM(glsym_glGenFramebuffers, "glGenFramebuffersEXT", "GL_EXT_framebuffer_object", glsym_func_void);
278    FALLBAK(glsym_glGenFramebuffers, glsym_func_void);
279 
280    FINDSYM(glsym_glBindFramebuffer, "glBindFramebuffer", NULL, glsym_func_void);
281    FINDSYM(glsym_glBindFramebuffer, "glBindFramebufferARB", "GL_ARB_framebuffer_object", glsym_func_void);
282    FINDSYM(glsym_glBindFramebuffer, "glBindFramebufferEXT", "GL_EXT_framebuffer_object", glsym_func_void);
283    FALLBAK(glsym_glBindFramebuffer, glsym_func_void);
284 
285 #endif
286 
287    FINDSYM(glsym_glFramebufferTexture2D, "glFramebufferTexture2D", NULL, glsym_func_void);
288    FINDSYM(glsym_glFramebufferTexture2D, "glFramebufferTexture2DARB", "GL_ARB_framebuffer_object", glsym_func_void);
289    FINDSYM(glsym_glFramebufferTexture2D, "glFramebufferTexture2DEXT", "GL_EXT_framebuffer_object", glsym_func_void);
290    FALLBAK(glsym_glFramebufferTexture2D, glsym_func_void);
291 
292    FINDSYM(glsym_glDeleteFramebuffers, "glDeleteFramebuffers", NULL, glsym_func_void);
293    FINDSYM(glsym_glDeleteFramebuffers, "glDeleteFramebuffersARB", "GL_ARB_framebuffer_object", glsym_func_void);
294    FINDSYM(glsym_glDeleteFramebuffers, "glDeleteFramebuffersEXT", "GL_EXT_framebuffer_object", glsym_func_void);
295    FALLBAK(glsym_glDeleteFramebuffers, glsym_func_void);
296 
297    // Not sure there's an EXT variant
298    FINDSYM(glsym_glGetProgramBinary, "glGetProgramBinary", NULL, glsym_func_void);
299    FINDSYM(glsym_glGetProgramBinary, "glGetProgramBinaryOES", "GL_OES_get_program_binary", glsym_func_void);
300    FINDSYM(glsym_glGetProgramBinary, "glGetProgramBinaryEXT", "GL_EXT_get_program_binary", glsym_func_void);
301 
302    // Not sure there's an EXT variant
303    FINDSYM(glsym_glProgramBinary, "glProgramBinary", NULL, glsym_func_void);
304    FINDSYM(glsym_glProgramBinary, "glProgramBinaryOES", "GL_OES_get_program_binary", glsym_func_void);
305    FINDSYM(glsym_glProgramBinary, "glProgramBinaryEXT", "GL_EXT_get_program_binary", glsym_func_void);
306 
307    FINDSYM(glsym_glProgramParameteri, "glProgramParameteri", NULL, glsym_func_void);
308    FINDSYM(glsym_glProgramParameteri, "glProgramParameteriEXT", "GL_EXT_separate_shader_objects", glsym_func_void);
309    FINDSYM(glsym_glProgramParameteri, "glProgramParameteriARB", "GL_ARB_geometry_shader4", glsym_func_void);
310 
311    FINDSYM(glsym_glReleaseShaderCompiler, "glReleaseShaderCompiler", NULL, glsym_func_void);
312 #ifndef GL_GLES
313    FINDSYM(glsym_glReleaseShaderCompiler, "glReleaseShaderCompiler", "GL_ARB_ES2_compatibility", glsym_func_void);
314 #endif
315 
316    // Not sure there's a core variant, glActivateTileQCOM is strange as well
317    FINDSYM(glsym_glStartTiling, "glStartTilingQCOM", "GL_QCOM_tiled_rendering", glsym_func_void);
318    FINDSYM(glsym_glStartTiling, "glStartTiling", NULL, glsym_func_void);
319    FINDSYM(glsym_glStartTiling, "glActivateTileQCOM", NULL, glsym_func_void);
320    FINDSYM(glsym_glEndTiling, "glEndTilingQCOM", "GL_QCOM_tiled_rendering", glsym_func_void);
321    FINDSYM(glsym_glEndTiling, "glEndTiling", NULL, glsym_func_void);
322 
323    if (!getenv("EVAS_GL_MAPBUFFER_DISABLE"))
324      {
325         // Not sure there's an EXT variant. (probably no KHR variant)
326         FINDSYM(glsym_glMapBuffer, "glMapBuffer", NULL, glsym_func_void_ptr);
327         FINDSYM(glsym_glMapBuffer, "glMapBufferOES", "GL_OES_mapbuffer", glsym_func_void_ptr);
328         FINDSYM(glsym_glMapBuffer, "glMapBufferARB", "GL_ARB_vertex_buffer_object", glsym_func_void_ptr);
329         FINDSYM(glsym_glMapBuffer, "glMapBufferARB", "GLX_ARB_vertex_buffer_object", glsym_func_void_ptr);
330         FINDSYM(glsym_glMapBuffer, "glMapBufferEXT", NULL, glsym_func_void_ptr);
331 
332         FINDSYM(glsym_glUnmapBuffer, "glUnmapBuffer", NULL, glsym_func_boolean);
333         FINDSYM(glsym_glUnmapBuffer, "glUnmapBufferOES", "GL_OES_mapbuffer", glsym_func_boolean);
334         FINDSYM(glsym_glUnmapBuffer, "glUnmapBufferARB", "GL_ARB_vertex_buffer_object", glsym_func_boolean);
335         FINDSYM(glsym_glUnmapBuffer, "glUnmapBufferARB", "GLX_ARB_vertex_buffer_object", glsym_func_boolean);
336         FINDSYM(glsym_glUnmapBuffer, "glUnmapBufferEXT", NULL, glsym_func_boolean);
337      }
338 
339    FINDSYM(glsym_glRenderbufferStorageMultisample, "glRenderbufferStorageMultisample", NULL, glsym_func_void);
340 
341 #ifdef GL_GLES
342 #define FINDSYMN(dst, sym, ext, typ) do { \
343    if (!dst) { \
344       if (_ckext(extsn, ext) && GetProcAddress) \
345         dst = (typ) GetProcAddress(sym); \
346       if (!dst) \
347         dst = (typ) dlsym(RTLD_DEFAULT, sym); \
348    }} while (0)
349 
350 // yes - gl core looking for egl stuff. i know it's odd. a reverse-layer thing
351 // but it will work as the egl/glx layer calls gl core common stuff and thus
352 // these symbols will work. making the glx/egl + x11 layer do this kind-of is
353 // wrong as this is not x11 (output) layer specific like the native surface
354 // stuff. this is generic zero-copy textures for gl
355 
356    {
357       const char *egl_version = eglQueryString(eglGetCurrentDisplay(), EGL_VERSION);
358       int vmin = 1, vmaj = 0;
359 
360       if (!egl_version || (sscanf(egl_version, "%d.%d", &vmaj, &vmin) != 2))
361         vmaj = 0;
362 
363       // Verify that EGL is >= 1.5 before looking up core function
364       if ((vmaj > 1) || (vmaj == 1 && vmin >= 5))
365         {
366            eglsym_eglCreateImage = dlsym(RTLD_DEFAULT, "eglCreateImage");
367            eglsym_eglDestroyImage = dlsym(RTLD_DEFAULT, "eglDestroyImage");
368         }
369 
370       // For EGL <= 1.4 only the KHR extension exists: "EGL_KHR_image_base"
371       if (!eglsym_eglCreateImage || !eglsym_eglDestroyImage)
372         {
373            eglsym_eglCreateImage = NULL;
374            eglsym_eglDestroyImage = NULL;
375            FINDSYMN(eglsym_eglCreateImageKHR, "eglCreateImageKHR", "EGL_KHR_image_base", secsym_func_void_ptr);
376            FINDSYMN(eglsym_eglDestroyImage, "eglDestroyImageKHR", "EGL_KHR_image_base", secsym_func_uint);
377         }
378    }
379 
380    FINDSYM(glsym_glProgramParameteri, "glProgramParameteri", NULL, glsym_func_void);
381    FINDSYM(glsym_glProgramParameteri, "glProgramParameteriEXT", "GL_EXT_geometry_shader4", glsym_func_void);
382    FINDSYM(glsym_glProgramParameteri, "glProgramParameteriARB", "GL_ARB_geometry_shader4", glsym_func_void);
383 
384    FINDSYMN(secsym_glEGLImageTargetTexture2DOES, "glEGLImageTargetTexture2DOES", "GL_OES_EGL_image_external", glsym_func_void);
385 
386    // Old SEC extensions
387    FINDSYMN(secsym_eglMapImageSEC, "eglMapImageSEC", NULL, secsym_func_void_ptr);
388    FINDSYMN(secsym_eglUnmapImageSEC, "eglUnmapImageSEC", NULL, secsym_func_uint);
389    FINDSYMN(secsym_eglGetImageAttribSEC, "eglGetImageAttribSEC", NULL, secsym_func_uint);
390 
391 #undef FINDSYMN
392 
393 #endif
394 
395 #undef FINDSYM
396 #undef FALLBAK
397 
398    if (failed)
399      {
400         ERR("Some core GL symbols could not be found, the GL engine will not "
401             "work properly.");
402      }
403 
404    done = 1;
405 }
406 
407 static void
tbm_symbols(void)408 tbm_symbols(void)
409 {
410    if (tbm_sym_done) return;
411    tbm_sym_done = 1;
412 
413 #ifdef GL_GLES
414    tbm_lib_handle = dlopen("libtbm.so.1", RTLD_NOW);
415    if (!tbm_lib_handle)
416      {
417         DBG("Unable to open libtbm:  %s", dlerror());
418         return;
419      }
420 
421 #define FINDSYM(dst, sym, typ) \
422    if (!dst) dst = (typ)dlsym(tbm_lib_handle, sym); \
423    if (!dst)  \
424      { \
425         ERR("Symbol not found %s\n", sym); \
426         return; \
427      }
428 
429    FINDSYM(secsym_tbm_surface_create, "tbm_surface_create", secsym_func_void_ptr);
430    FINDSYM(secsym_tbm_surface_destroy, "tbm_surface_destroy", secsym_func_int);
431    FINDSYM(secsym_tbm_surface_map, "tbm_surface_map", secsym_func_int);
432    FINDSYM(secsym_tbm_surface_unmap, "tbm_surface_unmap", secsym_func_int);
433    FINDSYM(secsym_tbm_surface_get_info, "tbm_surface_get_info", secsym_func_int);
434 
435 #undef FINDSYM
436 #endif
437 }
438 
439 static void shader_array_flush(Evas_Engine_GL_Context *gc);
440 
441 static Evas_Engine_GL_Context *_evas_gl_common_context = NULL;
442 static Evas_GL_Shared *shared = NULL;
443 
444 EAPI void
__evas_gl_err(int err,const char * file,const char * func,int line,const char * op)445 __evas_gl_err(int err, const char *file, const char *func, int line, const char *op)
446 {
447    const char *errmsg;
448    char buf[32];
449 
450    switch (err)
451      {
452      case GL_INVALID_ENUM:
453         errmsg = "GL_INVALID_ENUM";
454         break;
455      case GL_INVALID_VALUE:
456         errmsg = "GL_INVALID_VALUE";
457         break;
458      case GL_INVALID_OPERATION:
459         errmsg = "GL_INVALID_OPERATION";
460         break;
461      case GL_OUT_OF_MEMORY:
462         errmsg = "GL_OUT_OF_MEMORY";
463         break;
464 #ifdef GL_INVALID_FRAMEBUFFER_OPERATION
465      case GL_INVALID_FRAMEBUFFER_OPERATION:
466         {
467            GLenum e = glCheckFramebufferStatus(GL_FRAMEBUFFER);
468            switch (e)
469              {
470 #ifdef GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT
471               case GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT:
472                 errmsg = "GL_INVALID_FRAMEBUFFER_OPERATION: GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT";
473                 break;
474 #endif
475 #ifdef GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS
476               case GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS:
477                 errmsg = "GL_INVALID_FRAMEBUFFER_OPERATION: GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS";
478                 break;
479 #endif
480 #ifdef GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT
481               case GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT:
482                 errmsg = "GL_INVALID_FRAMEBUFFER_OPERATION: GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT";
483                 break;
484 #endif
485 #ifdef GL_FRAMEBUFFER_UNSUPPORTED
486               case GL_FRAMEBUFFER_UNSUPPORTED:
487                 errmsg = "GL_INVALID_FRAMEBUFFER_OPERATION: GL_FRAMEBUFFER_UNSUPPORTED";
488                 break;
489 #endif
490               default:
491                 errmsg = "GL_INVALID_FRAMEBUFFER_OPERATION";
492                 break;
493              }
494            break;
495         }
496 #endif
497      default:
498         snprintf(buf, sizeof(buf), "%#x", err);
499         errmsg = buf;
500      }
501 
502    eina_log_print(_evas_engine_GL_common_log_dom, EINA_LOG_LEVEL_ERR,
503                   file, func, line, "%s: %s", op, errmsg);
504 }
505 
506 static void
matrix_ortho(GLfloat * m,GLfloat l,GLfloat r,GLfloat t,GLfloat b,GLfloat near_,GLfloat far_,int rot,int vw,int vh,int foc,GLfloat orth)507 matrix_ortho(GLfloat *m,
508              GLfloat l, GLfloat r,
509              GLfloat t, GLfloat b,
510              GLfloat near_, GLfloat far_,
511              int rot, int vw, int vh,
512              int foc, GLfloat orth)
513 {
514    GLfloat rotf;
515    GLfloat cosv, sinv;
516    GLfloat tx, ty;
517 
518    rotf = (((rot / 90) & 0x3) * M_PI) / 2.0;
519 
520    tx = -0.5 * (1.0 - orth);
521    ty = -0.5 * (1.0 - orth);
522 
523    if (rot == 90)
524      {
525         tx += -(vw * 1.0);
526         ty += -(vh * 0.0);
527      }
528    if (rot == 180)
529      {
530         tx += -(vw * 1.0);
531         ty += -(vh * 1.0);
532      }
533    if (rot == 270)
534      {
535         tx += -(vw * 0.0);
536         ty += -(vh * 1.0);
537      }
538 
539    cosv = cos(rotf);
540    sinv = sin(rotf);
541 
542    m[0] = (2.0 / (r - l)) * ( cosv);
543    m[1] = (2.0 / (r - l)) * ( sinv);
544    m[2] = 0.0;
545    m[3] = 0.0;
546 
547    m[4] = (2.0 / (t - b)) * (-sinv);
548    m[5] = (2.0 / (t - b)) * ( cosv);
549    m[6] = 0.0;
550    m[7] = 0.0;
551 
552    m[8] = 0.0;
553    m[9] = 0.0;
554    m[10] = -(2.0 / (far_ - near_));
555    m[11] = 1.0 / (GLfloat)foc;
556 
557    m[12] = (m[0] * tx) + (m[4] * ty) - ((r + l) / (r - l));
558    m[13] = (m[1] * tx) + (m[5] * ty) - ((t + b) / (t - b));
559    m[14] = (m[2] * tx) + (m[6] * ty) - ((near_ + far_) / (far_ - near_));
560    m[15] = (m[3] * tx) + (m[7] * ty) + orth;
561 }
562 
563 int
evas_gl_common_version_check(int * minor_version)564 evas_gl_common_version_check(int *minor_version)
565 {
566    char *version;
567    char *tmp;
568    char *tmp2;
569    int major = 0;
570    int minor = 0;
571 
572   /*
573    * glGetString returns a string describing the current GL connection.
574    * GL_VERSION is used to get the version of the connection
575    */
576 
577    if (minor_version) *minor_version = 0;
578 
579    version = (char *)glGetString(GL_VERSION);
580    if (!version)
581      {
582         /* Something is wrong! */
583         return 0;
584      }
585 
586   /*
587    * OpengL ES
588    *
589    * 1.* : The form is:
590    *
591    * OpenGL ES-<profile> <major>.<minor>
592    *
593    * where <profile> is either "CM" or "CL". The minor can be followed by the vendor
594    * specific information
595    *
596    * 2.0 : The form is:
597    *
598    * OpenGL<space>ES<space><version number><space><vendor-specific information>
599    */
600 
601    /* OpenGL ES 1.* ? */
602 
603    if (strstr(version, "OpenGL ES-CM ") || strstr(version, "OpenGL ES-CL "))
604      {
605         /* Not supported */
606         return 0;
607      }
608 
609    /* OpenGL ES 3.*  */
610 
611    if (strstr(version, "OpenGL ES 3"))
612      {
613         /* Supported */
614         if (minor_version)
615           {
616              if ((version[11] == '.') && isdigit(version[12]))
617                *minor_version = atoi(&version[12]);
618              else *minor_version = 0;
619           }
620         return 3;
621      }
622 
623    /* OpenGL ES 2.* ? */
624 
625    if (strstr(version, "OpenGL ES "))
626      {
627         /* Supported */
628         if (minor_version)
629           {
630              if ((version[10] == '2') &&
631                  (version[11] == '.') && isdigit(version[12]))
632                *minor_version = atoi(&version[12]);
633              else *minor_version = 0;
634           }
635         return 2;
636      }
637 
638   /*
639    * OpenGL
640    *
641    * The GL_VERSION and GL_SHADING_LANGUAGE_VERSION strings begin with a
642    * version number. The version number uses one of these forms:
643    *
644    * major_number.minor_number
645    * major_number.minor_number.release_number
646    *
647    * Vendor-specific information may follow the version number. Its format
648    * depends on the implementation, but a space always separates the
649    * version number and the vendor-specific information.
650    */
651 
652    /* glGetString() returns a static string, and we are going to */
653    /* modify it, so we get a copy first */
654    version = strdup(version);
655    if (!version)
656      return 0;
657 
658    tmp = strchr(version, '.');
659    if (!tmp) goto fail;
660    /* the first '.' always exists */
661    *tmp = '\0';
662    major = atoi(version);
663    /* FIXME: maybe we can assume that minor in only a cipher */
664    tmp2 = ++tmp;
665    while ((*tmp != '.') && (*tmp != ' ') && (*tmp != '\0'))
666      tmp++;
667    /* *tmp is '\0' : version is major_number.minor_number */
668    /* *tmp is '.'  : version is major_number.minor_number.release_number */
669    /* *tmp is ' '  : version is major_number.minor_number followed by vendor */
670    *tmp = '\0';
671    minor = atoi(tmp2);
672 
673  fail:
674    free(version);
675 
676    // OpenGL 4.5 is supposed to be a superset of GLES 3.1
677    if ((major == 4) && (minor >= 5))
678      {
679         if (minor_version) *minor_version = 1;
680         return 3;
681      }
682 
683    // OpenGL 4.3 is supposed to be a superset of GLES 3.0
684    if ((major == 4) && (minor >= 3))
685      return 3;
686 
687    // Extension GL_ARB_ES3_compatibility means OpenGL is a superset of GLES 3.0
688    if ((major > 3) || ((major == 3) && (minor >= 3)))
689      {
690         const char *exts = NULL;
691         int num = 0;
692 
693         if (_has_ext("GL_ARB_ES3_compatibility", &exts, &num))
694           return 3;
695      }
696 
697    // OpenGL >= 1.4 is a superset of the features of GLES 2 (albeit not an
698    // exact function match)
699    if (((major == 1) && (minor >= 4)) || (major >= 2))
700      return 2; /* emulated support */
701 
702    return 0;
703 }
704 
705 static void
_evas_gl_common_viewport_set(Evas_Engine_GL_Context * gc)706 _evas_gl_common_viewport_set(Evas_Engine_GL_Context *gc)
707 {
708    int w = 1, h = 1, m = 1, rot = 1, foc = 0;
709    int offx = 0, offy = 0;
710    Evas_GL_Program *prog;
711    Eina_Iterator *it;
712 
713    EINA_SAFETY_ON_NULL_RETURN(gc);
714    foc = gc->foc;
715    // surface in pipe 0 will be the same as all pipes
716    if ((gc->pipe[0].shader.surface == gc->def_surface) ||
717        (!gc->pipe[0].shader.surface))
718      {
719         w = gc->w;
720         h = gc->h;
721         rot = gc->rot;
722      }
723    else
724      {
725         w = gc->pipe[0].shader.surface->w;
726         h = gc->pipe[0].shader.surface->h;
727         rot = 0;
728         m = -1;
729         offx = gc->pipe[0].shader.surface->tex->x;
730         offy = gc->pipe[0].shader.surface->tex->y;
731      }
732 
733 #ifdef GL_GLES
734    if (gc->shared->eglctxt == gc->eglctxt)
735 #endif
736      {
737         if (((offx == gc->shared->offx) && (offy == gc->shared->offy)) &&
738             ((!gc->change.size) ||
739              (
740                 (gc->shared->w == w) && (gc->shared->h == h) &&
741                 (gc->shared->rot == rot) && (gc->shared->foc == gc->foc) &&
742                 (gc->shared->mflip == m)
743              )
744             )
745            )
746           return;
747      }
748 #ifdef GL_GLES
749    gc->shared->eglctxt = gc->eglctxt;
750 #endif
751 
752    gc->shared->w = w;
753    gc->shared->h = h;
754    gc->shared->rot = rot;
755    gc->shared->mflip = m;
756    gc->shared->foc = foc;
757    gc->shared->z0 = gc->z0;
758    gc->shared->px = gc->px;
759    gc->shared->py = gc->py;
760    gc->change.size = 0;
761    gc->shared->offx = offx;
762    gc->shared->offy = offy;
763 
764    if (foc == 0)
765      {
766         if ((rot == 0) || (rot == 180))
767            glViewport(offx, offy, w, h);
768         else
769            glViewport(offx, offy, h, w);
770         // std matrix
771         if (m == 1)
772            matrix_ortho(gc->shared->proj,
773                         0, w, 0, h,
774                         -1000000.0, 1000000.0,
775                         rot, w, h,
776                         1, 1.0);
777         // v flipped matrix for render-to-texture
778         else
779            matrix_ortho(gc->shared->proj,
780                         0, w, h, 0,
781                         -1000000.0, 1000000.0,
782                         rot, w, h,
783                         1, 1.0);
784      }
785    else
786      {
787         int px, py, vx, vy, vw = 0, vh = 0, ax = 0, ay = 0, ppx = 0, ppy = 0;
788 
789         px = gc->shared->px;
790         py = gc->shared->py;
791 
792         if      ((rot == 0  ) || (rot == 90 )) ppx = px;
793         else if ((rot == 180) || (rot == 270)) ppx = w - px;
794         if      ((rot == 0  ) || (rot == 270)) ppy = py;
795         else if ((rot == 90 ) || (rot == 180)) ppy = h - py;
796 
797         vx = ((w / 2) - ppx);
798         if (vx >= 0)
799           {
800              vw = w + (2 * vx);
801              if      ((rot == 0  ) || (rot == 90 )) ax = 2 * vx;
802              else if ((rot == 180) || (rot == 270)) ax = 0;
803           }
804         else
805           {
806              vw = w - (2 * vx);
807              if      ((rot == 0  ) || (rot == 90 )) ax = 0;
808              else if ((rot == 180) || (rot == 270)) ax = ppx - px;
809              vx = 0;
810           }
811 
812         vy = ((h / 2) - ppy);
813         if (vy < 0)
814           {
815              vh = h - (2 * vy);
816              if      (rot == 0) ay = 0;
817              else if ((rot == 90 ) || (rot == 180) || (rot == 270)) ay = ppy - py;
818              vy = -vy;
819           }
820         else
821           {
822              vh = h + (2 * vy);
823              if      ((rot == 0  ) || (rot == 270)) ay = 2 * vy;
824              else if ((rot == 90 ) || (rot == 180)) ay = 0;
825              vy = 0;
826           }
827 
828         if (m == -1) ay = vy * 2;
829 
830         if ((rot == 0) || (rot == 180))
831            glViewport(offx + (-2 * vx), offy + (-2 * vy), vw, vh);
832         else
833            glViewport(offx + (-2 * vy), offy + (-2 * vx), vh, vw);
834         if (m == 1)
835            matrix_ortho(gc->shared->proj,
836                         0, vw, 0, vh,
837                         -1000000.0, 1000000.0,
838                         rot, vw, vh,
839                         foc, 0.0);
840         else
841            matrix_ortho(gc->shared->proj,
842                         0, vw, vh, 0,
843                         -1000000.0, 1000000.0,
844                         rot, vw, vh,
845                         foc, 0.0);
846         gc->shared->ax = ax;
847         gc->shared->ay = ay;
848      }
849 
850    // FIXME: Is this heavy work?
851    it = eina_hash_iterator_data_new(gc->shared->shaders_hash);
852    EINA_ITERATOR_FOREACH(it, prog)
853      prog->reset = EINA_TRUE;
854    eina_iterator_free(it);
855 
856    if (gc->state.current.prog != PRG_INVALID)
857      {
858         prog = gc->state.current.prog;
859         glUseProgram(prog->prog);
860         glUniform1i(prog->uniform.rotation_id, gc->rot / 90);
861         glUniformMatrix4fv(prog->uniform.mvp, 1, GL_FALSE, gc->shared->proj);
862      }
863 }
864 
865 EAPI Evas_Engine_GL_Context *
evas_gl_common_context_new(void)866 evas_gl_common_context_new(void)
867 {
868    Evas_Engine_GL_Context *gc;
869    const char *s;
870    int i, gles_version;
871 
872 #if 1
873    if (_evas_gl_common_context)
874      {
875         _evas_gl_common_context->references++;
876         return _evas_gl_common_context;
877      }
878 #endif
879 
880    if (!glsym_glGetStringi)
881      glsym_glGetStringi = dlsym(RTLD_DEFAULT, "glGetStringi");
882 
883    gles_version = evas_gl_common_version_check(NULL);
884    if (!gles_version) return NULL;
885 
886    gc = calloc(1, sizeof(Evas_Engine_GL_Context));
887    if (!gc) return NULL;
888 
889    tbm_symbols();
890    gc->gles_version = gles_version;
891 
892    gc->references = 1;
893 
894    _evas_gl_common_context = gc;
895 
896    for (i = 0; i < MAX_PIPES; i++)
897      {
898         gc->pipe[i].shader.render_op = EVAS_RENDER_BLEND;
899         if (glsym_glMapBuffer && glsym_glUnmapBuffer)
900           {
901              glGenBuffers(1, &gc->pipe[i].array.buffer);
902              gc->pipe[i].array.buffer_alloc = 0;
903              gc->pipe[i].array.buffer_use = 0;
904           }
905      }
906 
907    gc->state.current.tex_target = GL_TEXTURE_2D;
908 
909    if (!shared)
910      {
911         const char *ext;
912 
913         shared = calloc(1, sizeof(Evas_GL_Shared));
914         ext = (const char *) glGetString(GL_EXTENSIONS);
915         if (ext)
916           {
917              if (getenv("EVAS_GL_INFO"))
918                 fprintf(stderr, "EXT:\n%s\n", ext);
919              if ((_ckext(ext, "GL_ARB_texture_non_power_of_two")) ||
920                  (_ckext(ext, "OES_texture_npot")) ||
921                  (_ckext(ext, "GL_IMG_texture_npot")))
922                shared->info.tex_npo2 = 1;
923              if ((_ckext(ext, "GL_NV_texture_rectangle")) ||
924                  (_ckext(ext, "GL_EXT_texture_rectangle")) ||
925                  (_ckext(ext, "GL_ARB_texture_rectangle")))
926                shared->info.tex_rect = 1;
927              if ((_ckext(ext, "GL_ARB_get_program_binary")) ||
928                  (_ckext(ext, "GL_OES_get_program_binary")))
929                shared->info.bin_program = 1;
930              else
931                glsym_glGetProgramBinary = NULL;
932 #ifdef GL_UNPACK_ROW_LENGTH
933              shared->info.unpack_row_length = 1;
934 # ifdef GL_GLES
935              if (!_ckext(ext, "_unpack_subimage"))
936                shared->info.unpack_row_length = 0;
937 # endif
938 #endif
939 
940 #ifdef GL_TEXTURE_MAX_ANISOTROPY_EXT
941              if ((_ckext(ext, "GL_EXT_texture_filter_anisotropic")))
942                glGetFloatv(GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT,
943                            &(shared->info.anisotropic));
944 #endif
945 #ifdef GL_BGRA
946              if ((_ckext(ext, "GL_EXT_bgra")) ||
947                  (_ckext(ext, "GL_EXT_texture_format_BGRA8888")))
948                shared->info.bgra = 1;
949 #endif
950              if (_ckext(ext, "OES_compressed_ETC1_RGB8_texture"))
951                shared->info.etc1 = 1;
952              if (_ckext(ext, "GL_EXT_texture_compression_s3tc") ||
953                  _ckext(ext, "GL_S3_s3tc"))
954                shared->info.s3tc = 1;
955 #ifdef GL_GLES
956              // FIXME: there should be an extension name/string to check for
957              // not just symbols in the lib
958              i = 0;
959              s = getenv("EVAS_GL_NO_MAP_IMAGE_SEC");
960              if (s) i = atoi(s);
961              if (!i)
962                {
963                   // test for all needed symbols - be "conservative" and
964                   // need all of it
965                   if ((eglsym_eglDestroyImage) &&
966                       (secsym_glEGLImageTargetTexture2DOES) &&
967                       (secsym_eglMapImageSEC) &&
968                       (secsym_eglUnmapImageSEC) &&
969                       (secsym_eglGetImageAttribSEC))
970                      shared->info.sec_image_map = 1;
971                }
972              i = 0;
973 
974              if ((secsym_tbm_surface_create) &&
975                   (secsym_tbm_surface_destroy) &&
976                   (secsym_tbm_surface_map) &&
977                   (secsym_tbm_surface_unmap) &&
978                   (secsym_tbm_surface_get_info))
979                   shared->info.sec_tbm_surface = 1;
980 #endif
981              if (!_ckext(ext, "GL_QCOM_tiled_rendering"))
982                {
983                   glsym_glStartTiling = NULL;
984                   glsym_glEndTiling = NULL;
985                }
986           }
987         glGetIntegerv(GL_MAX_TEXTURE_IMAGE_UNITS,
988                       &(shared->info.max_texture_units));
989         glGetIntegerv(GL_MAX_TEXTURE_SIZE,
990                       &(shared->info.max_texture_size));
991         shared->info.max_vertex_elements = 6 * 100;
992 #ifdef GL_MAX_ELEMENTS_VERTICES
993 /* only applies to glDrawRangeElements. don't really need to get it.
994         glGetIntegerv(GL_MAX_ELEMENTS_VERTICES,
995                       &(shared->info.max_vertex_elements));
996  */
997 #endif
998         s = getenv("EVAS_GL_VERTEX_MAX");
999         if (s) shared->info.max_vertex_elements = atoi(s);
1000         if (shared->info.max_vertex_elements < 6)
1001            shared->info.max_vertex_elements = 6;
1002 
1003         // magic numbers that are a result of imperical testing and getting
1004         // "best case" performance across a range of systems
1005         shared->info.tune.cutout.max                 = DEF_CUTOUT;
1006         shared->info.tune.pipes.max                  = DEF_PIPES;
1007         shared->info.tune.atlas.max_alloc_size       = DEF_ATLAS_ALLOC;
1008         shared->info.tune.atlas.max_alloc_alpha_size = DEF_ATLAS_ALLOC_ALPHA;
1009         shared->info.tune.atlas.max_w                = DEF_ATLAS_W;
1010         shared->info.tune.atlas.max_h                = DEF_ATLAS_H;
1011 
1012         // per gpu hacks. based on impirical measurement of some known gpu's
1013         s = (const char *)glGetString(GL_RENDERER);
1014         if (s)
1015           {
1016              if (strstr(s, "PowerVR SGX 540"))
1017                shared->info.tune.pipes.max = DEF_PIPES_SGX_540;
1018              else if (strstr(s, "NVIDIA Tegra 3"))
1019                shared->info.tune.pipes.max = DEF_PIPES_TEGRA_3;
1020              else if (strstr(s, "NVIDIA Tegra"))
1021                shared->info.tune.pipes.max = DEF_PIPES_TEGRA_2;
1022           }
1023         if (!getenv("EVAS_GL_MAPBUFFER"))
1024           {
1025              glsym_glMapBuffer = NULL;
1026              glsym_glUnmapBuffer= NULL;
1027           }
1028 
1029 #define GETENVOPT(name, tune_param, min, max) \
1030         do { \
1031            const char *__v = getenv(name); \
1032            if (__v) { \
1033               shared->info.tune.tune_param = atoi(__v); \
1034               if (shared->info.tune.tune_param > max) \
1035                  shared->info.tune.tune_param = max; \
1036               else if (shared->info.tune.tune_param < min) \
1037                  shared->info.tune.tune_param = min; \
1038            } \
1039         } while (0)
1040 
1041         GETENVOPT("EVAS_GL_CUTOUT_MAX", cutout.max, -1, 0x7fffffff);
1042         GETENVOPT("EVAS_GL_PIPES_MAX", pipes.max, 1, MAX_PIPES);
1043         GETENVOPT("EVAS_GL_ATLAS_ALLOC_SIZE", atlas.max_alloc_size, MIN_ATLAS_ALLOC, MAX_ATLAS_ALLOC);
1044         GETENVOPT("EVAS_GL_ATLAS_ALLOC_ALPHA_SIZE", atlas.max_alloc_alpha_size, MIN_ATLAS_ALLOC_ALPHA, MAX_ATLAS_ALLOC_ALPHA);
1045         GETENVOPT("EVAS_GL_ATLAS_MAX_W", atlas.max_w, 0, MAX_ATLAS_W);
1046         GETENVOPT("EVAS_GL_ATLAS_MAX_H", atlas.max_h, 0, MAX_ATLAS_H);
1047         s = (const char *)getenv("EVAS_GL_GET_PROGRAM_BINARY");
1048         if (s)
1049           {
1050              if (atoi(s) == 0) shared->info.bin_program = 0;
1051           }
1052 
1053 #ifdef GL_GLES
1054         // Detect ECT2 support. We need both RGB and RGBA formats.
1055           {
1056              GLint texFormatCnt = 0;
1057              glGetIntegerv(GL_NUM_COMPRESSED_TEXTURE_FORMATS, &texFormatCnt);
1058              if (texFormatCnt > 0)
1059                {
1060                   GLenum *texFormats = malloc(texFormatCnt * sizeof(GLenum));
1061                   if (texFormats)
1062                     {
1063                        int k, cnt = 0;
1064                        glGetIntegerv(GL_COMPRESSED_TEXTURE_FORMATS, (GLint *) texFormats);
1065                        for (k = 0; k < texFormatCnt && cnt < 2; k++)
1066                          {
1067                             if (texFormats[k] == GL_COMPRESSED_RGB8_ETC2)
1068                               cnt++;
1069                             else if (texFormats[k] == GL_COMPRESSED_RGBA8_ETC2_EAC)
1070                               cnt++;
1071                          }
1072                        shared->info.etc2 = (cnt == 2);
1073                        free(texFormats);
1074 
1075                        // Note: If we support ETC2 we'll try to always use ETC2 even when the
1076                        // image has colorspace ETC1 (backwards compatibility).
1077 
1078                        if (_ckext(ext, "GL_EXT_compressed_ETC1_RGB8_sub_texture"))
1079                          shared->info.etc1_subimage = 1;
1080                        else
1081                          shared->info.etc1_subimage = shared->info.etc2;
1082 
1083                        // FIXME: My NVIDIA driver advertises ETC2 texture formats
1084                        // but does not support them. Driver bug? Logic bug?
1085                        // This is in #ifdef GL_GLES because Khronos recommends
1086                        // use of GL_COMPRESSED_TEXTURE_FORMATS but OpenGL 4.x
1087                        // does not.
1088                     }
1089                }
1090           }
1091 #endif
1092 
1093         if (getenv("EVAS_GL_INFO"))
1094            fprintf(stderr,
1095                    "max tex size %ix%i\n"
1096                    "max units %i\n"
1097                    "non-power-2 tex %i\n"
1098                    "rect tex %i\n"
1099                    "bgra : %i\n"
1100                    "etc1 : %i\n"
1101                    "etc2 : %i%s\n"
1102                    "s3tc : %i\n"
1103                    "max ansiotropic filtering: %3.3f\n"
1104                    "egl sec map image: %i\n"
1105                    "max vertex count: %i\n"
1106                    "\n"
1107                    "(can set EVAS_GL_VERTEX_MAX  EVAS_GL_NO_MAP_IMAGE_SEC  EVAS_GL_INFO  EVAS_GL_MEMINFO )\n"
1108                    "\n"
1109                    "EVAS_GL_GET_PROGRAM_BINARY: %i\n"
1110                    "EVAS_GL_CUTOUT_MAX: %i\n"
1111                    "EVAS_GL_PIPES_MAX: %i\n"
1112                    "EVAS_GL_ATLAS_ALLOC_SIZE: %i\n"
1113                    "EVAS_GL_ATLAS_ALLOC_ALPHA_SIZE: %i\n"
1114                    "EVAS_GL_ATLAS_MAX_W x EVAS_GL_ATLAS_MAX_H: %i x %i\n"
1115                    ,
1116                    (int)shared->info.max_texture_size, (int)shared->info.max_texture_size,
1117                    (int)shared->info.max_texture_units,
1118                    (int)shared->info.tex_npo2,
1119                    (int)shared->info.tex_rect,
1120                    (int)shared->info.bgra,
1121                    (int)shared->info.etc1,
1122                    (int)shared->info.etc2, shared->info.etc2 ? " (GL_COMPRESSED_RGB8_ETC2, GL_COMPRESSED_RGBA8_ETC2_EAC)" : "",
1123                    (int)shared->info.s3tc,
1124                    (double)shared->info.anisotropic,
1125                    (int)shared->info.sec_image_map,
1126                    (int)shared->info.max_vertex_elements,
1127 
1128                    (int)shared->info.bin_program,
1129                    (int)shared->info.tune.cutout.max,
1130                    (int)shared->info.tune.pipes.max,
1131                    (int)shared->info.tune.atlas.max_alloc_size,
1132                    (int)shared->info.tune.atlas.max_alloc_alpha_size,
1133                    (int)shared->info.tune.atlas.max_w, (int)shared->info.tune.atlas.max_h
1134                   );
1135 
1136         glDisable(GL_DEPTH_TEST);
1137         glEnable(GL_DITHER);
1138         glDisable(GL_BLEND);
1139         glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
1140         // no dest alpha
1141 //        glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); // dest alpha
1142 //        glBlendFunc(GL_SRC_ALPHA, GL_ONE); // ???
1143         glDepthMask(GL_FALSE);
1144 
1145         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
1146         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
1147         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
1148         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
1149 #ifdef GL_TEXTURE_MAX_ANISOTROPY_EXT
1150         if (shared->info.anisotropic > 0.0)
1151           glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, 1.0);
1152 #endif
1153 
1154         glEnableVertexAttribArray(SHAD_VERTEX);
1155         glEnableVertexAttribArray(SHAD_COLOR);
1156 
1157         if (!evas_gl_common_shader_program_init(shared))
1158           goto error;
1159 
1160         if (gc->state.current.prog)
1161           glUseProgram(gc->state.current.prog->prog);
1162 
1163         // in shader:
1164         // uniform sampler2D tex[8];
1165         //
1166         // in code:
1167         // GLuint texes[8];
1168         // GLint loc = glGetUniformLocation(prog, "tex");
1169         // glUniform1iv(loc, 8, texes);
1170 
1171         shared->native_pm_hash  = eina_hash_int32_new(NULL);
1172         shared->native_tex_hash = eina_hash_int32_new(NULL);
1173         shared->native_wl_hash = eina_hash_pointer_new(NULL);
1174         shared->native_tbm_hash = eina_hash_pointer_new(NULL);
1175         shared->native_evasgl_hash = eina_hash_pointer_new(NULL);
1176      }
1177    gc->shared = shared;
1178    gc->shared->references++;
1179    _evas_gl_common_viewport_set(gc);
1180 
1181    gc->def_surface = evas_gl_common_image_surface_new(gc, 1, 1, 1, EINA_FALSE);
1182 
1183    return gc;
1184 
1185 error:
1186    evas_gl_common_context_free(gc);
1187    return NULL;
1188 }
1189 
1190 #define VERTEX_CNT 3
1191 #define COLOR_CNT  4
1192 #define TEX_CNT    2
1193 #define SAM_CNT    2
1194 #define MASK_CNT   4
1195 
1196 #define PUSH_VERTEX(n, x, y, z) do { \
1197    gc->pipe[n].array.vertex[nv++] = x; \
1198    gc->pipe[n].array.vertex[nv++] = y; \
1199    gc->pipe[n].array.vertex[nv++] = z; } while(0)
1200 #define PUSH_COLOR(n, r, g, b, a) do { \
1201    gc->pipe[n].array.color[nc++] = r; \
1202    gc->pipe[n].array.color[nc++] = g; \
1203    gc->pipe[n].array.color[nc++] = b; \
1204    gc->pipe[n].array.color[nc++] = a; } while(0)
1205 #define PUSH_TEXUV(n, u, v) do { \
1206    gc->pipe[n].array.texuv[nu++] = u; \
1207    gc->pipe[n].array.texuv[nu++] = v; } while(0)
1208 #define PUSH_TEXUV2(n, u, v) do { \
1209    gc->pipe[n].array.texuv2[nu2++] = u; \
1210    gc->pipe[n].array.texuv2[nu2++] = v; } while(0)
1211 #define PUSH_TEXUV3(n, u, v) do { \
1212    gc->pipe[n].array.texuv3[nu3++] = u; \
1213    gc->pipe[n].array.texuv3[nu3++] = v; } while(0)
1214 #define PUSH_TEXA(n, u, v) do { \
1215    gc->pipe[n].array.texa[na++] = u; \
1216    gc->pipe[n].array.texa[na++] = v; } while(0)
1217 #define PUSH_TEXM(n, u, v, w, z) do { \
1218    gc->pipe[n].array.mask[nm++] = u; \
1219    gc->pipe[n].array.mask[nm++] = v; \
1220    gc->pipe[n].array.mask[nm++] = w; \
1221    gc->pipe[n].array.mask[nm++] = z; } while(0)
1222 #define PUSH_TEXSAM(n, x, y) do { \
1223    gc->pipe[n].array.texsam[ns++] = x; \
1224    gc->pipe[n].array.texsam[ns++] = y; } while(0)
1225 
1226 #define PUSH_6_VERTICES(pn, x, y, w, h) do { \
1227    PUSH_VERTEX(pn, x    , y    , 0); PUSH_VERTEX(pn, x + w, y    , 0); \
1228    PUSH_VERTEX(pn, x    , y + h, 0); PUSH_VERTEX(pn, x + w, y    , 0); \
1229    PUSH_VERTEX(pn, x + w, y + h, 0); PUSH_VERTEX(pn, x    , y + h, 0); \
1230    } while (0)
1231 #define PUSH_6_QUAD(pn, x1, y1, x2, y2, x3, y3, x4, y4)                 \
1232   PUSH_TEXUV(pn, x1, y1); PUSH_TEXUV(pn, x2, y2); PUSH_TEXUV(pn, x4, y4);\
1233   PUSH_TEXUV(pn, x2, y2); PUSH_TEXUV(pn, x3, y3); PUSH_TEXUV(pn, x4, y4);
1234 
1235 #define PUSH_6_TEXUV(pn, x1, y1, x2, y2)                \
1236   PUSH_6_QUAD(pn, x1, y1, x2, y1, x2, y2, x1, y2);
1237 
1238 #define PUSH_6_TEXUV2(pn, x1, y1, x2, y2) do { \
1239    PUSH_TEXUV2(pn, x1, y1); PUSH_TEXUV2(pn, x2, y1); PUSH_TEXUV2(pn, x1, y2); \
1240    PUSH_TEXUV2(pn, x2, y1); PUSH_TEXUV2(pn, x2, y2); PUSH_TEXUV2(pn, x1, y2); \
1241    } while (0)
1242 #define PUSH_6_TEXUV3(pn, x1, y1, x2, y2) do { \
1243    PUSH_TEXUV3(pn, x1, y1); PUSH_TEXUV3(pn, x2, y1); PUSH_TEXUV3(pn, x1, y2); \
1244    PUSH_TEXUV3(pn, x2, y1); PUSH_TEXUV3(pn, x2, y2); PUSH_TEXUV3(pn, x1, y2); \
1245    } while (0)
1246 #define PUSH_6_TEXA(pn, x1, y1, x2, y2) do { \
1247    PUSH_TEXA(pn, x1, y1); PUSH_TEXA(pn, x2, y1); PUSH_TEXA(pn, x1, y2); \
1248    PUSH_TEXA(pn, x2, y1); PUSH_TEXA(pn, x2, y2); PUSH_TEXA(pn, x1, y2); \
1249    } while (0)
1250 #define PUSH_SAMPLES(pn, dx, dy) do { \
1251    PUSH_TEXSAM(pn, dx, dy); PUSH_TEXSAM(pn, dx, dy); PUSH_TEXSAM(pn, dx, dy); \
1252    PUSH_TEXSAM(pn, dx, dy); PUSH_TEXSAM(pn, dx, dy); PUSH_TEXSAM(pn, dx, dy); \
1253    } while (0)
1254 #define PUSH_MASKSAM(pn, x, y, cnt) do { int _i; for (_i = 0; _i < cnt; _i++) { \
1255    gc->pipe[pn].array.masksam[nms++] = x; gc->pipe[pn].array.masksam[nms++] = y; \
1256    } } while (0)
1257 #define PUSH_6_COLORS(pn, r, g, b, a) \
1258    do { int i; for (i = 0; i < 6; i++) PUSH_COLOR(pn, r, g, b, a); } while(0)
1259 
1260 #define PIPE_GROW(gc, pn, inc) \
1261    int nv = gc->pipe[pn].array.num * VERTEX_CNT; (void) nv; \
1262    int nc = gc->pipe[pn].array.num * COLOR_CNT; (void) nc; \
1263    int nu = gc->pipe[pn].array.num * TEX_CNT; (void) nu; \
1264    int nu2 = gc->pipe[pn].array.num * TEX_CNT; (void) nu2; \
1265    int nu3 = gc->pipe[pn].array.num * TEX_CNT; (void) nu3; \
1266    int na = gc->pipe[pn].array.num * TEX_CNT; (void) na; \
1267    int ns = gc->pipe[pn].array.num * SAM_CNT; (void) ns; \
1268    int nm = gc->pipe[pn].array.num * MASK_CNT; (void) nm; \
1269    int nms = gc->pipe[pn].array.num * SAM_CNT; (void) nms; \
1270    gc->pipe[pn].array.num += inc; \
1271    array_alloc(gc, pn);
1272 
1273 #define PIPE_FREE(x) \
1274    do { _pipebuf_free(x); (x) = NULL; } while (0)
1275 
1276 #define FREE(x) \
1277    do { free(x); (x) = NULL; } while (0)
1278 
1279 typedef struct _Pipebuf
1280 {
1281    int skipped, alloc;
1282 } Pipebuf;
1283 
1284 static int        _pipe_bufs_max = 0;
1285 static int        _pipe_bufs_skipped = 0;
1286 static Eina_List *_pipe_bufs = NULL;
1287 
1288 /*
1289 static int _used = 0, _alloced = 0, _realloced = 0;
1290 static int _searches = 0, _looks = 0;
1291 */
1292 
1293 static void *
_pipebuf_resize(void * pb,int size)1294 _pipebuf_resize(void *pb, int size)
1295 {
1296    Pipebuf *buf, *buf2;
1297    Eina_List *l, *ll;
1298 
1299    if (size > _pipe_bufs_max) _pipe_bufs_max = size;
1300 
1301    if (!pb)
1302      {
1303         if (_pipe_bufs)
1304           {
1305 //             _searches++;
1306              EINA_LIST_FOREACH(_pipe_bufs, l, buf)
1307                {
1308 //                  _looks++;
1309                   if (buf->alloc >= size) break;
1310                   buf->skipped++;
1311                   _pipe_bufs_skipped++;
1312                }
1313              if (l)
1314                {
1315 //                  _used++;
1316                   _pipe_bufs = eina_list_remove_list(_pipe_bufs, l);
1317                   _pipe_bufs_skipped -= buf->skipped;
1318                   buf->skipped = 0;
1319                   goto done;
1320                }
1321           }
1322         buf = malloc(size + sizeof(Pipebuf));
1323         if (!buf) return NULL;
1324         buf->skipped = 0;
1325         buf->alloc = size;
1326 //        _alloced++;
1327         goto done;
1328      }
1329    buf = (Pipebuf *)(((unsigned char *)pb) - sizeof(Pipebuf));
1330    if (buf->alloc < size)
1331      {
1332         buf2 = realloc(buf, size + sizeof(Pipebuf));
1333         if (!buf2) return NULL;
1334 //        _realloced++;
1335         buf = buf2;
1336         buf->alloc = size;
1337      }
1338 done:
1339    if (_pipe_bufs_skipped > 100)
1340      {
1341         EINA_LIST_REVERSE_FOREACH_SAFE(_pipe_bufs, l, ll, buf2)
1342           {
1343              if (buf2->skipped > 5)
1344                {
1345                   _pipe_bufs = eina_list_remove_list(_pipe_bufs, l);
1346                   _pipe_bufs_skipped -= buf2->skipped;
1347                   free(buf2);
1348                   if (_pipe_bufs_skipped == 0) break;
1349                }
1350           }
1351      }
1352 //   if ((_used + _alloced + _realloced) % 1000 == 0)
1353 //     printf("MAX=%i/%i skipped=%i searching=%i/%i    -   %i | %i | %i\n",
1354 //            _pipe_bufs_max, eina_list_count(_pipe_bufs), _pipe_bufs_skipped,
1355 //            _looks, _searches,
1356 //            _used, _alloced, _realloced);
1357    return ((unsigned char *)buf) +  sizeof(Pipebuf);
1358 }
1359 
1360 static void
_pipebuf_free(void * pb)1361 _pipebuf_free(void *pb)
1362 {
1363    Pipebuf *buf;
1364 
1365    if (!pb) return;
1366    buf = (Pipebuf *)(((unsigned char *)pb) - sizeof(Pipebuf));
1367    _pipe_bufs_max = (_pipe_bufs_max * 19) / 20;
1368    if (buf->alloc > (_pipe_bufs_max * 4))
1369      {
1370         free(buf);
1371         return;
1372      }
1373    if ((!_pipe_bufs) || (eina_list_count(_pipe_bufs) < 20))
1374      {
1375         _pipe_bufs = eina_list_prepend(_pipe_bufs, buf);
1376         return;
1377      }
1378    free(buf);
1379 }
1380 
1381 static void
_pipebuf_clear(void)1382 _pipebuf_clear(void)
1383 {
1384    Pipebuf *buf;
1385 
1386    _pipe_bufs_max = 0;
1387    EINA_LIST_FREE(_pipe_bufs, buf)
1388      {
1389         free(buf);
1390      }
1391 }
1392 
1393 static void
array_alloc(Evas_Engine_GL_Context * gc,int n)1394 array_alloc(Evas_Engine_GL_Context *gc, int n)
1395 {
1396    gc->havestuff = EINA_TRUE;
1397    if (gc->pipe[n].array.num <= gc->pipe[n].array.alloc) return;
1398 
1399    gc->pipe[n].array.alloc += 6 * 256;
1400 
1401 #define RALOC(field, type, size) \
1402    if (gc->pipe[n].array.use_##field) \
1403       gc->pipe[n].array.field = _pipebuf_resize(gc->pipe[n].array.field, \
1404                                                 gc->pipe[n].array.alloc * sizeof(type) * size)
1405 
1406    RALOC(vertex, GLfloat, VERTEX_CNT);
1407    RALOC(color,  GLubyte, COLOR_CNT);
1408    RALOC(texuv,  GLfloat, TEX_CNT);
1409    RALOC(texa,   GLfloat, TEX_CNT);
1410    RALOC(texuv2, GLfloat, TEX_CNT);
1411    RALOC(texuv3, GLfloat, TEX_CNT);
1412    RALOC(texsam, GLfloat, SAM_CNT);
1413    RALOC(mask,   GLfloat, MASK_CNT);
1414    RALOC(masksam, GLfloat, SAM_CNT);
1415 
1416 #undef ALOC
1417 #undef RALOC
1418 }
1419 
1420 EAPI void
evas_gl_common_context_free(Evas_Engine_GL_Context * gc)1421 evas_gl_common_context_free(Evas_Engine_GL_Context *gc)
1422 {
1423    int i, j;
1424    Eina_List *l;
1425 
1426    gc->references--;
1427    if (gc->references > 0) return;
1428    if (gc->shared) gc->shared->references--;
1429 
1430    if (gc->def_surface) evas_gl_common_image_free(gc->def_surface);
1431 
1432    if (gc->font_surface)
1433      evas_cache_image_drop(&gc->font_surface->cache_entry);
1434 
1435    if (glsym_glMapBuffer && glsym_glUnmapBuffer)
1436      {
1437         for (i = 0; i < MAX_PIPES; i++)
1438           glDeleteBuffers(1, &gc->pipe[i].array.buffer);
1439      }
1440 
1441    if (gc->shared)
1442      {
1443         for (i = 0; i < gc->shared->info.tune.pipes.max; i++)
1444           {
1445              PIPE_FREE(gc->pipe[i].array.vertex);
1446              PIPE_FREE(gc->pipe[i].array.color);
1447              PIPE_FREE(gc->pipe[i].array.texuv);
1448              PIPE_FREE(gc->pipe[i].array.texuv2);
1449              PIPE_FREE(gc->pipe[i].array.texuv3);
1450              PIPE_FREE(gc->pipe[i].array.texa);
1451              PIPE_FREE(gc->pipe[i].array.texsam);
1452              PIPE_FREE(gc->pipe[i].array.mask);
1453              PIPE_FREE(gc->pipe[i].array.masksam);
1454              FREE(gc->pipe[i].array.filter_data);
1455           }
1456      }
1457 
1458    while (gc->font_glyph_textures)
1459      evas_gl_common_texture_free(gc->font_glyph_textures->data, EINA_TRUE);
1460 
1461    while (gc->font_glyph_images)
1462      evas_gl_common_image_free(gc->font_glyph_images->data);
1463 
1464    if ((gc->shared) && (gc->shared->references == 0))
1465      {
1466         Evas_GL_Texture_Pool *pt;
1467 
1468         evas_gl_common_shader_program_shutdown(gc->shared);
1469 
1470         while (gc->shared->images)
1471           {
1472              evas_gl_common_image_free(gc->shared->images->data);
1473           }
1474 
1475         for (j = 0; j < ATLAS_FORMATS_COUNT; j++)
1476           {
1477               EINA_LIST_FOREACH(gc->shared->tex.atlas[j], l, pt)
1478                  evas_gl_texture_pool_empty(pt);
1479               eina_list_free(gc->shared->tex.atlas[j]);
1480           }
1481         EINA_LIST_FOREACH(gc->shared->tex.whole, l, pt)
1482            evas_gl_texture_pool_empty(pt);
1483         eina_list_free(gc->shared->info.cspaces);
1484         eina_list_free(gc->shared->tex.whole);
1485         eina_hash_free(gc->shared->native_pm_hash);
1486         eina_hash_free(gc->shared->native_tex_hash);
1487         eina_hash_free(gc->shared->native_wl_hash);
1488         eina_hash_free(gc->shared->native_tbm_hash);
1489         eina_hash_free(gc->shared->native_evasgl_hash);
1490         eina_stringshare_del(gc->shared->shaders_checksum);
1491         free(gc->shared);
1492         shared = NULL;
1493      }
1494    if (gc == _evas_gl_common_context)
1495      {
1496         _pipebuf_clear();
1497         _evas_gl_common_context = NULL;
1498      }
1499    free(gc);
1500    if (_evas_gl_common_cutout_rects)
1501      {
1502         evas_common_draw_context_apply_clear_cutouts(_evas_gl_common_cutout_rects);
1503         _evas_gl_common_cutout_rects = NULL;
1504      }
1505 }
1506 
1507 EAPI void
evas_gl_common_context_use(Evas_Engine_GL_Context * gc)1508 evas_gl_common_context_use(Evas_Engine_GL_Context *gc)
1509 {
1510    if (_evas_gl_common_context == gc) return;
1511    _evas_gl_common_context = gc;
1512    if (gc) _evas_gl_common_viewport_set(gc);
1513 }
1514 
1515 EAPI void
evas_gl_common_context_newframe(Evas_Engine_GL_Context * gc)1516 evas_gl_common_context_newframe(Evas_Engine_GL_Context *gc)
1517 {
1518    int i;
1519 
1520    if (_evas_gl_common_cutout_rects)
1521      {
1522         evas_common_draw_context_apply_clear_cutouts(_evas_gl_common_cutout_rects);
1523         _evas_gl_common_cutout_rects = NULL;
1524      }
1525    if (dbgflushnum < 0)
1526      {
1527         dbgflushnum = 0;
1528         if (getenv("EVAS_GL_DBG")) dbgflushnum = 1;
1529      }
1530    if (dbgflushnum) printf("----prev-flushnum: %i -----------------------------------\n", gc->flushnum);
1531 //   fprintf(stderr, "------------------------\n");
1532 
1533    gc->flushnum = 0;
1534    gc->state.current.prog = NULL;
1535    gc->state.current.cur_tex = 0;
1536    gc->state.current.cur_texu = 0;
1537    gc->state.current.cur_texv = 0;
1538    gc->state.current.cur_texa = 0;
1539    gc->state.current.cur_texm = 0;
1540    gc->state.current.tex_target = GL_TEXTURE_2D;
1541    gc->state.current.render_op = EVAS_RENDER_COPY;
1542    gc->state.current.smooth = 0;
1543    gc->state.current.blend = 0;
1544    gc->state.current.clip = 0;
1545    gc->state.current.cx = 0;
1546    gc->state.current.cy = 0;
1547    gc->state.current.cw = 0;
1548    gc->state.current.ch = 0;
1549 
1550    for (i = 0; i < gc->shared->info.tune.pipes.max; i++)
1551      {
1552         gc->pipe[i].region.x = 0;
1553         gc->pipe[i].region.y = 0;
1554         gc->pipe[i].region.w = 0;
1555         gc->pipe[i].region.h = 0;
1556         gc->pipe[i].region.type = 0;
1557         //gc->pipe[i].shader.surface = NULL;
1558         gc->pipe[i].shader.prog = NULL;
1559         gc->pipe[i].shader.cur_tex = 0;
1560         gc->pipe[i].shader.cur_texu = 0;
1561         gc->pipe[i].shader.cur_texv = 0;
1562         gc->pipe[i].shader.cur_texa = 0;
1563         gc->pipe[i].shader.cur_texm = 0;
1564         gc->pipe[i].shader.tex_target = GL_TEXTURE_2D;
1565         gc->pipe[i].shader.render_op = EVAS_RENDER_COPY;
1566         gc->pipe[i].shader.smooth = 0;
1567         gc->pipe[i].shader.blend = 0;
1568         gc->pipe[i].shader.clip = 0;
1569         gc->pipe[i].shader.cx = 0;
1570         gc->pipe[i].shader.cy = 0;
1571         gc->pipe[i].shader.cw = 0;
1572         gc->pipe[i].shader.ch = 0;
1573      }
1574    gc->change.size = 1;
1575 
1576    glDisable(GL_SCISSOR_TEST);
1577    glScissor(0, 0, 0, 0);
1578 
1579    glDisable(GL_DEPTH_TEST);
1580    glEnable(GL_DITHER);
1581    glDisable(GL_BLEND);
1582    glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
1583    // no dest alpha
1584 //   glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); // dest alpha
1585 //   glBlendFunc(GL_SRC_ALPHA, GL_ONE); // ???
1586    glDepthMask(GL_FALSE);
1587 
1588    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
1589    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
1590    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
1591    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
1592 #ifdef GL_TEXTURE_MAX_ANISOTROPY_EXT
1593    if (shared->info.anisotropic > 0.0)
1594      glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, 1.0);
1595 #endif
1596 
1597    glEnableVertexAttribArray(SHAD_VERTEX);
1598    glEnableVertexAttribArray(SHAD_COLOR);
1599    if (gc->state.current.prog != PRG_INVALID)
1600      glUseProgram(gc->state.current.prog->prog);
1601 
1602    glActiveTexture(GL_TEXTURE0);
1603    glBindTexture(gc->pipe[0].shader.tex_target, gc->pipe[0].shader.cur_tex);
1604 
1605    _evas_gl_common_viewport_set(gc);
1606 }
1607 
1608 EAPI void
evas_gl_common_context_resize(Evas_Engine_GL_Context * gc,int w,int h,int rot)1609 evas_gl_common_context_resize(Evas_Engine_GL_Context *gc, int w, int h, int rot)
1610 {
1611    if ((gc->w == w) && (gc->h == h) && (gc->rot == rot)) return;
1612    evas_gl_common_context_flush(gc);
1613    gc->change.size = 1;
1614    gc->rot = rot;
1615    gc->w = w;
1616    gc->h = h;
1617    if (_evas_gl_common_context == gc) _evas_gl_common_viewport_set(gc);
1618 }
1619 
1620 void
evas_gl_common_tiling_start(Evas_Engine_GL_Context * gc EINA_UNUSED,int rot,int gw,int gh,int cx,int cy,int cw,int ch,int bitmask)1621 evas_gl_common_tiling_start(Evas_Engine_GL_Context *gc EINA_UNUSED,
1622                             int rot, int gw, int gh,
1623                             int cx, int cy, int cw, int ch,
1624                             int bitmask)
1625 {
1626    if (!glsym_glStartTiling) return;
1627    switch (rot)
1628      {
1629       case 0: // UP this way: ^
1630         glsym_glStartTiling(cx, cy, cw, ch, bitmask);
1631         break;
1632       case 90: // UP this way: <
1633         glsym_glStartTiling(gh - (cy + ch), cx, ch, cw, bitmask);
1634         break;
1635       case 180: // UP this way: v
1636         glsym_glStartTiling(gw - (cx + cw), gh - (cy + ch), cw, ch, bitmask);
1637         break;
1638       case 270: // UP this way: >
1639         glsym_glStartTiling(cy, gw - (cx + cw), ch, cw, bitmask);
1640         break;
1641       default: // assume up is up
1642         glsym_glStartTiling(cx, cy, cw, ch, bitmask);
1643         break;
1644      }
1645    GLERRV("glsym_glStartTiling");
1646 }
1647 
1648 void
evas_gl_common_tiling_done(Evas_Engine_GL_Context * gc EINA_UNUSED)1649 evas_gl_common_tiling_done(Evas_Engine_GL_Context *gc EINA_UNUSED)
1650 {
1651    if (glsym_glEndTiling)
1652      {
1653         glsym_glEndTiling(GL_COLOR_BUFFER_BIT0_QCOM);
1654         GLERRV("glsym_glEndTiling");
1655      }
1656 }
1657 
1658 
1659 EAPI void
evas_gl_common_context_done(Evas_Engine_GL_Context * gc)1660 evas_gl_common_context_done(Evas_Engine_GL_Context *gc)
1661 {
1662    if (gc->master_clip.used)
1663      {
1664         if (glsym_glEndTiling)
1665           {
1666              glsym_glEndTiling(GL_COLOR_BUFFER_BIT0_QCOM);
1667              GLERRV("glsym_glEndTiling");
1668           }
1669         gc->master_clip.used = EINA_FALSE;
1670      }
1671 }
1672 
1673 void
evas_gl_common_context_target_surface_set(Evas_Engine_GL_Context * gc,Evas_GL_Image * surface)1674 evas_gl_common_context_target_surface_set(Evas_Engine_GL_Context *gc,
1675                                           Evas_GL_Image *surface)
1676 {
1677    if (surface == gc->pipe[0].shader.surface) return;
1678 
1679    evas_gl_common_context_flush(gc);
1680    evas_gl_common_context_done(gc);
1681 
1682    gc->state.current.prog = NULL;
1683    gc->state.current.cur_tex = 0;
1684    gc->state.current.cur_texu = 0;
1685    gc->state.current.cur_texv = 0;
1686    gc->state.current.cur_texa = 0;
1687    gc->state.current.cur_texm = 0;
1688    gc->state.current.tex_target = GL_TEXTURE_2D;
1689    gc->state.current.render_op = -1;
1690    gc->state.current.smooth = -1;
1691    gc->state.current.blend = -1;
1692    gc->state.current.clip = -1;
1693    gc->state.current.cx = -1;
1694    gc->state.current.cy = -1;
1695    gc->state.current.cw = -1;
1696    gc->state.current.ch = -1;
1697    gc->state.current.anti_alias = -1;
1698 
1699    gc->pipe[0].shader.surface = surface;
1700    gc->change.size = 1;
1701 #ifdef GL_GLES
1702 # ifndef GL_FRAMEBUFFER
1703 #  define GL_FRAMEBUFFER GL_FRAMEBUFFER_OES
1704 # endif
1705 #else
1706 # ifndef GL_FRAMEBUFFER
1707 #  define GL_FRAMEBUFFER GL_FRAMEBUFFER_EXT
1708 # endif
1709 #endif
1710    if (gc->pipe[0].shader.surface == gc->def_surface)
1711      glsym_glBindFramebuffer(GL_FRAMEBUFFER, 0);
1712    else
1713       glsym_glBindFramebuffer(GL_FRAMEBUFFER, surface->tex->pt->fb);
1714    _evas_gl_common_viewport_set(gc);
1715 }
1716 
1717 static inline Eina_Bool
_push_mask(Evas_Engine_GL_Context * gc,const int pn,int nm,Evas_GL_Texture * mtex,int mx,int my,int mw,int mh,Shader_Sampling msam,int nms)1718 _push_mask(Evas_Engine_GL_Context *gc, const int pn, int nm, Evas_GL_Texture *mtex,
1719            int mx, int my, int mw, int mh, Shader_Sampling msam, int nms)
1720 {
1721    double glmx, glmy, glmw, glmh, yinv = -1.f;
1722    int gw = gc->w, gh = gc->h, i, cnt = 6;
1723 
1724    if (!((gc->pipe[0].shader.surface == gc->def_surface) ||
1725          (!gc->pipe[0].shader.surface)))
1726      {
1727         gw = gc->pipe[0].shader.surface->w;
1728         gh = gc->pipe[0].shader.surface->h;
1729         yinv = 1.f;
1730      }
1731 
1732    if (!gw || !gh || !mw || !mh || !mtex->pt->w || !mtex->pt->h)
1733      return EINA_FALSE;
1734 
1735    /* Vertex shader:
1736     *
1737     * INPUTS:
1738     *   vec4 mask_coord = vec4(glmx, glmy, glmw, glmh);
1739     *   int rotation_id = gc->rot / 90;
1740     *
1741     * CODE:
1742     *   vec4 mask_Position = mvp * vertex * vec4(0.5, sign(mask_coord.w) * 0.5, 0.5, 0.5) + vec4(0.5, 0.5, 0, 0);
1743     *   vec2 pos[4]; // no ctor-style init because of GLSL-ES (version 100)
1744     *   pos[0] = vec2(mask_Position.xy);
1745     *   pos[1] = vec2(1.0 - mask_Position.y, mask_Position.x);
1746     *   pos[2] = vec2(1.0 - mask_Position.xy);
1747     *   pos[3] = vec2(mask_Position.y, 1.0 - mask_Position.x);
1748     *   tex_m = pos[rotation_id].xy * abs(mask_coord.zw) + mask_coord.xy;
1749     */
1750    glmx = (double)((mtex->x * mw) - (mtex->w * mx)) / (double)(mw * mtex->pt->w);
1751    glmy = (double)((mtex->y * mh) - (mtex->h * my)) / (double)(mh * mtex->pt->h);
1752    glmw = (double)(gw * mtex->w) / (double)(mw * mtex->pt->w);
1753    glmh = (double)(gh * mtex->h) / (double)(mh * mtex->pt->h);
1754    glmh *= yinv;
1755 
1756    if (gc->pipe[pn].array.line)
1757      cnt = 2;
1758 
1759    for (i = 0; i < cnt; i++)
1760      PUSH_TEXM(pn, glmx, glmy, glmw, glmh);
1761 
1762    if (msam)
1763      {
1764         double samx = (double)(mtex->w) / (double)(mtex->pt->w * mw * 4);
1765         double samy = (double)(mtex->h) / (double)(mtex->pt->h * mh * 4);
1766         PUSH_MASKSAM(pn, samx, samy, cnt);
1767      }
1768 
1769    return EINA_TRUE;
1770 }
1771 
1772 #define PUSH_MASK(pn, mtex, mx, my, mw, mh, msam) if (mtex) do { \
1773    _push_mask(gc, pn, nm, mtex, mx, my, mw, mh, msam, nms); \
1774    } while(0)
1775 
1776 static int
pipe_region_intersects(Evas_Engine_GL_Context * gc,int n,int x,int y,int w,int h)1777 pipe_region_intersects(Evas_Engine_GL_Context *gc, int n,
1778                        int x, int y, int w, int h)
1779 {
1780 #define SPANS_INTERSECT(x1, w1, x2, w2) \
1781 (!((((x2) + (w2)) <= (x1)) || ((x2) >= ((x1) + (w1)))))
1782 
1783 #define REGIONS_INTERSECT(x, y, w, h, xx, yy, ww, hh) \
1784 ((SPANS_COMMON((x), (w), (xx), (ww))) && (SPANS_COMMON((y), (h), (yy), (hh))))
1785 
1786    float rx, ry, rw, rh;
1787    int ii, end;
1788    const GLfloat *v;
1789 
1790    rx = gc->pipe[n].region.x;
1791    ry = gc->pipe[n].region.y;
1792    rw = gc->pipe[n].region.w;
1793    rh = gc->pipe[n].region.h;
1794    if (!REGIONS_INTERSECT(x, y, w, h, rx, ry, rw, rh)) return 0;
1795 
1796    // a hack for now. map pipes use their whole bounding box for intersects
1797    // which at worst case reduces to old pipeline flushes, but cheaper than
1798    // full quad region or triangle intersects right now
1799    if (gc->pipe[n].region.type == SHD_MAP) return 1;
1800 
1801    v = gc->pipe[n].array.vertex;
1802    end = gc->pipe[n].array.num * 3;
1803    for (ii = 0; ii < end; ii += (3 * 3 * 2))
1804      {  // tri 1...
1805         // 0, 1, 2 < top left
1806         // 3, 4, 5 < top right
1807         // 6, 7, 8 < bottom left
1808         rx = v[ii + 0];
1809         ry = v[ii + 1];
1810         rw = v[ii + 3] - rx;
1811         rh = v[ii + 7] - ry;
1812         if (REGIONS_INTERSECT(x, y, w, h, rx, ry, rw, rh)) return 1;
1813      }
1814    return 0;
1815 }
1816 
1817 static void
pipe_region_expand(Evas_Engine_GL_Context * gc,int n,int x,int y,int w,int h)1818 pipe_region_expand(Evas_Engine_GL_Context *gc, int n,
1819                    int x, int y, int w, int h)
1820 {
1821    int x1, y1, x2, y2;
1822 
1823    if (gc->pipe[n].region.w <= 0)
1824      {
1825         gc->pipe[n].region.x = x;
1826         gc->pipe[n].region.y = y;
1827         gc->pipe[n].region.w = w;
1828         gc->pipe[n].region.h = h;
1829         return;
1830      }
1831    x1 = gc->pipe[n].region.x;
1832    y1 = gc->pipe[n].region.y;
1833    x2 = gc->pipe[n].region.x + gc->pipe[n].region.w;
1834    y2 = gc->pipe[n].region.y + gc->pipe[n].region.h;
1835    if (x < x1) x1 = x;
1836    if (y < y1) y1 = y;
1837    if ((x + w) > x2) x2 = x + w;
1838    if ((y + h) > y2) y2 = y + h;
1839    gc->pipe[n].region.x = x1;
1840    gc->pipe[n].region.y = y1;
1841    gc->pipe[n].region.w = x2 - x1;
1842    gc->pipe[n].region.h = y2 - y1;
1843 }
1844 
1845 static Eina_Bool
vertex_array_size_check(Evas_Engine_GL_Context * gc,int pn,int n)1846 vertex_array_size_check(Evas_Engine_GL_Context *gc, int pn, int n)
1847 {
1848 //   return 1;
1849    if ((gc->pipe[pn].array.num + n) > gc->shared->info.max_vertex_elements)
1850      {
1851         shader_array_flush(gc);
1852         return 0;
1853      }
1854    return 1;
1855 }
1856 
1857 static int
_evas_gl_common_context_push(Shader_Type rtype,Evas_Engine_GL_Context * gc,Evas_GL_Texture * tex,Evas_GL_Texture * texm,Evas_GL_Program * prog,int x,int y,int w,int h,Eina_Bool blend,Eina_Bool smooth,Eina_Bool clip,int cx,int cy,int cw,int ch,Eina_Bool mask_smooth)1858 _evas_gl_common_context_push(Shader_Type rtype,
1859                              Evas_Engine_GL_Context *gc,
1860                              Evas_GL_Texture *tex,
1861                              Evas_GL_Texture *texm,
1862                              Evas_GL_Program *prog,
1863                              int x, int y, int w, int h,
1864                              Eina_Bool blend,
1865                              Eina_Bool smooth,
1866                              Eina_Bool clip,
1867                              int cx, int cy, int cw, int ch,
1868                              Eina_Bool mask_smooth)
1869 {
1870    GLuint current_tex = 0;
1871    int pn = 0;
1872 
1873    if (tex)
1874      current_tex = tex->ptt ? tex->ptt->texture : tex->pt->texture;
1875 
1876  again:
1877    vertex_array_size_check(gc, gc->state.top_pipe, (rtype == SHD_LINE) ? 2 : 6);
1878    pn = gc->state.top_pipe;
1879 
1880    if (!((pn == 0) && (gc->pipe[pn].array.num == 0)))
1881      {
1882         int found = 0;
1883         int i;
1884 
1885         for (i = pn; i >= 0; i--)
1886           {
1887              if ((gc->pipe[i].region.type == rtype)
1888                  && (!tex || gc->pipe[i].shader.cur_tex == current_tex)
1889                  && (!texm || ((gc->pipe[i].shader.cur_texm == texm->pt->texture)
1890                                && (gc->pipe[i].shader.mask_smooth == mask_smooth)))
1891                  && (gc->pipe[i].shader.prog == prog)
1892                  && (gc->pipe[i].shader.smooth == smooth)
1893                  && (gc->pipe[i].shader.blend == blend)
1894                  && (gc->pipe[i].shader.render_op == gc->dc->render_op)
1895                  && (gc->pipe[i].shader.clip == clip)
1896                  && (!clip || ((gc->pipe[i].shader.cx == cx)
1897                                && (gc->pipe[i].shader.cy == cy)
1898                                && (gc->pipe[i].shader.cw == cw)
1899                                && (gc->pipe[i].shader.ch == ch))))
1900                {
1901                   found = 1;
1902                   pn = i;
1903                   break;
1904                }
1905              if (pipe_region_intersects(gc, i, x, y, w, h)) break;
1906           }
1907         if (!found)
1908           {
1909              pn = gc->state.top_pipe + 1;
1910              if (pn >= gc->shared->info.tune.pipes.max)
1911                {
1912                   shader_array_flush(gc);
1913                   goto again;
1914                }
1915              gc->state.top_pipe = pn;
1916           }
1917      }
1918    if ((tex) && (((tex->im) && (tex->im->native.data)) || tex->pt->dyn.img))
1919      {
1920         if (gc->pipe[pn].array.im != tex->im)
1921           {
1922              shader_array_flush(gc);
1923              pn = gc->state.top_pipe; // 0 after flush
1924              gc->pipe[pn].array.im = tex->im;
1925              goto again;
1926           }
1927      }
1928    return pn;
1929 }
1930 
1931 void
evas_gl_common_context_line_push(Evas_Engine_GL_Context * gc,int x1,int y1,int x2,int y2,int clip,int cx,int cy,int cw,int ch,Evas_GL_Texture * mtex,int mx,int my,int mw,int mh,Eina_Bool mask_smooth,Eina_Bool mask_color,int r,int g,int b,int a)1932 evas_gl_common_context_line_push(Evas_Engine_GL_Context *gc,
1933                                  int x1, int y1, int x2, int y2,
1934                                  int clip, int cx, int cy, int cw, int ch,
1935                                  Evas_GL_Texture *mtex, int mx, int my, int mw, int mh,
1936                                  Eina_Bool mask_smooth, Eina_Bool mask_color,
1937                                  int r, int g, int b, int a)
1938 {
1939    Eina_Bool blend = EINA_FALSE;
1940    Evas_GL_Program *prog;
1941    int pn = 0, i;
1942    GLuint mtexid = mtex ? mtex->pt->texture : 0;
1943    Shader_Sampling masksam = SHD_SAM11;
1944    int x = MIN(x1, x2);
1945    int y = MIN(y1, y2);
1946    int w = abs(x2 - x1);
1947    int h = abs(y2 - y1);
1948 
1949    if (!(gc->dc->render_op == EVAS_RENDER_COPY) && ((a < 255) || (mtex)))
1950      blend = EINA_TRUE;
1951 
1952    prog = evas_gl_common_shader_program_get(gc, SHD_LINE, NULL, 0, r, g, b, a,
1953                                             0, 0, 0, 0, EINA_FALSE, NULL, EINA_FALSE,
1954                                             mtex, mask_smooth, mask_color, mw, mh,
1955                                             EINA_FALSE, NULL, NULL, &masksam);
1956 
1957    pn = _evas_gl_common_context_push(SHD_LINE,
1958                                      gc, NULL, mtex,
1959                                      prog,
1960                                      x, y, w, h,
1961                                      blend,
1962                                      EINA_FALSE,
1963                                      0, 0, 0, 0, 0,
1964                                      mask_smooth);
1965 
1966    if (gc->pipe[pn].array.num == 0)
1967      {
1968         gc->pipe[pn].region.type = SHD_LINE;
1969         gc->pipe[pn].shader.prog = prog;
1970         gc->pipe[pn].shader.cur_tex = 0;
1971         gc->pipe[pn].shader.cur_texm = mtexid;
1972         gc->pipe[pn].shader.blend = blend;
1973         gc->pipe[pn].shader.render_op = gc->dc->render_op;
1974         gc->pipe[pn].shader.clip = clip;
1975         gc->pipe[pn].shader.cx = cx;
1976         gc->pipe[pn].shader.cy = cy;
1977         gc->pipe[pn].shader.cw = cw;
1978         gc->pipe[pn].shader.ch = ch;
1979         gc->pipe[pn].shader.mask_smooth = mask_smooth;
1980 
1981         gc->pipe[pn].array.line = 1;
1982         gc->pipe[pn].array.anti_alias = gc->dc->anti_alias;
1983         gc->pipe[pn].array.use_vertex = 1;
1984         gc->pipe[pn].array.use_color = 1;
1985         gc->pipe[pn].array.use_texuv = 0;
1986         gc->pipe[pn].array.use_texuv2 = 0;
1987         gc->pipe[pn].array.use_texuv3 = 0;
1988         gc->pipe[pn].array.use_texa = 0;
1989         gc->pipe[pn].array.use_texsam = 0;
1990         gc->pipe[pn].array.use_masksam = (masksam != SHD_SAM11);
1991         gc->pipe[pn].array.use_mask = !!mtex;
1992      }
1993 
1994    pipe_region_expand(gc, pn, x, y, w, h);
1995    PIPE_GROW(gc, pn, 2);
1996    PUSH_VERTEX(pn, x1, y1, 0);
1997    PUSH_VERTEX(pn, x2, y2, 0);
1998    PUSH_MASK(pn, mtex, mx, my, mw, mh, masksam);
1999    for (i = 0; i < 2; i++)
2000      PUSH_COLOR(pn, r, g, b, a);
2001 }
2002 
2003 void
evas_gl_common_context_rectangle_push(Evas_Engine_GL_Context * gc,int x,int y,int w,int h,int r,int g,int b,int a,Evas_GL_Texture * mtex,int mx,int my,int mw,int mh,Eina_Bool mask_smooth,Eina_Bool mask_color)2004 evas_gl_common_context_rectangle_push(Evas_Engine_GL_Context *gc,
2005                                       int x, int y, int w, int h,
2006                                       int r, int g, int b, int a,
2007                                       Evas_GL_Texture *mtex,
2008                                       int mx, int my, int mw, int mh,
2009                                       Eina_Bool mask_smooth, Eina_Bool mask_color)
2010 {
2011    Eina_Bool blend = EINA_FALSE;
2012    Shader_Sampling masksam = SHD_SAM11;
2013    Evas_GL_Program *prog;
2014    GLuint mtexid = mtex ? mtex->pt->texture : 0;
2015    int pn = 0;
2016 
2017    if (!(gc->dc->render_op == EVAS_RENDER_COPY) && ((a < 255) || mtex))
2018      blend = EINA_TRUE;
2019 
2020    prog = evas_gl_common_shader_program_get(gc, SHD_RECT, NULL, 0, r, g, b, a,
2021                                             0, 0, 0, 0, EINA_FALSE, NULL, EINA_FALSE,
2022                                             mtex, mask_smooth, mask_color, mw, mh,
2023                                             EINA_FALSE, NULL, NULL, &masksam);
2024 
2025 
2026    pn = _evas_gl_common_context_push(SHD_RECT,
2027                                      gc, NULL, mtex,
2028                                      prog,
2029                                      x, y, w, h,
2030                                      blend,
2031                                      EINA_FALSE,
2032                                      0, 0, 0, 0, 0,
2033                                      mask_smooth);
2034    if (gc->pipe[pn].array.num == 0)
2035      {
2036         gc->pipe[pn].region.type = SHD_RECT;
2037         gc->pipe[pn].shader.prog = prog;
2038         gc->pipe[pn].shader.cur_tex = 0;
2039         gc->pipe[pn].shader.cur_texm = mtexid;
2040         gc->pipe[pn].shader.blend = blend;
2041         gc->pipe[pn].shader.render_op = gc->dc->render_op;
2042         gc->pipe[pn].shader.mask_smooth = mask_smooth;
2043         gc->pipe[pn].shader.clip = 0;
2044         gc->pipe[pn].shader.cx = 0;
2045         gc->pipe[pn].shader.cy = 0;
2046         gc->pipe[pn].shader.cw = 0;
2047         gc->pipe[pn].shader.ch = 0;
2048         gc->pipe[pn].array.line = 0;
2049         gc->pipe[pn].array.use_vertex = 1;
2050         gc->pipe[pn].array.use_color = 1;
2051         gc->pipe[pn].array.use_texuv = 0;
2052         gc->pipe[pn].array.use_texuv2 = 0;
2053         gc->pipe[pn].array.use_texuv3 = 0;
2054         gc->pipe[pn].array.use_texa = 0;
2055         gc->pipe[pn].array.use_texsam = 0;
2056         gc->pipe[pn].array.use_masksam = (masksam != SHD_SAM11);
2057         gc->pipe[pn].array.use_mask = !!mtex;
2058      }
2059 
2060    pipe_region_expand(gc, pn, x, y, w, h);
2061    PIPE_GROW(gc, pn, 6);
2062    PUSH_6_VERTICES(pn, x, y, w, h);
2063    PUSH_MASK(pn, mtex, mx, my, mw, mh, masksam);
2064    PUSH_6_COLORS(pn, r, g, b, a);
2065 }
2066 
2067 #define SWAP(a, b, tmp) \
2068    tmp = *a; \
2069    *a = *b; \
2070    *b = tmp;
2071 
2072 // 1-2      4-1
2073 // | |  =>  | |
2074 // 4-3      3-2
2075 static void
_rotate_90(double * x1,double * y1,double * x2,double * y2,double * x3,double * y3,double * x4,double * y4)2076 _rotate_90(double *x1, double *y1, double *x2, double *y2, double *x3, double *y3, double *x4, double *y4)
2077 {
2078    double tmp;
2079 
2080    SWAP(x1, x4, tmp);
2081    SWAP(y1, y4, tmp);
2082 
2083    SWAP(x4, x3, tmp);
2084    SWAP(y4, y3, tmp);
2085 
2086    SWAP(x3, x2, tmp);
2087    SWAP(y3, y2, tmp);
2088 }
2089 
2090 // 1-2      3-4
2091 // | |  =>  | |
2092 // 4-3      2-1
2093 static void
_rotate_180(double * x1,double * y1,double * x2,double * y2,double * x3,double * y3,double * x4,double * y4)2094 _rotate_180(double *x1, double *y1, double *x2, double *y2, double *x3, double *y3, double *x4, double *y4)
2095 {
2096    double tmp;
2097 
2098    SWAP(x1, x3, tmp);
2099    SWAP(y1, y3, tmp);
2100 
2101    SWAP(x2, x4, tmp);
2102    SWAP(y2, y4, tmp);
2103 }
2104 
2105 // 1-2      2-3
2106 // | |  =>  | |
2107 // 4-3      1-4
2108 static void
_rotate_270(double * x1,double * y1,double * x2,double * y2,double * x3,double * y3,double * x4,double * y4)2109 _rotate_270(double *x1, double *y1, double *x2, double *y2, double *x3, double *y3, double *x4, double *y4)
2110 {
2111    double tmp;
2112 
2113    SWAP(x1, x2, tmp);
2114    SWAP(y1, y2, tmp);
2115 
2116    SWAP(x2, x3, tmp);
2117    SWAP(y2, y3, tmp);
2118 
2119    SWAP(x3, x4, tmp);
2120    SWAP(y3, y4, tmp);
2121 }
2122 
2123 // 1-2      2-1
2124 // | |  =>  | |
2125 // 4-3      3-4
2126 static void
_flip_horizontal(double * x1,double * y1,double * x2,double * y2,double * x3,double * y3,double * x4,double * y4)2127 _flip_horizontal(double *x1, double *y1, double *x2, double *y2, double *x3, double *y3, double *x4, double *y4)
2128 {
2129    double tmp;
2130 
2131    SWAP(x1, x2, tmp);
2132    SWAP(y1, y2, tmp);
2133 
2134    SWAP(x3, x4, tmp);
2135    SWAP(y3, y4, tmp);
2136 }
2137 
2138 // 1-2      4-3
2139 // | |  =>  | |
2140 // 4-3      1-2
2141 static void
_flip_vertical(double * x1,double * y1,double * x2,double * y2,double * x3,double * y3,double * x4,double * y4)2142 _flip_vertical(double *x1, double *y1, double *x2, double *y2, double *x3, double *y3, double *x4, double *y4)
2143 {
2144    double tmp;
2145 
2146    SWAP(x1, x4, tmp);
2147    SWAP(y1, y4, tmp);
2148 
2149    SWAP(x2, x3, tmp);
2150    SWAP(y2, y3, tmp);
2151 }
2152 
2153 // 1-2      1-4
2154 // | |  =>  | |
2155 // 4-3      2-3
2156 static void
_transpose(double * x1 EINA_UNUSED,double * y1 EINA_UNUSED,double * x2,double * y2,double * x3 EINA_UNUSED,double * y3 EINA_UNUSED,double * x4,double * y4)2157 _transpose(double *x1 EINA_UNUSED, double *y1 EINA_UNUSED, double *x2, double *y2,
2158            double *x3 EINA_UNUSED, double *y3 EINA_UNUSED, double *x4, double *y4)
2159 {
2160    double tmp;
2161 
2162    SWAP(x2, x4, tmp);
2163    SWAP(y2, y4, tmp);
2164 }
2165 
2166 // 1-2      3-2
2167 // | |  =>  | |
2168 // 4-3      4-1
2169 static void
_transverse(double * x1,double * y1,double * x2 EINA_UNUSED,double * y2 EINA_UNUSED,double * x3,double * y3,double * x4 EINA_UNUSED,double * y4 EINA_UNUSED)2170 _transverse(double *x1, double *y1, double *x2 EINA_UNUSED, double *y2 EINA_UNUSED,
2171             double *x3, double *y3, double *x4 EINA_UNUSED, double *y4 EINA_UNUSED)
2172 {
2173    double tmp;
2174 
2175    SWAP(x1, x3, tmp);
2176    SWAP(y1, y3, tmp);
2177 }
2178 
2179 void
evas_gl_common_context_image_push(Evas_Engine_GL_Context * gc,Evas_GL_Texture * tex,double sx,double sy,double sw,double sh,int x,int y,int w,int h,Evas_GL_Texture * mtex,int mx,int my,int mw,int mh,Eina_Bool mask_smooth,Eina_Bool mask_color,int r,int g,int b,int a,Eina_Bool smooth,Eina_Bool tex_only,Eina_Bool alphaonly)2180 evas_gl_common_context_image_push(Evas_Engine_GL_Context *gc,
2181                                   Evas_GL_Texture *tex,
2182                                   double sx, double sy, double sw, double sh,
2183                                   int x, int y, int w, int h,
2184                                   Evas_GL_Texture *mtex, int mx, int my, int mw, int mh,
2185                                   Eina_Bool mask_smooth, Eina_Bool mask_color,
2186                                   int r, int g, int b, int a,
2187                                   Eina_Bool smooth, Eina_Bool tex_only,
2188                                   Eina_Bool alphaonly)
2189 {
2190 
2191    Evas_GL_Texture_Pool *pt;
2192    double ox1, oy1, ox2, oy2, ox3, oy3, ox4, oy4;
2193    GLfloat tx1, ty1, tx2, ty2, tx3, ty3, tx4, ty4;
2194    GLfloat offsetx, offsety;
2195    double pw, ph;
2196    Eina_Bool blend = EINA_FALSE;
2197    Evas_GL_Program *prog;
2198    int pn = 0, render_op = gc->dc->render_op, nomul = 0;
2199    Shader_Sampling sam = 0, masksam = 0;
2200    int yinvert = 0;
2201    Shader_Type shd_in = SHD_IMAGE;
2202    int tex_target = GL_TEXTURE_2D;
2203 
2204    if (tex->im)
2205      {
2206         if (tex->im->native.data)
2207           shd_in = SHD_IMAGENATIVE;
2208         if (tex->im->native.target == GL_TEXTURE_EXTERNAL_OES)
2209           tex_target = GL_TEXTURE_EXTERNAL_OES;
2210      }
2211 
2212    if (!!mtex)
2213      {
2214         // masking forces BLEND mode (mask with COPY does not make sense)
2215         blend = EINA_TRUE;
2216         render_op = EVAS_RENDER_BLEND;
2217      }
2218    else if (!(render_op == EVAS_RENDER_COPY) && ((a < 255) || (tex->alpha)))
2219      blend = EINA_TRUE;
2220 
2221    prog = evas_gl_common_shader_program_get(gc, shd_in, NULL, 0, r, g, b, a,
2222                                             sw, sh, w, h, smooth, tex, tex_only,
2223                                             mtex, mask_smooth, mask_color, mw, mh,
2224                                             alphaonly, &sam, &nomul, &masksam);
2225 
2226    if (tex->ptt)
2227      {
2228         pt = tex->ptt;
2229         offsetx = tex->tx;
2230         offsety = tex->ty;
2231         smooth = EINA_TRUE;
2232 
2233         // Adjusting sx, sy, sw and sh to real size of tiny texture
2234         sx = sx * (EVAS_GL_TILE_SIZE - 2) / tex->w;
2235         sw = sw * (EVAS_GL_TILE_SIZE - 2) / tex->w;
2236         sy = sy * (EVAS_GL_TILE_SIZE - 1) / tex->h;
2237         sh = sh * (EVAS_GL_TILE_SIZE - 1) / tex->h;
2238      }
2239    else
2240      {
2241         pt = tex->pt;
2242         offsetx = tex->x;
2243         offsety = tex->y;
2244      }
2245 
2246    pn = _evas_gl_common_context_push(SHD_IMAGE,
2247                                      gc, tex, mtex,
2248                                      prog,
2249                                      x, y, w, h,
2250                                      blend,
2251                                      smooth,
2252                                      0, 0, 0, 0, 0,
2253                                      mask_smooth);
2254 
2255    if (gc->pipe[pn].array.num == 0)
2256      {
2257         gc->pipe[pn].region.type = SHD_IMAGE;
2258         gc->pipe[pn].shader.prog = prog;
2259         gc->pipe[pn].shader.cur_tex = pt->texture;
2260         gc->pipe[pn].shader.cur_texm = mtex ? mtex->pt->texture : 0;
2261         gc->pipe[pn].shader.tex_target = tex_target;
2262         gc->pipe[pn].shader.smooth = smooth;
2263         gc->pipe[pn].shader.mask_smooth = mask_smooth;
2264         gc->pipe[pn].shader.blend = blend;
2265         gc->pipe[pn].shader.render_op = render_op;
2266         gc->pipe[pn].shader.clip = 0;
2267         gc->pipe[pn].shader.cx = 0;
2268         gc->pipe[pn].shader.cy = 0;
2269         gc->pipe[pn].shader.cw = 0;
2270         gc->pipe[pn].shader.ch = 0;
2271         gc->pipe[pn].array.line = 0;
2272         gc->pipe[pn].array.use_vertex = 1;
2273         gc->pipe[pn].array.use_color = !nomul;
2274         gc->pipe[pn].array.use_texuv = 1;
2275         gc->pipe[pn].array.use_texuv2 = 0;
2276         gc->pipe[pn].array.use_texuv3 = 0;
2277         gc->pipe[pn].array.use_texsam = (sam != SHD_SAM11);
2278         gc->pipe[pn].array.use_mask = !!mtex;
2279         gc->pipe[pn].array.use_masksam = (masksam != SHD_SAM11);
2280      }
2281 
2282    pipe_region_expand(gc, pn, x, y, w, h);
2283    PIPE_GROW(gc, pn, 6);
2284 
2285    pw = pt->w;
2286    ph = pt->h;
2287 
2288    if (tex->im &&
2289        (tex->im->orient == EVAS_IMAGE_ORIENT_90))
2290      {
2291         double tmp;
2292 
2293         SWAP(&sw, &sh, tmp);
2294         SWAP(&sx, &sy, tmp);
2295 
2296         sy = tex->im->h - sh - sy;
2297      }
2298 
2299    else if (tex->im &&
2300        (tex->im->orient == EVAS_IMAGE_ORIENT_180))
2301      {
2302         sx = tex->im->w - sw - sx;
2303         sy = tex->im->h - sh - sy;
2304      }
2305 
2306    else if (tex->im &&
2307        (tex->im->orient == EVAS_IMAGE_ORIENT_270))
2308      {
2309         double tmp;
2310 
2311         SWAP(&sw, &sh, tmp);
2312         SWAP(&sx, &sy, tmp);
2313 
2314         sx = tex->im->w - sw - sx;
2315      }
2316 
2317    else if (tex->im &&
2318        (tex->im->orient == EVAS_IMAGE_FLIP_HORIZONTAL))
2319      {
2320         sx = tex->im->w - sw - sx;
2321      }
2322 
2323    else if (tex->im &&
2324        (tex->im->orient == EVAS_IMAGE_FLIP_VERTICAL))
2325      {
2326         sy = tex->im->h - sh - sy;
2327      }
2328 
2329    else if (tex->im &&
2330        (tex->im->orient == EVAS_IMAGE_FLIP_TRANSVERSE))
2331      {
2332         double tmp;
2333 
2334         SWAP(&sw, &sh, tmp);
2335         SWAP(&sx, &sy, tmp);
2336 
2337         sx = tex->im->w - sw - sx;
2338         sy = tex->im->h - sh - sy;
2339      }
2340 
2341    else if (tex->im &&
2342        (tex->im->orient == EVAS_IMAGE_FLIP_TRANSPOSE))
2343      {
2344         double tmp;
2345 
2346         SWAP(&sw, &sh, tmp);
2347         SWAP(&sx, &sy, tmp);
2348      }
2349 
2350    ox1 = sx;
2351    oy1 = sy;
2352    ox2 = sx + sw;
2353    oy2 = sy;
2354    ox3 = sx + sw;
2355    oy3 = sy + sh;
2356    ox4 = sx;
2357    oy4 = sy + sh;
2358 
2359    if ((tex->im) && (tex->im->native.data))
2360      {
2361         if (tex->im->native.func.yinvert)
2362           yinvert = tex->im->native.func.yinvert(tex->im);
2363         else
2364           yinvert = tex->im->native.yinvert;
2365      }
2366 
2367    if ((tex->im) && (!yinvert))
2368      {
2369         // FIXME: What if yinvert is true? How to test that?
2370         switch (tex->im->orient)
2371           {
2372            case EVAS_IMAGE_ORIENT_NONE:
2373               break;
2374            case EVAS_IMAGE_ORIENT_90:
2375               _rotate_90(&ox1, &oy1, &ox2, &oy2, &ox3, &oy3, &ox4, &oy4);
2376               break;
2377            case EVAS_IMAGE_ORIENT_180:
2378               _rotate_180(&ox1, &oy1, &ox2, &oy2, &ox3, &oy3, &ox4, &oy4);
2379               break;
2380            case EVAS_IMAGE_ORIENT_270:
2381               _rotate_270(&ox1, &oy1, &ox2, &oy2, &ox3, &oy3, &ox4, &oy4);
2382               break;
2383            case EVAS_IMAGE_FLIP_HORIZONTAL:
2384               _flip_horizontal(&ox1, &oy1, &ox2, &oy2, &ox3, &oy3, &ox4, &oy4);
2385               break;
2386            case EVAS_IMAGE_FLIP_VERTICAL:
2387               _flip_vertical(&ox1, &oy1, &ox2, &oy2, &ox3, &oy3, &ox4, &oy4);
2388               break;
2389            case EVAS_IMAGE_FLIP_TRANSVERSE:
2390               _transverse(&ox1, &oy1, &ox2, &oy2, &ox3, &oy3, &ox4, &oy4);
2391               break;
2392            case EVAS_IMAGE_FLIP_TRANSPOSE:
2393               _transpose(&ox1, &oy1, &ox2, &oy2, &ox3, &oy3, &ox4, &oy4);
2394               break;
2395            default:
2396               ERR("Wrong orientation ! %i", tex->im->orient);
2397           }
2398      }
2399 
2400    tx1 = ((double)(offsetx) + ox1) / pw;
2401    ty1 = ((double)(offsety) + oy1) / ph;
2402    tx2 = ((double)(offsetx) + ox2) / pw;
2403    ty2 = ((double)(offsety) + oy2) / ph;
2404    tx3 = ((double)(offsetx) + ox3) / pw;
2405    ty3 = ((double)(offsety) + oy3) / ph;
2406    tx4 = ((double)(offsetx) + ox4) / pw;
2407    ty4 = ((double)(offsety) + oy4) / ph;
2408    if ((tex->im) && (tex->im->native.data) && (!tex->im->native.yinvert))
2409      {
2410         ty1 = 1.0 - ty1;
2411         ty2 = 1.0 - ty2;
2412         ty3 = 1.0 - ty3;
2413         ty4 = 1.0 - ty4;
2414      }
2415 
2416    PUSH_6_VERTICES(pn, x, y, w, h);
2417    PUSH_6_QUAD(pn, tx1, ty1, tx2, ty2, tx3, ty3, tx4, ty4);
2418 
2419    if (sam)
2420      {
2421         double samx = (double)(sw) / (double)(tex->pt->w * w * 4);
2422         double samy = (double)(sh) / (double)(tex->pt->h * h * 4);
2423         PUSH_SAMPLES(pn, samx, samy);
2424      }
2425 
2426    PUSH_MASK(pn, mtex, mx, my, mw, mh, masksam);
2427 
2428    if (!nomul)
2429      PUSH_6_COLORS(pn, r, g, b, a);
2430 }
2431 
2432 void
evas_gl_common_context_font_push(Evas_Engine_GL_Context * gc,Evas_GL_Texture * tex,double sx,double sy,double sw,double sh,int x,int y,int w,int h,Evas_GL_Texture * mtex,int mx,int my,int mw,int mh,Eina_Bool mask_smooth,Eina_Bool mask_color,int r,int g,int b,int a)2433 evas_gl_common_context_font_push(Evas_Engine_GL_Context *gc,
2434                                  Evas_GL_Texture *tex,
2435                                  double sx, double sy, double sw, double sh,
2436                                  int x, int y, int w, int h,
2437                                  Evas_GL_Texture *mtex, int mx, int my, int mw, int mh,
2438                                  Eina_Bool mask_smooth, Eina_Bool mask_color,
2439                                  int r, int g, int b, int a)
2440 {
2441    GLfloat tx1, tx2, ty1, ty2;
2442    Shader_Sampling masksam = SHD_SAM11;
2443    Evas_GL_Program *prog;
2444    int pn = 0;
2445 
2446    prog = evas_gl_common_shader_program_get(gc, SHD_FONT, NULL, 0, r, g, b, a,
2447                                             sw, sh, w, h, EINA_FALSE, tex, EINA_FALSE,
2448                                             mtex, mask_smooth, mask_color, mw, mh,
2449                                             EINA_FALSE, NULL, NULL, &masksam);
2450 
2451    pn = _evas_gl_common_context_push(SHD_FONT,
2452                                      gc, tex, mtex,
2453                                      prog,
2454                                      x, y, w, h,
2455                                      1,
2456                                      0,
2457                                      0, 0, 0, 0, 0,
2458                                      mask_smooth);
2459 
2460    if (gc->pipe[pn].array.num == 0)
2461      {
2462         gc->pipe[pn].region.type = SHD_FONT;
2463         gc->pipe[pn].shader.prog = prog;
2464         gc->pipe[pn].shader.cur_tex = tex->pt->texture;
2465         gc->pipe[pn].shader.cur_texm = mtex ? mtex->pt->texture : 0;
2466         gc->pipe[pn].shader.smooth = 0;
2467         gc->pipe[pn].shader.blend = 1;
2468         gc->pipe[pn].shader.render_op = gc->dc->render_op;
2469         gc->pipe[pn].shader.mask_smooth = mask_smooth;
2470         gc->pipe[pn].shader.clip = 0;
2471         gc->pipe[pn].shader.cx = 0;
2472         gc->pipe[pn].shader.cy = 0;
2473         gc->pipe[pn].shader.cw = 0;
2474         gc->pipe[pn].shader.ch = 0;
2475         gc->pipe[pn].array.line = 0;
2476         gc->pipe[pn].array.use_vertex = 1;
2477         gc->pipe[pn].array.use_color = 1;
2478         gc->pipe[pn].array.use_texuv = 1;
2479         gc->pipe[pn].array.use_texuv2 = 0;
2480         gc->pipe[pn].array.use_texuv3 = 0;
2481         gc->pipe[pn].array.use_texsam = 0;
2482         gc->pipe[pn].array.use_mask = !!mtex;
2483         gc->pipe[pn].array.use_masksam = (masksam != SHD_SAM11);
2484      }
2485 
2486    pipe_region_expand(gc, pn, x, y, w, h);
2487    PIPE_GROW(gc, pn, 6);
2488 
2489    if (EINA_DBL_EQ(sw, 0.0))
2490      {
2491         tx1 = tex->sx1;
2492         ty1 = tex->sy1;
2493         tx2 = tex->sx2;
2494         ty2 = tex->sy2;
2495      }
2496    else
2497      {
2498         tx1 = ((double)(tex->x) + sx) / (double)tex->pt->w;
2499         ty1 = ((double)(tex->y) + sy) / (double)tex->pt->h;
2500         tx2 = ((double)(tex->x) + sx + sw) / (double)tex->pt->w;
2501         ty2 = ((double)(tex->y) + sy + sh) / (double)tex->pt->h;
2502      }
2503 
2504    PUSH_6_VERTICES(pn, x, y, w, h);
2505    PUSH_6_TEXUV(pn, tx1, ty1, tx2, ty2);
2506    PUSH_MASK(pn, mtex, mx, my, mw, mh, masksam);
2507    PUSH_6_COLORS(pn, r, g, b, a);
2508 }
2509 
2510 void
evas_gl_common_context_yuv_push(Evas_Engine_GL_Context * gc,Evas_GL_Texture * tex,double sx,double sy,double sw,double sh,int x,int y,int w,int h,Evas_GL_Texture * mtex,int mx,int my,int mw,int mh,Eina_Bool mask_smooth,Eina_Bool mask_color,int r,int g,int b,int a,Eina_Bool smooth)2511 evas_gl_common_context_yuv_push(Evas_Engine_GL_Context *gc,
2512                                 Evas_GL_Texture *tex,
2513                                 double sx, double sy, double sw, double sh,
2514                                 int x, int y, int w, int h,
2515                                 Evas_GL_Texture *mtex, int mx, int my, int mw, int mh,
2516                                 Eina_Bool mask_smooth, Eina_Bool mask_color,
2517                                 int r, int g, int b, int a,
2518                                 Eina_Bool smooth)
2519 {
2520    GLfloat tx1, tx2, ty1, ty2, t2x1, t2x2, t2y1, t2y2;
2521    Shader_Sampling masksam = SHD_SAM11;
2522    Eina_Bool blend = 0;
2523    Evas_GL_Program *prog;
2524    int pn = 0, nomul = 0;
2525 
2526    if ((a < 255) || (!!mtex))
2527      blend = 1;
2528 
2529    prog = evas_gl_common_shader_program_get(gc, SHD_YUV, NULL, 0, r, g, b, a,
2530                                             w, h, w, h, smooth, tex, 0,
2531                                             mtex, mask_smooth, mask_color, mw, mh,
2532                                             EINA_FALSE, NULL, &nomul, &masksam);
2533 
2534    pn = _evas_gl_common_context_push(SHD_YUV,
2535                                      gc, tex, mtex,
2536                                      prog,
2537                                      x, y, w, h,
2538                                      blend,
2539                                      smooth,
2540                                      0, 0, 0, 0, 0,
2541                                      mask_smooth);
2542 
2543    if (gc->pipe[pn].array.num == 0)
2544      {
2545         gc->pipe[pn].region.type = SHD_YUV;
2546         gc->pipe[pn].shader.prog = prog;
2547         gc->pipe[pn].shader.cur_tex = tex->pt->texture;
2548         gc->pipe[pn].shader.cur_texu = tex->ptu->texture;
2549         gc->pipe[pn].shader.cur_texv = tex->ptv->texture;
2550         gc->pipe[pn].shader.cur_texm = mtex ? mtex->pt->texture : 0;
2551         gc->pipe[pn].shader.smooth = smooth;
2552         gc->pipe[pn].shader.blend = blend;
2553         gc->pipe[pn].shader.render_op = gc->dc->render_op;
2554         gc->pipe[pn].shader.mask_smooth = mask_smooth;
2555         gc->pipe[pn].shader.clip = 0;
2556         gc->pipe[pn].shader.cx = 0;
2557         gc->pipe[pn].shader.cy = 0;
2558         gc->pipe[pn].shader.cw = 0;
2559         gc->pipe[pn].shader.ch = 0;
2560         gc->pipe[pn].array.line = 0;
2561         gc->pipe[pn].array.use_vertex = 1;
2562         gc->pipe[pn].array.use_color = !nomul;
2563         gc->pipe[pn].array.use_texuv = 1;
2564         gc->pipe[pn].array.use_texuv2 = 1;
2565         gc->pipe[pn].array.use_texuv3 = 1;
2566         gc->pipe[pn].array.use_mask = !!mtex;
2567         gc->pipe[pn].array.use_texsam = 0;
2568         gc->pipe[pn].array.use_masksam = (masksam != SHD_SAM11);
2569      }
2570 
2571    pipe_region_expand(gc, pn, x, y, w, h);
2572    PIPE_GROW(gc, pn, 6);
2573 
2574    tx1 = (sx) / (double)tex->pt->w;
2575    ty1 = (sy) / (double)tex->pt->h;
2576    tx2 = (sx + sw) / (double)tex->pt->w;
2577    ty2 = (sy + sh) / (double)tex->pt->h;
2578 
2579    t2x1 = ((sx) / 2.0) / (double)tex->ptu->w;
2580    t2y1 = ((sy) / 2.0) / (double)tex->ptu->h;
2581    t2x2 = ((sx + sw) / 2.0) / (double)tex->ptu->w;
2582    t2y2 = ((sy + sh) / 2.0) / (double)tex->ptu->h;
2583 
2584    PUSH_6_VERTICES(pn, x, y, w, h);
2585    PUSH_6_TEXUV(pn, tx1, ty1, tx2, ty2);
2586    PUSH_6_TEXUV2(pn, t2x1, t2y1, t2x2, t2y2);
2587    PUSH_6_TEXUV3(pn, t2x1, t2y1, t2x2, t2y2);
2588    PUSH_MASK(pn, mtex, mx, my, mw, mh, masksam);
2589    if (!nomul)
2590      PUSH_6_COLORS(pn, r, g, b, a);
2591 }
2592 
2593 void
evas_gl_common_context_yuv_709_push(Evas_Engine_GL_Context * gc,Evas_GL_Texture * tex,double sx,double sy,double sw,double sh,int x,int y,int w,int h,Evas_GL_Texture * mtex,int mx,int my,int mw,int mh,Eina_Bool mask_smooth,Eina_Bool mask_color,int r,int g,int b,int a,Eina_Bool smooth)2594 evas_gl_common_context_yuv_709_push(Evas_Engine_GL_Context *gc,
2595                                     Evas_GL_Texture *tex,
2596                                     double sx, double sy, double sw, double sh,
2597                                     int x, int y, int w, int h,
2598                                     Evas_GL_Texture *mtex, int mx, int my, int mw, int mh,
2599                                     Eina_Bool mask_smooth, Eina_Bool mask_color,
2600                                     int r, int g, int b, int a,
2601                                     Eina_Bool smooth)
2602 {
2603    GLfloat tx1, tx2, ty1, ty2, t2x1, t2x2, t2y1, t2y2;
2604    Shader_Sampling masksam = SHD_SAM11;
2605    Eina_Bool blend = 0;
2606    Evas_GL_Program *prog;
2607    int pn = 0, nomul = 0;
2608 
2609    if ((a < 255) || (!!mtex))
2610      blend = 1;
2611 
2612    prog = evas_gl_common_shader_program_get(gc, SHD_YUV_709, NULL, 0, r, g, b, a,
2613                                             w, h, w, h, smooth, tex, 0,
2614                                             mtex, mask_smooth, mask_color, mw, mh,
2615                                             EINA_FALSE, NULL, &nomul, &masksam);
2616 
2617    pn = _evas_gl_common_context_push(SHD_YUV_709,
2618                                      gc, tex, mtex,
2619                                      prog,
2620                                      x, y, w, h,
2621                                      blend,
2622                                      smooth,
2623                                      0, 0, 0, 0, 0,
2624                                      mask_smooth);
2625 
2626    if (gc->pipe[pn].array.num == 0)
2627      {
2628         gc->pipe[pn].region.type = SHD_YUV_709;
2629         gc->pipe[pn].shader.prog = prog;
2630         gc->pipe[pn].shader.cur_tex = tex->pt->texture;
2631         gc->pipe[pn].shader.cur_texu = tex->ptu->texture;
2632         gc->pipe[pn].shader.cur_texv = tex->ptv->texture;
2633         gc->pipe[pn].shader.cur_texm = mtex ? mtex->pt->texture : 0;
2634         gc->pipe[pn].shader.smooth = smooth;
2635         gc->pipe[pn].shader.blend = blend;
2636         gc->pipe[pn].shader.render_op = gc->dc->render_op;
2637         gc->pipe[pn].shader.mask_smooth = mask_smooth;
2638         gc->pipe[pn].shader.clip = 0;
2639         gc->pipe[pn].shader.cx = 0;
2640         gc->pipe[pn].shader.cy = 0;
2641         gc->pipe[pn].shader.cw = 0;
2642         gc->pipe[pn].shader.ch = 0;
2643         gc->pipe[pn].array.line = 0;
2644         gc->pipe[pn].array.use_vertex = 1;
2645         gc->pipe[pn].array.use_color = !nomul;
2646         gc->pipe[pn].array.use_texuv = 1;
2647         gc->pipe[pn].array.use_texuv2 = 1;
2648         gc->pipe[pn].array.use_texuv3 = 1;
2649         gc->pipe[pn].array.use_mask = !!mtex;
2650         gc->pipe[pn].array.use_texsam = 0;
2651         gc->pipe[pn].array.use_masksam = (masksam != SHD_SAM11);
2652      }
2653 
2654    pipe_region_expand(gc, pn, x, y, w, h);
2655    PIPE_GROW(gc, pn, 6);
2656 
2657    tx1 = (sx) / (double)tex->pt->w;
2658    ty1 = (sy) / (double)tex->pt->h;
2659    tx2 = (sx + sw) / (double)tex->pt->w;
2660    ty2 = (sy + sh) / (double)tex->pt->h;
2661 
2662    t2x1 = ((sx) / 2.0) / (double)tex->ptu->w;
2663    t2y1 = ((sy) / 2.0) / (double)tex->ptu->h;
2664    t2x2 = ((sx + sw) / 2.0) / (double)tex->ptu->w;
2665    t2y2 = ((sy + sh) / 2.0) / (double)tex->ptu->h;
2666 
2667    PUSH_6_VERTICES(pn, x, y, w, h);
2668    PUSH_6_TEXUV(pn, tx1, ty1, tx2, ty2);
2669    PUSH_6_TEXUV2(pn, t2x1, t2y1, t2x2, t2y2);
2670    PUSH_6_TEXUV3(pn, t2x1, t2y1, t2x2, t2y2);
2671    PUSH_MASK(pn, mtex, mx, my, mw, mh, masksam);
2672    if (!nomul)
2673      PUSH_6_COLORS(pn, r, g, b, a);
2674 }
2675 
2676 void
evas_gl_common_context_yuy2_push(Evas_Engine_GL_Context * gc,Evas_GL_Texture * tex,double sx,double sy,double sw,double sh,int x,int y,int w,int h,Evas_GL_Texture * mtex,int mx,int my,int mw,int mh,Eina_Bool mask_smooth,Eina_Bool mask_color,int r,int g,int b,int a,Eina_Bool smooth)2677 evas_gl_common_context_yuy2_push(Evas_Engine_GL_Context *gc,
2678                                  Evas_GL_Texture *tex,
2679                                  double sx, double sy, double sw, double sh,
2680                                  int x, int y, int w, int h,
2681                                  Evas_GL_Texture *mtex, int mx, int my, int mw, int mh,
2682                                  Eina_Bool mask_smooth, Eina_Bool mask_color,
2683                                  int r, int g, int b, int a,
2684                                  Eina_Bool smooth)
2685 {
2686    GLfloat tx1, tx2, ty1, ty2, t2x1, t2x2, t2y1, t2y2;
2687    Shader_Sampling masksam = SHD_SAM11;
2688    Eina_Bool blend = 0;
2689    Evas_GL_Program *prog;
2690    int pn = 0, nomul = 0;
2691 
2692    if ((a < 255) || (!!mtex))
2693      blend = 1;
2694 
2695    prog = evas_gl_common_shader_program_get(gc, SHD_YUY2, NULL, 0, r, g, b, a,
2696                                             sw, sh, w, h, smooth, tex, 0,
2697                                             mtex, mask_smooth, mask_color, mw, mh,
2698                                             EINA_FALSE, NULL, &nomul, &masksam);
2699 
2700    pn = _evas_gl_common_context_push(SHD_YUY2,
2701                                      gc, tex, mtex,
2702                                      prog,
2703                                      x, y, w, h,
2704                                      blend,
2705                                      smooth,
2706                                      0, 0, 0, 0, 0,
2707                                      mask_smooth);
2708 
2709    if (gc->pipe[pn].array.num == 0)
2710      {
2711         gc->pipe[pn].region.type = SHD_YUY2;
2712         gc->pipe[pn].shader.prog = prog;
2713         gc->pipe[pn].shader.cur_tex = tex->pt->texture;
2714         gc->pipe[pn].shader.cur_texu = tex->ptuv->texture;
2715         gc->pipe[pn].shader.cur_texm = mtex ? mtex->pt->texture : 0;
2716         gc->pipe[pn].shader.smooth = smooth;
2717         gc->pipe[pn].shader.blend = blend;
2718         gc->pipe[pn].shader.render_op = gc->dc->render_op;
2719         gc->pipe[pn].shader.mask_smooth = mask_smooth;
2720         gc->pipe[pn].shader.clip = 0;
2721         gc->pipe[pn].shader.cx = 0;
2722         gc->pipe[pn].shader.cy = 0;
2723         gc->pipe[pn].shader.cw = 0;
2724         gc->pipe[pn].shader.ch = 0;
2725         gc->pipe[pn].array.line = 0;
2726         gc->pipe[pn].array.use_vertex = 1;
2727         gc->pipe[pn].array.use_color = !nomul;
2728         gc->pipe[pn].array.use_texuv = 1;
2729         gc->pipe[pn].array.use_texuv2 = 1;
2730         gc->pipe[pn].array.use_texuv3 = 0;
2731         gc->pipe[pn].array.use_mask = !!mtex;
2732         gc->pipe[pn].array.use_texsam = 0;
2733         gc->pipe[pn].array.use_masksam = (masksam != SHD_SAM11);
2734      }
2735 
2736    pipe_region_expand(gc, pn, x, y, w, h);
2737    PIPE_GROW(gc, pn, 6);
2738 
2739    tx1 = (sx) / (double)tex->pt->w;
2740    ty1 = (sy) / (double)tex->pt->h;
2741    tx2 = (sx + sw) / (double)tex->pt->w;
2742    ty2 = (sy + sh) / (double)tex->pt->h;
2743 
2744    t2x1 = sx / (double)tex->ptuv->w;
2745    t2y1 = sy / (double)tex->ptuv->h;
2746    t2x2 = (sx + sw) / (double)tex->ptuv->w;
2747    t2y2 = (sy + sh) / (double)tex->ptuv->h;
2748 
2749    PUSH_6_VERTICES(pn, x, y, w, h);
2750    PUSH_6_TEXUV(pn, tx1, ty1, tx2, ty2);
2751    PUSH_6_TEXUV2(pn, t2x1, t2y1, t2x2, t2y2);
2752    PUSH_MASK(pn, mtex, mx, my, mw, mh, masksam);
2753    if (!nomul)
2754      PUSH_6_COLORS(pn, r, g, b, a);
2755 }
2756 
2757 void
evas_gl_common_context_nv12_push(Evas_Engine_GL_Context * gc,Evas_GL_Texture * tex,double sx,double sy,double sw,double sh,int x,int y,int w,int h,Evas_GL_Texture * mtex,int mx,int my,int mw,int mh,Eina_Bool mask_smooth,Eina_Bool mask_color,int r,int g,int b,int a,Eina_Bool smooth)2758 evas_gl_common_context_nv12_push(Evas_Engine_GL_Context *gc,
2759                                  Evas_GL_Texture *tex,
2760                                  double sx, double sy, double sw, double sh,
2761                                  int x, int y, int w, int h,
2762                                  Evas_GL_Texture *mtex, int mx, int my, int mw, int mh,
2763                                  Eina_Bool mask_smooth, Eina_Bool mask_color,
2764                                  int r, int g, int b, int a,
2765                                  Eina_Bool smooth)
2766 {
2767    GLfloat tx1, tx2, ty1, ty2, t2x1, t2x2, t2y1, t2y2;
2768    Shader_Sampling masksam = SHD_SAM11;
2769    Eina_Bool blend = 0;
2770    Evas_GL_Program *prog;
2771    int pn = 0, nomul = 0;
2772 
2773    if ((a < 255) || (!!mtex))
2774      blend = 1;
2775 
2776    prog = evas_gl_common_shader_program_get(gc, SHD_NV12, NULL, 0, r, g, b, a,
2777                                             sw, sh, w, h, smooth, tex, 0,
2778                                             mtex, mask_smooth, mask_color, mw, mh,
2779                                             EINA_FALSE, NULL, &nomul, &masksam);
2780 
2781    pn = _evas_gl_common_context_push(SHD_NV12,
2782                                      gc, tex, mtex,
2783                                      prog,
2784                                      x, y, w, h,
2785                                      blend,
2786                                      smooth,
2787                                      0, 0, 0, 0, 0,
2788                                      mask_smooth);
2789 
2790    if (gc->pipe[pn].array.num == 0)
2791      {
2792         gc->pipe[pn].region.type = SHD_NV12;
2793         gc->pipe[pn].shader.prog = prog;
2794         gc->pipe[pn].shader.cur_tex = tex->pt->texture;
2795         gc->pipe[pn].shader.cur_tex_dyn = tex->pt->dyn.img;
2796         gc->pipe[pn].shader.cur_texu = tex->ptuv->texture;
2797         gc->pipe[pn].shader.cur_texu_dyn = tex->ptuv->dyn.img;
2798         gc->pipe[pn].shader.cur_texm = mtex ? mtex->pt->texture : 0;
2799         gc->pipe[pn].shader.smooth = smooth;
2800         gc->pipe[pn].shader.blend = blend;
2801         gc->pipe[pn].shader.render_op = gc->dc->render_op;
2802         gc->pipe[pn].shader.mask_smooth = mask_smooth;
2803         gc->pipe[pn].shader.clip = 0;
2804         gc->pipe[pn].shader.cx = 0;
2805         gc->pipe[pn].shader.cy = 0;
2806         gc->pipe[pn].shader.cw = 0;
2807         gc->pipe[pn].shader.ch = 0;
2808         gc->pipe[pn].array.line = 0;
2809         gc->pipe[pn].array.use_vertex = 1;
2810         gc->pipe[pn].array.use_color = !nomul;
2811         gc->pipe[pn].array.use_texuv = 1;
2812         gc->pipe[pn].array.use_texuv2 = 1;
2813         gc->pipe[pn].array.use_texuv3 = 0;
2814         gc->pipe[pn].array.use_mask = !!mtex;
2815         gc->pipe[pn].array.use_texsam = 0;
2816         gc->pipe[pn].array.use_masksam = (masksam != SHD_SAM11);
2817      }
2818 
2819    pipe_region_expand(gc, pn, x, y, w, h);
2820    PIPE_GROW(gc, pn, 6);
2821 
2822    tx1 = (sx) / (double)tex->pt->w;
2823    ty1 = (sy) / (double)tex->pt->h;
2824    tx2 = (sx + sw) / (double)tex->pt->w;
2825    ty2 = (sy + sh) / (double)tex->pt->h;
2826 
2827    t2x1 = sx / (double)tex->ptuv->w;
2828    t2y1 = sy / (double)tex->ptuv->h;
2829    t2x2 = (sx + sw) / (double)tex->ptuv->w;
2830    t2y2 = (sy + sh) / (double)tex->ptuv->h;
2831 
2832    PUSH_6_VERTICES(pn, x, y, w, h);
2833    PUSH_6_TEXUV(pn, tx1, ty1, tx2, ty2);
2834    PUSH_6_TEXUV2(pn, t2x1, t2y1, t2x2, t2y2);
2835    PUSH_MASK(pn, mtex, mx, my, mw, mh, masksam);
2836    if (!nomul)
2837      PUSH_6_COLORS(pn, r, g, b, a);
2838 }
2839 
2840 void
evas_gl_common_context_rgb_a_pair_push(Evas_Engine_GL_Context * gc,Evas_GL_Texture * tex,double sx,double sy,double sw,double sh,int x,int y,int w,int h,Evas_GL_Texture * mtex,int mx,int my,int mw,int mh,Eina_Bool mask_smooth,Eina_Bool mask_color,int r,int g,int b,int a,Eina_Bool smooth)2841 evas_gl_common_context_rgb_a_pair_push(Evas_Engine_GL_Context *gc,
2842                                        Evas_GL_Texture *tex,
2843                                        double sx, double sy,
2844                                        double sw, double sh,
2845                                        int x, int y, int w, int h,
2846                                        Evas_GL_Texture *mtex, int mx, int my, int mw, int mh,
2847                                        Eina_Bool mask_smooth, Eina_Bool mask_color,
2848                                        int r, int g, int b, int a,
2849                                        Eina_Bool smooth)
2850 
2851 {
2852    /* This RGB+Alpha mode is used for ETC1+Alpha textures, where the shader
2853     * will multiply RGB by alpha. Two textures are created: tex->{pt,pta}.
2854     * Since the exact encoding doesn't matter here (decoding is transparent
2855     * from the shader point of view), this method could be used for other
2856     * colorspaces as well (eg. RGB565+Alpha4, ...).
2857     */
2858 
2859    GLfloat tx1, tx2, ty1, ty2, t2x1, t2x2, t2y1, t2y2;
2860    Shader_Sampling masksam = SHD_SAM11;
2861    Evas_GL_Program *prog;
2862    int pn, nomul = 0;
2863 
2864    prog = evas_gl_common_shader_program_get(gc, SHD_RGB_A_PAIR, NULL, 0, r, g, b, a,
2865                                             sw, sh, w, h, smooth, tex, 0,
2866                                             mtex, mask_smooth, mask_color, mw, mh,
2867                                             EINA_FALSE, NULL, &nomul, &masksam);
2868 
2869    pn = _evas_gl_common_context_push(SHD_RGB_A_PAIR,
2870                                      gc, tex, mtex,
2871                                      prog,
2872                                      x, y, w, h,
2873                                      EINA_TRUE,
2874                                      smooth,
2875                                      EINA_FALSE, 0, 0, 0, 0,
2876                                      mask_smooth);
2877 
2878    if (gc->pipe[pn].array.num == 0)
2879      {
2880         gc->pipe[pn].region.type = SHD_RGB_A_PAIR;
2881         gc->pipe[pn].shader.prog = prog;
2882         gc->pipe[pn].shader.cur_tex = tex->pt->texture;
2883         gc->pipe[pn].shader.cur_texa = tex->pta->texture;
2884         gc->pipe[pn].shader.cur_texm = mtex ? mtex->pt->texture : 0;
2885         gc->pipe[pn].shader.smooth = smooth;
2886         gc->pipe[pn].shader.blend = EINA_TRUE;
2887         gc->pipe[pn].shader.render_op = gc->dc->render_op;
2888         gc->pipe[pn].shader.mask_smooth = mask_smooth;
2889         gc->pipe[pn].shader.clip = 0;
2890         gc->pipe[pn].shader.cx = 0;
2891         gc->pipe[pn].shader.cy = 0;
2892         gc->pipe[pn].shader.cw = 0;
2893         gc->pipe[pn].shader.ch = 0;
2894         gc->pipe[pn].array.line = 0;
2895         gc->pipe[pn].array.use_vertex = EINA_TRUE;
2896         gc->pipe[pn].array.use_color = !nomul;
2897         gc->pipe[pn].array.use_texuv = EINA_TRUE;
2898         gc->pipe[pn].array.use_texuv2 = 0;
2899         gc->pipe[pn].array.use_texuv3 = 0;
2900         gc->pipe[pn].array.use_texa = EINA_TRUE;
2901         gc->pipe[pn].array.use_texsam = 0;
2902         gc->pipe[pn].array.use_mask = !!mtex;
2903         gc->pipe[pn].array.use_masksam = (masksam != SHD_SAM11);
2904      }
2905 
2906    pipe_region_expand(gc, pn, x, y, w, h);
2907    PIPE_GROW(gc, pn, 6);
2908 
2909    // FIXME: pt and pta could have different x,y
2910    tx1 = (tex->x + sx) / (double)tex->pt->w;
2911    ty1 = (tex->y + sy) / (double)tex->pt->h;
2912    tx2 = (tex->x + sx + sw) / (double)tex->pt->w;
2913    ty2 = (tex->y + sy + sh) / (double)tex->pt->h;
2914 
2915    t2x1 = (tex->x + sx) / (double)tex->pta->w;
2916    t2y1 = (tex->y + sy) / (double)tex->pta->h;
2917    t2x2 = (tex->x + sx + sw) / (double)tex->pta->w;
2918    t2y2 = (tex->y + sy + sh) / (double)tex->pta->h;
2919 
2920    PUSH_6_VERTICES(pn, x, y, w, h);
2921    PUSH_6_TEXUV(pn, tx1, ty1, tx2, ty2);
2922    PUSH_6_TEXA(pn, t2x1, t2y1, t2x2, t2y2);
2923    PUSH_MASK(pn, mtex, mx, my, mw, mh, masksam);
2924    if (!nomul)
2925      PUSH_6_COLORS(pn, r, g, b, a);
2926 }
2927 
2928 void
evas_gl_common_context_image_map_push(Evas_Engine_GL_Context * gc,Evas_GL_Texture * tex,int npoints,RGBA_Map_Point * p,int clip,int cx,int cy,int cw,int ch,Evas_GL_Texture * mtex,int mx,int my,int mw,int mh,Eina_Bool mask_smooth,Eina_Bool mask_color,int r,int g,int b,int a,Eina_Bool smooth,Eina_Bool tex_only,Evas_Colorspace cspace)2929 evas_gl_common_context_image_map_push(Evas_Engine_GL_Context *gc,
2930                                       Evas_GL_Texture *tex,
2931                                       int npoints,
2932                                       RGBA_Map_Point *p,
2933                                       int clip, int cx, int cy, int cw, int ch,
2934                                       Evas_GL_Texture *mtex, int mx, int my, int mw, int mh,
2935                                       Eina_Bool mask_smooth, Eina_Bool mask_color,
2936                                       int r, int g, int b, int a,
2937                                       Eina_Bool smooth, Eina_Bool tex_only,
2938                                       Evas_Colorspace cspace)
2939 {
2940    const int points[6] = { 0, 1, 2, 0, 2, 3 };
2941    int x = 0, y = 0, w = 0, h = 0, px = 0, py = 0;
2942    GLfloat tx[4], ty[4], t2x[4], t2y[4];
2943    DATA32 cmul;
2944    Shader_Sampling masksam = SHD_SAM11;
2945    Evas_GL_Program *prog;
2946    Eina_Bool utexture = EINA_FALSE;
2947    Eina_Bool uvtexture = EINA_FALSE;
2948    Eina_Bool use_texa = EINA_FALSE;
2949    Shader_Type type;
2950    int pn = 0, i;
2951    int nomul = 0, yinvert = 0;
2952    Eina_Bool flat = EINA_FALSE;
2953    Eina_Bool blend = EINA_FALSE;
2954 
2955    if (!(gc->dc->render_op == EVAS_RENDER_COPY) &&
2956        ((a < 255) || (tex->alpha) || (!!mtex))) blend = EINA_TRUE;
2957 
2958    if ((A_VAL(&(p[0].col)) < 0xff) || (A_VAL(&(p[1].col)) < 0xff) ||
2959        (A_VAL(&(p[2].col)) < 0xff) || (A_VAL(&(p[3].col)) < 0xff))
2960      blend = EINA_TRUE;
2961 
2962    if (((p[0].z == p[1].z) && (p[1].z == p[2].z) && (p[2].z == p[3].z)) ||
2963        (p[0].foc <= 0))
2964      {
2965         flat = EINA_TRUE;
2966      }
2967 
2968    if (!clip) cx = cy = cw = ch = 0;
2969 
2970    switch (cspace)
2971      {
2972       case EVAS_COLORSPACE_YCBCR422P601_PL:
2973         type = SHD_YUV;
2974         utexture = EINA_TRUE;
2975         break;
2976       case EVAS_COLORSPACE_YCBCR422P709_PL:
2977         type = SHD_YUV_709;
2978         utexture = EINA_TRUE;
2979         break;
2980       case EVAS_COLORSPACE_YCBCR422601_PL:
2981         type = SHD_YUY2;
2982         uvtexture = EINA_TRUE;
2983         break;
2984       case EVAS_COLORSPACE_YCBCR420NV12601_PL:
2985       case EVAS_COLORSPACE_YCBCR420TM12601_PL:
2986         type = SHD_NV12;
2987         uvtexture = EINA_TRUE;
2988         break;
2989       case EVAS_COLORSPACE_ETC1_ALPHA:
2990         type = SHD_RGB_A_PAIR;
2991         use_texa = EINA_TRUE;
2992         break;
2993       default:
2994         type = SHD_MAP;
2995         break;
2996      }
2997    prog = evas_gl_common_shader_program_get(gc, type, p, npoints, r, g, b, a,
2998                                             w, h, w, h, smooth, tex, tex_only,
2999                                             mtex, mask_smooth, mask_color, mw, mh,
3000                                             EINA_FALSE, NULL, &nomul, &masksam);
3001 
3002    x = w = (p[0].x >> FP);
3003    y = h = (p[0].y >> FP);
3004    for (i = 0; i < 4; i++)
3005      {
3006         tx[i] = ((double)(tex->x) + (((double)p[i].u) / FP1)) /
3007           (double)tex->pt->w;
3008         ty[i] = ((double)(tex->y) + (((double)p[i].v) / FP1)) /
3009           (double)tex->pt->h;
3010         px = (p[i].x >> FP);
3011         if      (px < x) x = px;
3012         else if (px > w) w = px;
3013         py = (p[i].y >> FP);
3014         if      (py < y) y = py;
3015         else if (py > h) h = py;
3016         if (utexture)
3017           {
3018              t2x[i] = ((((double)p[i].u / 2) / FP1)) / (double)tex->ptu->w;
3019              t2y[i] = ((((double)p[i].v / 2) / FP1)) / (double)tex->ptu->h;
3020           }
3021         else if (uvtexture)
3022           {
3023              t2x[i] = ((((double)p[i].u / 2) / FP1)) / (double)tex->ptuv->w;
3024              t2y[i] = ((((double)p[i].v / 2) / FP1)) / (double)tex->ptuv->h;
3025           }
3026      }
3027    w = w - x;
3028    h = h - y;
3029 
3030    // FUZZZZ!
3031    x -= 3;
3032    y -= 3;
3033    w += 6;
3034    h += 6;
3035 
3036    if (!flat)
3037      {
3038         shader_array_flush(gc);
3039         gc->foc = p[0].foc >> FP;
3040         gc->z0 = p[0].z0 >> FP;
3041         gc->px = p[0].px >> FP;
3042         gc->py = p[0].py >> FP;
3043         gc->change.size = 1;
3044         _evas_gl_common_viewport_set(gc);
3045      }
3046    else if (clip)
3047      {
3048         int nx = x, ny = y, nw = w, nh = h;
3049 
3050         RECTS_CLIP_TO_RECT(nx, ny, nw, nh, cx, cy, cw, ch);
3051         if ((nx == x) && (ny == y) && (nw == w) && (nh == h))
3052           {
3053              clip = 0; cx = 0; cy = 0; cw = 0; ch = 0;
3054           }
3055         x = nx; y = ny; w = nw; h = nh;
3056      }
3057 
3058    pn = _evas_gl_common_context_push(SHD_MAP,
3059                                      gc, tex, mtex,
3060                                      prog,
3061                                      x, y, w, h,
3062                                      blend,
3063                                      smooth,
3064                                      clip, cx, cy, cw, ch,
3065                                      mask_smooth);
3066    if (gc->pipe[pn].array.num == 0)
3067      {
3068         gc->pipe[pn].region.type = SHD_MAP;
3069         gc->pipe[pn].shader.prog = prog;
3070         gc->pipe[pn].shader.cur_tex = tex->pt->texture;
3071         gc->pipe[pn].shader.tex_target = GL_TEXTURE_2D;
3072 
3073         if (utexture)
3074           {
3075              gc->pipe[pn].shader.cur_texu = tex->ptu->texture;
3076              gc->pipe[pn].shader.cur_texu_dyn = tex->ptu->dyn.img;
3077              gc->pipe[pn].shader.cur_texv = tex->ptv->texture;
3078              gc->pipe[pn].shader.cur_texv_dyn = tex->ptv->dyn.img;
3079           }
3080         else if (uvtexture)
3081           {
3082              gc->pipe[pn].shader.cur_texu = tex->ptuv->texture;
3083              gc->pipe[pn].shader.cur_texu_dyn = tex->ptuv->dyn.img;
3084           }
3085         gc->pipe[pn].shader.cur_texm = mtex ? mtex->pt->texture : 0;
3086         gc->pipe[pn].shader.smooth = smooth;
3087         gc->pipe[pn].shader.blend = blend;
3088         gc->pipe[pn].shader.render_op = gc->dc->render_op;
3089         gc->pipe[pn].shader.mask_smooth = mask_smooth;
3090         gc->pipe[pn].shader.clip = clip;
3091         gc->pipe[pn].shader.cx = cx;
3092         gc->pipe[pn].shader.cy = cy;
3093         gc->pipe[pn].shader.cw = cw;
3094         gc->pipe[pn].shader.ch = ch;
3095         gc->pipe[pn].array.line = 0;
3096         gc->pipe[pn].array.use_vertex = 1;
3097         gc->pipe[pn].array.use_color = !nomul;
3098         gc->pipe[pn].array.use_texuv = 1;
3099         gc->pipe[pn].array.use_texuv2 = (utexture || uvtexture) ? 1 : 0;
3100         gc->pipe[pn].array.use_texuv3 = (utexture) ? 1 : 0;
3101         gc->pipe[pn].array.use_mask = !!mtex;
3102         gc->pipe[pn].array.use_texa = use_texa;
3103         gc->pipe[pn].array.use_texsam = 0;
3104         gc->pipe[pn].array.use_masksam = (masksam != SHD_SAM11);
3105      }
3106 
3107    pipe_region_expand(gc, pn, x, y, w, h);
3108    PIPE_GROW(gc, pn, 6);
3109 
3110    if ((tex->im) && (tex->im->native.data))
3111      {
3112         if (tex->im->native.func.yinvert)
3113           yinvert = tex->im->native.func.yinvert(tex->im);
3114         else
3115           yinvert = tex->im->native.yinvert;
3116      }
3117 
3118    if ((tex->im) && (tex->im->native.data) && (!yinvert))
3119      {
3120         for (i = 0; i < 4; i++)
3121           {
3122              ty[i] = 1.0 - ty[i];
3123              if (utexture || uvtexture)
3124                 t2y[i] = 1.0 - t2y[i];
3125           }
3126      }
3127 
3128    cmul = ARGB_JOIN(a, r, g, b);
3129    for (i = 0; i < 6; i++)
3130      {
3131         DATA32 cl = MUL4_SYM(cmul, p[points[i]].col);
3132         if (flat)
3133           {
3134              PUSH_VERTEX(pn,
3135                          p[points[i]].fx,
3136                          p[points[i]].fy,
3137                          0);
3138           }
3139         else
3140           {
3141              PUSH_VERTEX(pn,
3142                          (p[points[i]].fx) + gc->shared->ax,
3143                          (p[points[i]].fy) + gc->shared->ay,
3144                          (p[points[i]].fz)
3145                          + (gc->shared->foc - gc->shared->z0));
3146           }
3147         PUSH_TEXUV(pn,
3148                    tx[points[i]],
3149                    ty[points[i]]);
3150         if (utexture)
3151           {
3152              PUSH_TEXUV2(pn,
3153                          t2x[points[i]],
3154                          t2y[points[i]]);
3155              PUSH_TEXUV3(pn,
3156                          t2x[points[i]],
3157                          t2y[points[i]]);
3158           }
3159         else if (uvtexture)
3160           {
3161              PUSH_TEXUV2(pn,
3162                          t2x[points[i]],
3163                          t2y[points[i]]);
3164           }
3165 
3166         if (!nomul)
3167           {
3168              PUSH_COLOR(pn,
3169                         R_VAL(&cl),
3170                         G_VAL(&cl),
3171                         B_VAL(&cl),
3172                         A_VAL(&cl));
3173           }
3174      }
3175 
3176    PUSH_MASK(pn, mtex, mx, my, mw, mh, masksam);
3177 
3178    if (!flat)
3179      {
3180         shader_array_flush(gc);
3181         gc->foc = 0;
3182         gc->z0 = 0;
3183         gc->px = 0;
3184         gc->py = 0;
3185         gc->change.size = 1;
3186         _evas_gl_common_viewport_set(gc);
3187      }
3188 }
3189 
3190 // ----------------------------------------------------------------------------
3191 // Gfx Filters
3192 
3193 static inline void
_filter_data_flush(Evas_Engine_GL_Context * gc,Evas_GL_Program * prog)3194 _filter_data_flush(Evas_Engine_GL_Context *gc, Evas_GL_Program *prog)
3195 {
3196    // filter_data is not using a vertex array, which means early flushes
3197    // are necessary. Vertex arrays crashed for whatever reason :(
3198    for (size_t k = 0; k < MAX_PIPES; k++)
3199      if ((gc->pipe[k].array.filter_data || gc->pipe[k].shader.filter.map_tex)
3200          && (gc->pipe[k].shader.prog == prog))
3201        {
3202           shader_array_flush(gc);
3203           break;
3204        }
3205 }
3206 
3207 static inline void
_filter_data_alloc(Evas_Engine_GL_Context * gc,int pn,int count)3208 _filter_data_alloc(Evas_Engine_GL_Context *gc, int pn, int count)
3209 {
3210    gc->pipe[pn].array.filter_data_count = count;
3211    if (count) gc->pipe[pn].array.filter_data = malloc(count * 2 * sizeof(GLfloat));
3212    else gc->pipe[pn].array.filter_data = NULL;
3213 }
3214 
3215 static inline void
_filter_data_prepare(Evas_Engine_GL_Context * gc EINA_UNUSED,Evas_GL_Program * prog,int count)3216 _filter_data_prepare(Evas_Engine_GL_Context *gc EINA_UNUSED,
3217                      Evas_GL_Program *prog, int count)
3218 {
3219    if (!prog->filter) prog->filter = calloc(1, sizeof(*prog->filter));
3220    if (!prog->filter->attribute.known_locations)
3221      {
3222         prog->filter->attribute.known_locations = EINA_TRUE;
3223         for (int k = 0; k < count; k++)
3224           {
3225              char name[32];
3226 
3227              sprintf(name, "filter_data_%d", k);
3228              prog->filter->attribute.loc[k] = glGetAttribLocation(prog->prog, name);
3229           }
3230      }
3231 }
3232 
3233 void
evas_gl_common_filter_displace_push(Evas_Engine_GL_Context * gc,Evas_GL_Texture * tex,Evas_GL_Texture * map_tex,int x,int y,int w,int h,double dx,double dy,Eina_Bool nearest)3234 evas_gl_common_filter_displace_push(Evas_Engine_GL_Context *gc,
3235                                     Evas_GL_Texture *tex, Evas_GL_Texture *map_tex,
3236                                     int x, int y, int w, int h, double dx, double dy,
3237                                     Eina_Bool nearest)
3238 {
3239    double sx, sy, sw, sh, pw, ph;
3240    double ox1, oy1, ox2, oy2, ox3, oy3, ox4, oy4;
3241    GLfloat tx1, ty1, tx2, ty2, tx3, ty3, tx4, ty4;
3242    Shader_Sampling sam = SHD_SAM11;
3243    GLfloat offsetx, offsety;
3244    GLfloat *filter_data;
3245    int r, g, b, a, nomul = 0, pn;
3246    Evas_GL_Program *prog;
3247    Eina_Bool blend = EINA_TRUE;
3248    Eina_Bool smooth = EINA_TRUE;
3249 
3250    r = R_VAL(&gc->dc->mul.col);
3251    g = G_VAL(&gc->dc->mul.col);
3252    b = B_VAL(&gc->dc->mul.col);
3253    a = A_VAL(&gc->dc->mul.col);
3254    if (gc->dc->render_op == EVAS_RENDER_COPY)
3255      blend = EINA_FALSE;
3256 
3257    prog = evas_gl_common_shader_program_get(gc, SHD_FILTER_DISPLACE, NULL, 0, r, g, b, a,
3258                                             w, h, w, h, smooth, tex, EINA_FALSE,
3259                                             NULL, EINA_FALSE, EINA_FALSE, 0, 0,
3260                                             EINA_FALSE, &sam, &nomul, NULL);
3261    _filter_data_flush(gc, prog);
3262 
3263    pn = _evas_gl_common_context_push(SHD_FILTER_DISPLACE, gc, tex, NULL, prog,
3264                                      x, y, w, h, blend, smooth,
3265                                      0, 0, 0, 0, 0, EINA_FALSE);
3266 
3267    if (gc->pipe[pn].array.num == 0)
3268      {
3269         gc->pipe[pn].region.type = SHD_FILTER_DISPLACE;
3270         gc->pipe[pn].shader.prog = prog;
3271         gc->pipe[pn].shader.cur_tex = tex->pt->texture;
3272         gc->pipe[pn].shader.cur_texm = 0;
3273         gc->pipe[pn].shader.tex_target = GL_TEXTURE_2D;
3274         gc->pipe[pn].shader.smooth = smooth;
3275         gc->pipe[pn].shader.mask_smooth = 0;
3276         gc->pipe[pn].shader.blend = blend;
3277         gc->pipe[pn].shader.render_op = gc->dc->render_op;
3278         gc->pipe[pn].shader.clip = 0;
3279         gc->pipe[pn].shader.cx = 0;
3280         gc->pipe[pn].shader.cy = 0;
3281         gc->pipe[pn].shader.cw = 0;
3282         gc->pipe[pn].shader.ch = 0;
3283         gc->pipe[pn].array.line = 0;
3284         gc->pipe[pn].array.use_vertex = 1;
3285         gc->pipe[pn].array.use_color = !nomul;
3286         gc->pipe[pn].array.use_texuv = 1;
3287         gc->pipe[pn].array.use_texuv2 = 0;
3288         gc->pipe[pn].array.use_texuv3 = 0;
3289         gc->pipe[pn].array.use_texsam = (sam != SHD_SAM11);
3290         gc->pipe[pn].array.use_mask = 0;
3291         gc->pipe[pn].array.use_masksam = 0;
3292      }
3293 
3294    pipe_region_expand(gc, pn, x, y, w, h);
3295    PIPE_GROW(gc, pn, 6);
3296 
3297    // displace properties
3298    gc->pipe[pn].shader.filter.map_tex = map_tex->pt->texture;
3299    gc->pipe[pn].shader.filter.map_nearest = nearest;
3300    _filter_data_prepare(gc, prog, 3);
3301    _filter_data_alloc(gc, pn, 3);
3302 
3303    sx = x;
3304    sy = y;
3305    sw = w;
3306    sh = h;
3307 
3308    pw = tex->pt->w;
3309    ph = tex->pt->h;
3310 
3311    ox1 = sx;
3312    oy1 = sy;
3313    ox2 = sx + sw;
3314    oy2 = sy;
3315    ox3 = sx + sw;
3316    oy3 = sy + sh;
3317    ox4 = sx;
3318    oy4 = sy + sh;
3319 
3320    offsetx = tex->x;
3321    offsety = tex->y;
3322 
3323    tx1 = ((double)(offsetx) + ox1) / pw;
3324    ty1 = ((double)(offsety) + oy1) / ph;
3325    tx2 = ((double)(offsetx) + ox2) / pw;
3326    ty2 = ((double)(offsety) + oy2) / ph;
3327    tx3 = ((double)(offsetx) + ox3) / pw;
3328    ty3 = ((double)(offsety) + oy3) / ph;
3329    tx4 = ((double)(offsetx) + ox4) / pw;
3330    ty4 = ((double)(offsety) + oy4) / ph;
3331 
3332    PUSH_6_VERTICES(pn, x, y, w, h);
3333    PUSH_6_QUAD(pn, tx1, ty1, tx2, ty2, tx3, ty3, tx4, ty4);
3334 
3335    if (sam)
3336      {
3337         double samx = (double)(sw) / (double)(tex->pt->w * w * 4);
3338         double samy = (double)(sh) / (double)(tex->pt->h * h * 4);
3339         PUSH_SAMPLES(pn, samx, samy);
3340      }
3341 
3342    filter_data = gc->pipe[pn].array.filter_data;
3343    filter_data[0] = (dx * tex->w / pw) / w;
3344    filter_data[1] = (dy * tex->h / ph) / h;
3345    filter_data[2] = tex->x / pw;
3346    filter_data[3] = tex->y / ph;
3347    filter_data[4] = (tex->x + tex->w) / pw;
3348    filter_data[5] = (tex->y + tex->h) / ph;
3349 
3350    if (!nomul)
3351      PUSH_6_COLORS(pn, r, g, b, a);
3352 }
3353 
3354 void
evas_gl_common_filter_curve_push(Evas_Engine_GL_Context * gc,Evas_GL_Texture * tex,int x,int y,int w,int h,const uint8_t * points,int channel)3355 evas_gl_common_filter_curve_push(Evas_Engine_GL_Context *gc,
3356                                  Evas_GL_Texture *tex,
3357                                  int x, int y, int w, int h,
3358                                  const uint8_t *points, int channel)
3359 {
3360    double sx, sy, sw, sh, pw, ph;
3361    double ox1, oy1, ox2, oy2, ox3, oy3, ox4, oy4;
3362    GLfloat tx1, ty1, tx2, ty2, tx3, ty3, tx4, ty4;
3363    Shader_Sampling sam = SHD_SAM11;
3364    GLfloat offsetx, offsety;
3365    int r, g, b, a, nomul = 0, pn, k;
3366    uint32_t values[256];
3367    Evas_GL_Program *prog;
3368    Eina_Bool blend = EINA_TRUE;
3369    Eina_Bool smooth = EINA_TRUE;
3370    GLuint map_tex;
3371 
3372    r = R_VAL(&gc->dc->mul.col);
3373    g = G_VAL(&gc->dc->mul.col);
3374    b = B_VAL(&gc->dc->mul.col);
3375    a = A_VAL(&gc->dc->mul.col);
3376    if (gc->dc->render_op == EVAS_RENDER_COPY)
3377      blend = EINA_FALSE;
3378 
3379    prog = evas_gl_common_shader_program_get(gc, SHD_FILTER_CURVE, NULL, 0, r, g, b, a,
3380                                             w, h, w, h, smooth, tex, EINA_FALSE,
3381                                             NULL, EINA_FALSE, EINA_FALSE, 0, 0,
3382                                             EINA_FALSE, &sam, &nomul, NULL);
3383    _filter_data_flush(gc, prog);
3384 
3385    pn = _evas_gl_common_context_push(SHD_FILTER_CURVE, gc, tex, NULL, prog,
3386                                      x, y, w, h, blend, smooth,
3387                                      0, 0, 0, 0, 0, EINA_FALSE);
3388 
3389    if (gc->pipe[pn].array.num == 0)
3390      {
3391         gc->pipe[pn].region.type = SHD_FILTER_CURVE;
3392         gc->pipe[pn].shader.prog = prog;
3393         gc->pipe[pn].shader.cur_tex = tex->pt->texture;
3394         gc->pipe[pn].shader.cur_texm = 0;
3395         gc->pipe[pn].shader.tex_target = GL_TEXTURE_2D;
3396         gc->pipe[pn].shader.smooth = smooth;
3397         gc->pipe[pn].shader.mask_smooth = 0;
3398         gc->pipe[pn].shader.blend = blend;
3399         gc->pipe[pn].shader.render_op = gc->dc->render_op;
3400         gc->pipe[pn].shader.clip = 0;
3401         gc->pipe[pn].shader.cx = 0;
3402         gc->pipe[pn].shader.cy = 0;
3403         gc->pipe[pn].shader.cw = 0;
3404         gc->pipe[pn].shader.ch = 0;
3405         gc->pipe[pn].array.line = 0;
3406         gc->pipe[pn].array.use_vertex = 1;
3407         gc->pipe[pn].array.use_color = !nomul;
3408         gc->pipe[pn].array.use_texuv = 1;
3409         gc->pipe[pn].array.use_texuv2 = 0;
3410         gc->pipe[pn].array.use_texuv3 = 0;
3411         gc->pipe[pn].array.use_texsam = (sam != SHD_SAM11);
3412         gc->pipe[pn].array.use_mask = 0;
3413         gc->pipe[pn].array.use_masksam = 0;
3414      }
3415 
3416    pipe_region_expand(gc, pn, x, y, w, h);
3417    PIPE_GROW(gc, pn, 6);
3418 
3419    // Build 256 colors map in RGBA
3420    switch (channel)
3421      {
3422       case 0: // EVAS_FILTER_CHANNEL_ALPHA
3423         for (k = 0; k < 256; k++)
3424           values[k] = ARGB_JOIN(points[k], k, k, k);
3425         break;
3426       case 1:  // EVAS_FILTER_CHANNEL_RED
3427         for (k = 0; k < 256; k++)
3428           values[k] = ARGB_JOIN(k, points[k], k, k);
3429         break;
3430       case 2:  // EVAS_FILTER_CHANNEL_GREEN
3431         for (k = 0; k < 256; k++)
3432           values[k] = ARGB_JOIN(k, k, points[k], k);
3433         break;
3434       case 3:  // EVAS_FILTER_CHANNEL_BLUE
3435         for (k = 0; k < 256; k++)
3436           values[k] = ARGB_JOIN(k, k, k, points[k]);
3437         break;
3438       case 4:  // EVAS_FILTER_CHANNEL_RGB
3439         for (k = 0; k < 256; k++)
3440           values[k] = ARGB_JOIN(k, points[k], points[k], points[k]);
3441         break;
3442       case 5: // ALPHA only
3443         for (k = 0; k < 256; k++)
3444           values[k] = ARGB_JOIN(points[k], points[k], points[k], points[k]);
3445         break;
3446       default: // INVALID: no curve applied
3447         for (k = 0; k < 256; k++)
3448           values[k] = ARGB_JOIN(k, k, k, k);
3449         break;
3450      }
3451 
3452    // Synchronous upload of 256x1 RGBA texture (FIXME: no reuse)
3453    glGenTextures(1, &map_tex);
3454    glBindTexture(GL_TEXTURE_2D, map_tex);
3455    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
3456    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
3457    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
3458    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
3459    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 256, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, values);
3460 
3461    // Set curve properties (no need for filter_data)
3462    gc->pipe[pn].shader.filter.map_tex = map_tex;
3463    gc->pipe[pn].shader.filter.map_nearest = EINA_TRUE;
3464    gc->pipe[pn].shader.filter.map_delete = EINA_TRUE;
3465    gc->pipe[pn].array.filter_data_count = 0;
3466 
3467    sx = x;
3468    sy = y;
3469    sw = w;
3470    sh = h;
3471 
3472    pw = tex->pt->w;
3473    ph = tex->pt->h;
3474 
3475    ox1 = sx;
3476    oy1 = sy;
3477    ox2 = sx + sw;
3478    oy2 = sy;
3479    ox3 = sx + sw;
3480    oy3 = sy + sh;
3481    ox4 = sx;
3482    oy4 = sy + sh;
3483 
3484    offsetx = tex->x;
3485    offsety = tex->y;
3486 
3487    tx1 = ((double)(offsetx) + ox1) / pw;
3488    ty1 = ((double)(offsety) + oy1) / ph;
3489    tx2 = ((double)(offsetx) + ox2) / pw;
3490    ty2 = ((double)(offsety) + oy2) / ph;
3491    tx3 = ((double)(offsetx) + ox3) / pw;
3492    ty3 = ((double)(offsety) + oy3) / ph;
3493    tx4 = ((double)(offsetx) + ox4) / pw;
3494    ty4 = ((double)(offsety) + oy4) / ph;
3495 
3496    PUSH_6_VERTICES(pn, x, y, w, h);
3497    PUSH_6_QUAD(pn, tx1, ty1, tx2, ty2, tx3, ty3, tx4, ty4);
3498 
3499    if (sam)
3500      {
3501         double samx = (double)(sw) / (double)(tex->pt->w * w * 4);
3502         double samy = (double)(sh) / (double)(tex->pt->h * h * 4);
3503         PUSH_SAMPLES(pn, samx, samy);
3504      }
3505 
3506    if (!nomul)
3507      PUSH_6_COLORS(pn, r, g, b, a);
3508 }
3509 
3510 void
evas_gl_common_filter_blend_push(Evas_Engine_GL_Context * gc,Evas_GL_Texture * tex,double sx,double sy,double sw,double sh,double dx,double dy,double dw,double dh,Eina_Bool alphaonly)3511 evas_gl_common_filter_blend_push(Evas_Engine_GL_Context *gc,
3512                                  Evas_GL_Texture *tex,
3513                                  double sx, double sy, double sw, double sh,
3514                                  double dx, double dy, double dw, double dh,
3515                                  Eina_Bool alphaonly)
3516 {
3517    int r, g, b, a;
3518 
3519    r = R_VAL(&gc->dc->mul.col);
3520    g = G_VAL(&gc->dc->mul.col);
3521    b = B_VAL(&gc->dc->mul.col);
3522    a = A_VAL(&gc->dc->mul.col);
3523    if (alphaonly)
3524      r = g = b = a;
3525 
3526    evas_gl_common_context_image_push(gc, tex, sx, sy, sw, sh, dx, dy, dw, dh,
3527                                      NULL, 0, 0, 0, 0, EINA_FALSE, EINA_FALSE,
3528                                      r, g, b, a, EINA_TRUE, EINA_FALSE,
3529                                      alphaonly);
3530 }
3531 
3532 void
evas_gl_common_filter_blur_push(Evas_Engine_GL_Context * gc,Evas_GL_Texture * tex,double sx,double sy,double sw,double sh,double dx,double dy,double dw,double dh,const double * const weights,const double * const offsets,int count,double radius,Eina_Bool horiz,Eina_Bool alphaonly)3533 evas_gl_common_filter_blur_push(Evas_Engine_GL_Context *gc,
3534                                 Evas_GL_Texture *tex,
3535                                 double sx, double sy, double sw, double sh,
3536                                 double dx, double dy, double dw, double dh,
3537                                 const double * const weights,
3538                                 const double * const offsets, int count,
3539                                 double radius, Eina_Bool horiz, Eina_Bool alphaonly)
3540 {
3541    double ox1, oy1, ox2, oy2, ox3, oy3, ox4, oy4, pw, ph, texlen;
3542    GLfloat tx1, ty1, tx2, ty2, tx3, ty3, tx4, ty4;
3543    GLfloat offsetx, offsety;
3544    int r, g, b, a, nomul = 0, pn;
3545    Evas_GL_Program *prog;
3546    Eina_Bool blend = EINA_TRUE;
3547    Eina_Bool smooth = EINA_TRUE;
3548    Shader_Type type = horiz ? SHD_FILTER_BLUR_X : SHD_FILTER_BLUR_Y;
3549    Eina_Bool update_uniforms = EINA_FALSE;
3550    GLuint *map_tex_data;
3551    double sum = 0.0;
3552 
3553    r = R_VAL(&gc->dc->mul.col);
3554    g = G_VAL(&gc->dc->mul.col);
3555    b = B_VAL(&gc->dc->mul.col);
3556    a = A_VAL(&gc->dc->mul.col);
3557    if (gc->dc->render_op == EVAS_RENDER_COPY)
3558      blend = EINA_FALSE;
3559 
3560    prog = evas_gl_common_shader_program_get(gc, type, NULL, 0, r, g, b, a,
3561                                             sw, sh, dw, dh, smooth, tex, EINA_FALSE,
3562                                             NULL, EINA_FALSE, EINA_FALSE, 0, 0,
3563                                             alphaonly, NULL, &nomul, NULL);
3564 
3565    _filter_data_flush(gc, prog);
3566    EINA_SAFETY_ON_NULL_RETURN(prog);
3567 
3568    pw = tex->pt->w;
3569    ph = tex->pt->h;
3570    texlen = horiz ? pw : ph;
3571 
3572    /* Convert double data to RGBA pixel data.
3573     *
3574     * We are not using GL_FLOAT or GL_DOUBLE because:
3575     * - It's not as portable (needs extensions),
3576     * - GL_DOUBLE didn't work during my tests (dunno why),
3577     * - GL_FLOAT didn't seem to carry the proper precision all the way to
3578     *   the fragment shader,
3579     * - Real data buffers are not available in GLES 2.0,
3580     * - GL_RGBA is 100% portable.
3581     */
3582    map_tex_data = alloca(2 * count * sizeof(*map_tex_data));
3583    for (int k = 0; k < count; k++)
3584      {
3585         GLuint val;
3586 
3587         if (k == 0) sum = weights[k];
3588         else sum += 2.0 * weights[k];
3589 
3590         // Weight is always > 0.0 and < 255.0 by maths
3591         val = (GLuint) (weights[k] * 256.0 * 256.0 * 256.0);
3592         map_tex_data[k] = val;
3593 
3594         // Offset is always in [0.0 , 1.0] by definition
3595         val = (GLuint) (offsets[k] * 256.0 * 256.0 * 256.0);
3596         map_tex_data[k + count] = val;
3597      }
3598 
3599    // Prepare attributes & uniforms
3600    _filter_data_prepare(gc, prog, 0);
3601    if (!prog->filter->uniform.known_locations)
3602      {
3603         prog->filter->uniform.known_locations = EINA_TRUE;
3604         prog->filter->uniform.blur_count_loc = glGetUniformLocation(prog->prog, "blur_count");
3605         prog->filter->uniform.blur_texlen_loc = glGetUniformLocation(prog->prog, "blur_texlen");
3606         prog->filter->uniform.blur_div_loc = glGetUniformLocation(prog->prog, "blur_div");
3607      }
3608 
3609    if ((prog->filter->uniform.blur_count_value != count - 1) ||
3610        (!EINA_FLT_EQ(prog->filter->uniform.blur_texlen_value, texlen)) ||
3611        (!EINA_FLT_EQ(prog->filter->uniform.blur_div_value, sum)))
3612      {
3613         update_uniforms = EINA_TRUE;
3614         shader_array_flush(gc);
3615      }
3616 
3617    pn = _evas_gl_common_context_push(type, gc, tex, NULL, prog,
3618                                      sx, sy, dw, dh, blend, smooth,
3619                                      0, 0, 0, 0, 0, EINA_FALSE);
3620 
3621    if (gc->pipe[pn].array.num == 0)
3622      {
3623         gc->pipe[pn].region.type = type;
3624         gc->pipe[pn].shader.prog = prog;
3625         gc->pipe[pn].shader.cur_tex = tex->pt->texture;
3626         gc->pipe[pn].shader.cur_texm = 0;
3627         gc->pipe[pn].shader.tex_target = GL_TEXTURE_2D;
3628         gc->pipe[pn].shader.smooth = smooth;
3629         gc->pipe[pn].shader.mask_smooth = 0;
3630         gc->pipe[pn].shader.blend = blend;
3631         gc->pipe[pn].shader.render_op = gc->dc->render_op;
3632         gc->pipe[pn].shader.clip = 0;
3633         gc->pipe[pn].shader.cx = 0;
3634         gc->pipe[pn].shader.cy = 0;
3635         gc->pipe[pn].shader.cw = 0;
3636         gc->pipe[pn].shader.ch = 0;
3637         gc->pipe[pn].array.line = 0;
3638         gc->pipe[pn].array.use_vertex = 1;
3639         gc->pipe[pn].array.use_color = !nomul;
3640         gc->pipe[pn].array.use_texuv = 1;
3641         gc->pipe[pn].array.use_texuv2 = 0;
3642         gc->pipe[pn].array.use_texuv3 = 0;
3643         gc->pipe[pn].array.use_texsam = 0;
3644         gc->pipe[pn].array.use_mask = 0;
3645         gc->pipe[pn].array.use_masksam = 0;
3646      }
3647 
3648    pipe_region_expand(gc, pn, dx, dy, dw, dh);
3649    PIPE_GROW(gc, pn, 6);
3650 
3651    _filter_data_alloc(gc, pn, 0);
3652 
3653    // Synchronous upload of Nx2 RGBA texture
3654    if (!EINA_DBL_EQ(prog->filter->blur_radius, radius))
3655      {
3656         prog->filter->blur_radius = radius;
3657 
3658         if (!prog->filter->texture.tex_ids[0])
3659           glGenTextures(1, prog->filter->texture.tex_ids);
3660 
3661         glBindTexture(GL_TEXTURE_2D, prog->filter->texture.tex_ids[0]);
3662         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
3663         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
3664         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
3665         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
3666         if (tex->gc->shared->info.unpack_row_length)
3667           glPixelStorei(GL_UNPACK_ROW_LENGTH, 0);
3668         glPixelStorei(GL_UNPACK_ALIGNMENT, sizeof(*map_tex_data));
3669         glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, count, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE, map_tex_data);
3670      }
3671 
3672    if (update_uniforms)
3673      {
3674         prog->filter->uniform.blur_count_value = count - 1;
3675         prog->filter->uniform.blur_texlen_value = texlen;
3676         prog->filter->uniform.blur_div_value = sum;
3677         glUseProgram(prog->prog);
3678         glUniform1i(prog->filter->uniform.blur_count_loc, prog->filter->uniform.blur_count_value);
3679         glUniform1f(prog->filter->uniform.blur_texlen_loc, prog->filter->uniform.blur_texlen_value);
3680         glUniform1f(prog->filter->uniform.blur_div_loc, prog->filter->uniform.blur_div_value);
3681      }
3682 
3683    // Set shader properties
3684    gc->pipe[pn].shader.filter.map_tex = prog->filter->texture.tex_ids[0];
3685    gc->pipe[pn].shader.filter.map_nearest = EINA_TRUE;
3686    gc->pipe[pn].shader.filter.map_delete = EINA_FALSE;
3687 
3688    ox1 = sx;
3689    oy1 = sy;
3690    ox2 = sx + sw;
3691    oy2 = sy;
3692    ox3 = sx + sw;
3693    oy3 = sy + sh;
3694    ox4 = sx;
3695    oy4 = sy + sh;
3696 
3697    offsetx = tex->x;
3698    offsety = tex->y;
3699 
3700    tx1 = ((double)(offsetx) + ox1) / pw;
3701    ty1 = ((double)(offsety) + oy1) / ph;
3702    tx2 = ((double)(offsetx) + ox2) / pw;
3703    ty2 = ((double)(offsety) + oy2) / ph;
3704    tx3 = ((double)(offsetx) + ox3) / pw;
3705    ty3 = ((double)(offsety) + oy3) / ph;
3706    tx4 = ((double)(offsetx) + ox4) / pw;
3707    ty4 = ((double)(offsety) + oy4) / ph;
3708 
3709    PUSH_6_VERTICES(pn, dx, dy, dw, dh);
3710    PUSH_6_QUAD(pn, tx1, ty1, tx2, ty2, tx3, ty3, tx4, ty4);
3711 
3712    if (!nomul)
3713      PUSH_6_COLORS(pn, r, g, b, a);
3714 }
3715 
3716 void
evas_gl_common_filter_grayscale_push(Evas_Engine_GL_Context * gc,Evas_GL_Texture * tex,int x,int y,int w,int h)3717 evas_gl_common_filter_grayscale_push(Evas_Engine_GL_Context *gc,
3718                                 Evas_GL_Texture *tex,
3719                                 int x, int y, int w, int h)
3720 {
3721    double ox1, oy1, ox2, oy2, ox3, oy3, ox4, oy4, pw, ph;
3722    GLfloat tx1, ty1, tx2, ty2, tx3, ty3, tx4, ty4;
3723    GLfloat offsetx, offsety;
3724    int r, g, b, a, nomul = 0, pn;
3725    Evas_GL_Program *prog;
3726    Eina_Bool blend = EINA_TRUE;
3727    Eina_Bool smooth = EINA_TRUE;
3728    Shader_Type type = SHD_FILTER_GRAYSCALE;
3729 
3730    r = R_VAL(&gc->dc->mul.col);
3731    g = G_VAL(&gc->dc->mul.col);
3732    b = B_VAL(&gc->dc->mul.col);
3733    a = A_VAL(&gc->dc->mul.col);
3734    if (gc->dc->render_op == EVAS_RENDER_COPY)
3735      blend = EINA_FALSE;
3736 
3737    prog = evas_gl_common_shader_program_get(gc, type, NULL, 0, r, g, b, a,
3738                                             w, h, w, h, smooth, tex, EINA_FALSE,
3739                                             NULL, EINA_FALSE, EINA_FALSE, 0, 0,
3740                                             EINA_FALSE, NULL, &nomul, NULL);
3741 
3742    _filter_data_flush(gc, prog);
3743    EINA_SAFETY_ON_NULL_RETURN(prog);
3744 
3745    pn = _evas_gl_common_context_push(type, gc, tex, NULL, prog,
3746                                      x, y, w, h, blend, smooth,
3747                                      0, 0, 0, 0, 0, EINA_FALSE);
3748 
3749    if (gc->pipe[pn].array.num == 0)
3750      {
3751         gc->pipe[pn].region.type = type;
3752         gc->pipe[pn].shader.prog = prog;
3753         gc->pipe[pn].shader.cur_tex = tex->pt->texture;
3754         gc->pipe[pn].shader.cur_texm = 0;
3755         gc->pipe[pn].shader.tex_target = GL_TEXTURE_2D;
3756         gc->pipe[pn].shader.smooth = smooth;
3757         gc->pipe[pn].shader.mask_smooth = 0;
3758         gc->pipe[pn].shader.blend = blend;
3759         gc->pipe[pn].shader.render_op = gc->dc->render_op;
3760         gc->pipe[pn].shader.clip = 0;
3761         gc->pipe[pn].shader.cx = 0;
3762         gc->pipe[pn].shader.cy = 0;
3763         gc->pipe[pn].shader.cw = 0;
3764         gc->pipe[pn].shader.ch = 0;
3765         gc->pipe[pn].array.line = 0;
3766         gc->pipe[pn].array.use_vertex = 1;
3767         gc->pipe[pn].array.use_color = !nomul;
3768         gc->pipe[pn].array.use_texuv = 1;
3769         gc->pipe[pn].array.use_texuv2 = 0;
3770         gc->pipe[pn].array.use_texuv3 = 0;
3771         gc->pipe[pn].array.use_texsam = 0;
3772         gc->pipe[pn].array.use_mask = 0;
3773         gc->pipe[pn].array.use_masksam = 0;
3774      }
3775 
3776    pipe_region_expand(gc, pn, x, y, w, h);
3777    PIPE_GROW(gc, pn, 6);
3778 
3779    _filter_data_alloc(gc, pn, 0);
3780 
3781    pw = tex->pt->w;
3782    ph = tex->pt->h;
3783 
3784    ox1 = x;
3785    oy1 = y;
3786    ox2 = x + w;
3787    oy2 = y;
3788    ox3 = x + w;
3789    oy3 = y + h;
3790    ox4 = x;
3791    oy4 = y + h;
3792 
3793    offsetx = tex->x;
3794    offsety = tex->y;
3795 
3796    tx1 = ((double)(offsetx) + ox1) / pw;
3797    ty1 = ((double)(offsety) + oy1) / ph;
3798    tx2 = ((double)(offsetx) + ox2) / pw;
3799    ty2 = ((double)(offsety) + oy2) / ph;
3800    tx3 = ((double)(offsetx) + ox3) / pw;
3801    ty3 = ((double)(offsety) + oy3) / ph;
3802    tx4 = ((double)(offsetx) + ox4) / pw;
3803    ty4 = ((double)(offsety) + oy4) / ph;
3804 
3805    PUSH_6_VERTICES(pn, x, y, w, h);
3806    PUSH_6_QUAD(pn, tx1, ty1, tx2, ty2, tx3, ty3, tx4, ty4);
3807 
3808    if (!nomul)
3809      PUSH_6_COLORS(pn, r, g, b, a);
3810 }
3811 
3812 void
evas_gl_common_filter_inverse_color_push(Evas_Engine_GL_Context * gc,Evas_GL_Texture * tex,int x,int y,int w,int h)3813 evas_gl_common_filter_inverse_color_push(Evas_Engine_GL_Context *gc,
3814                                          Evas_GL_Texture *tex,
3815                                          int x, int y, int w, int h)
3816 {
3817    double ox1, oy1, ox2, oy2, ox3, oy3, ox4, oy4, pw, ph;
3818    GLfloat tx1, ty1, tx2, ty2, tx3, ty3, tx4, ty4;
3819    GLfloat offsetx, offsety;
3820    int r, g, b, a, nomul = 0, pn;
3821    Evas_GL_Program *prog;
3822    Eina_Bool blend = EINA_TRUE;
3823    Eina_Bool smooth = EINA_TRUE;
3824    Shader_Type type = SHD_FILTER_INVERSE_COLOR;
3825 
3826    r = R_VAL(&gc->dc->mul.col);
3827    g = G_VAL(&gc->dc->mul.col);
3828    b = B_VAL(&gc->dc->mul.col);
3829    a = A_VAL(&gc->dc->mul.col);
3830    if (gc->dc->render_op == EVAS_RENDER_COPY)
3831      blend = EINA_FALSE;
3832 
3833    prog = evas_gl_common_shader_program_get(gc, type, NULL, 0, r, g, b, a,
3834                                             w, h, w, h, smooth, tex, EINA_FALSE,
3835                                             NULL, EINA_FALSE, EINA_FALSE, 0, 0,
3836                                             EINA_FALSE, NULL, &nomul, NULL);
3837 
3838    _filter_data_flush(gc, prog);
3839    EINA_SAFETY_ON_NULL_RETURN(prog);
3840 
3841    pn = _evas_gl_common_context_push(type, gc, tex, NULL, prog,
3842                                      x, y, w, h, blend, smooth,
3843                                      0, 0, 0, 0, 0, EINA_FALSE);
3844 
3845    if (gc->pipe[pn].array.num == 0)
3846      {
3847         gc->pipe[pn].region.type = type;
3848         gc->pipe[pn].shader.prog = prog;
3849         gc->pipe[pn].shader.cur_tex = tex->pt->texture;
3850         gc->pipe[pn].shader.cur_texm = 0;
3851         gc->pipe[pn].shader.tex_target = GL_TEXTURE_2D;
3852         gc->pipe[pn].shader.smooth = smooth;
3853         gc->pipe[pn].shader.mask_smooth = 0;
3854         gc->pipe[pn].shader.blend = blend;
3855         gc->pipe[pn].shader.render_op = gc->dc->render_op;
3856         gc->pipe[pn].shader.clip = 0;
3857         gc->pipe[pn].shader.cx = 0;
3858         gc->pipe[pn].shader.cy = 0;
3859         gc->pipe[pn].shader.cw = 0;
3860         gc->pipe[pn].shader.ch = 0;
3861         gc->pipe[pn].array.line = 0;
3862         gc->pipe[pn].array.use_vertex = 1;
3863         gc->pipe[pn].array.use_color = !nomul;
3864         gc->pipe[pn].array.use_texuv = 1;
3865         gc->pipe[pn].array.use_texuv2 = 0;
3866         gc->pipe[pn].array.use_texuv3 = 0;
3867         gc->pipe[pn].array.use_texsam = 0;
3868         gc->pipe[pn].array.use_mask = 0;
3869         gc->pipe[pn].array.use_masksam = 0;
3870      }
3871 
3872    pipe_region_expand(gc, pn, x, y, w, h);
3873    PIPE_GROW(gc, pn, 6);
3874 
3875    _filter_data_alloc(gc, pn, 0);
3876 
3877    pw = tex->pt->w;
3878    ph = tex->pt->h;
3879 
3880    ox1 = x;
3881    oy1 = y;
3882    ox2 = x + w;
3883    oy2 = y;
3884    ox3 = x + w;
3885    oy3 = y + h;
3886    ox4 = x;
3887    oy4 = y + h;
3888 
3889    offsetx = tex->x;
3890    offsety = tex->y;
3891 
3892    tx1 = ((double)(offsetx) + ox1) / pw;
3893    ty1 = ((double)(offsety) + oy1) / ph;
3894    tx2 = ((double)(offsetx) + ox2) / pw;
3895    ty2 = ((double)(offsety) + oy2) / ph;
3896    tx3 = ((double)(offsetx) + ox3) / pw;
3897    ty3 = ((double)(offsety) + oy3) / ph;
3898    tx4 = ((double)(offsetx) + ox4) / pw;
3899    ty4 = ((double)(offsety) + oy4) / ph;
3900 
3901    PUSH_6_VERTICES(pn, x, y, w, h);
3902    PUSH_6_QUAD(pn, tx1, ty1, tx2, ty2, tx3, ty3, tx4, ty4);
3903 
3904    if (!nomul)
3905      PUSH_6_COLORS(pn, r, g, b, a);
3906 }
3907 // ----------------------------------------------------------------------------
3908 
3909 EAPI void
evas_gl_common_context_flush(Evas_Engine_GL_Context * gc)3910 evas_gl_common_context_flush(Evas_Engine_GL_Context *gc)
3911 {
3912    shader_array_flush(gc);
3913 }
3914 
3915 static void
scissor_rot(Evas_Engine_GL_Context * gc EINA_UNUSED,int rot,int gw,int gh,int cx,int cy,int cw,int ch)3916 scissor_rot(Evas_Engine_GL_Context *gc EINA_UNUSED,
3917             int rot, int gw, int gh, int cx, int cy, int cw, int ch)
3918 {
3919    switch (rot)
3920      {
3921       case 0: // UP this way: ^
3922         glScissor(cx, cy, cw, ch);
3923         break;
3924       case 90: // UP this way: <
3925         glScissor(gh - (cy + ch), cx, ch, cw);
3926         break;
3927       case 180: // UP this way: v
3928         glScissor(gw - (cx + cw), gh - (cy + ch), cw, ch);
3929         break;
3930       case 270: // UP this way: >
3931         glScissor(cy, gw - (cx + cw), ch, cw);
3932         break;
3933       default: // assume up is up
3934         glScissor(cx, cy, cw, ch);
3935         break;
3936      }
3937 }
3938 
3939 static void
start_tiling(Evas_Engine_GL_Context * gc EINA_UNUSED,int rot,int gw,int gh,int cx,int cy,int cw,int ch,int bitmask)3940 start_tiling(Evas_Engine_GL_Context *gc EINA_UNUSED,
3941              int rot, int gw, int gh, int cx, int cy, int cw, int ch,
3942              int bitmask)
3943 {
3944    if (!glsym_glStartTiling) return;
3945    switch (rot)
3946      {
3947       case 0: // UP this way: ^
3948         glsym_glStartTiling(cx, cy, cw, ch, bitmask);
3949         break;
3950       case 90: // UP this way: <
3951         glsym_glStartTiling(gh - (cy + ch), cx, ch, cw, bitmask);
3952         break;
3953       case 180: // UP this way: v
3954         glsym_glStartTiling(gw - (cx + cw), gh - (cy + ch), cw, ch, bitmask);
3955         break;
3956       case 270: // UP this way: >
3957         glsym_glStartTiling(cy, gw - (cx + cw), ch, cw, bitmask);
3958         break;
3959       default: // assume up is up
3960         glsym_glStartTiling(cx, cy, cw, ch, bitmask);
3961         break;
3962      }
3963    GLERRV("glsym_glStartTiling");
3964 }
3965 
3966 static void
shader_array_flush(Evas_Engine_GL_Context * gc)3967 shader_array_flush(Evas_Engine_GL_Context *gc)
3968 {
3969    int i, gw, gh, offx = 0, offy = 0;
3970    unsigned int pipe_done = 0;  //count pipe iteration for debugging
3971    Eina_Bool setclip;
3972    Eina_Bool fbo = EINA_FALSE;
3973 
3974    if (!gc->havestuff) return;
3975    gw = gc->w;
3976    gh = gc->h;
3977    if (!((gc->pipe[0].shader.surface == gc->def_surface) ||
3978          (!gc->pipe[0].shader.surface)))
3979      {
3980         gw = gc->pipe[0].shader.surface->w;
3981         gh = gc->pipe[0].shader.surface->h;
3982         fbo = EINA_TRUE;
3983         offx = gc->pipe[0].shader.surface->tex->x;
3984         offy = gc->pipe[0].shader.surface->tex->y;
3985      }
3986    for (i = 0; i < gc->shared->info.tune.pipes.max; i++)
3987      {
3988         Evas_GL_Program *prog;
3989 
3990         if (gc->pipe[i].array.num <= 0) break;
3991 
3992         prog = gc->pipe[i].shader.prog;
3993         setclip = EINA_FALSE;
3994         pipe_done++;
3995         gc->flushnum++;
3996 
3997         if (prog != gc->state.current.prog)
3998           {
3999              glUseProgram(prog->prog);
4000              if (prog->reset)
4001                {
4002                   glUniform1i(prog->uniform.rotation_id, fbo ? 0 : gc->rot / 90);
4003                   glUniformMatrix4fv(prog->uniform.mvp, 1, GL_FALSE, gc->shared->proj);
4004                   prog->reset = EINA_FALSE;
4005                }
4006           }
4007 
4008         if (gc->pipe[i].shader.cur_tex != gc->state.current.cur_tex)
4009           {
4010 #if 0
4011              if (gc->pipe[i].shader.cur_tex)
4012                {
4013                   glEnable(GL_TEXTURE_2D);
4014                }
4015              else
4016                {
4017                   glDisable(GL_TEXTURE_2D);
4018                }
4019 #endif
4020              glActiveTexture(GL_TEXTURE0);
4021              glBindTexture(gc->pipe[i].shader.tex_target, gc->pipe[i].shader.cur_tex);
4022           }
4023         if (gc->pipe[i].array.im)
4024           {
4025 #ifdef GL_GLES
4026              if (gc->pipe[i].array.im->tex->pt->dyn.img)
4027                {
4028                   secsym_glEGLImageTargetTexture2DOES
4029                         (gc->pipe[i].array.im->tex->pt->dyn.target, gc->pipe[i].array.im->tex->pt->dyn.img);
4030                }
4031              else
4032 #endif
4033                {
4034                   if (!gc->pipe[i].array.im->native.loose)
4035                     {
4036                        if (gc->pipe[i].array.im->native.func.bind)
4037                          gc->pipe[i].array.im->native.func.bind(gc->pipe[i].array.im);
4038                     }
4039                }
4040           }
4041         if ((gc->pipe[i].shader.render_op != gc->state.current.render_op) ||
4042             gc->state.current.anti_alias)
4043           {
4044              switch (gc->pipe[i].shader.render_op)
4045                {
4046                 case EVAS_RENDER_BLEND: /**< default op: d = d*(1-sa) + s */
4047                   glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
4048                   break;
4049                 case EVAS_RENDER_BLEND_REL: /**< d = d*(1 - sa) + s*da */
4050                   glBlendFunc(GL_DST_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
4051                   break;
4052                 case EVAS_RENDER_COPY: /**< d = s */
4053                   gc->pipe[i].shader.blend = 0;
4054                   // just disable blend mode. no need to set blend func
4055                   //glBlendFunc(GL_ONE, GL_ZERO);
4056                   break;
4057                 case EVAS_RENDER_COPY_REL: /**< d = s*da */
4058                   glBlendFunc(GL_DST_ALPHA, GL_ZERO);
4059                   break;
4060                 case EVAS_RENDER_ADD: /**< d = d + s */
4061                   glBlendFunc(GL_ONE, GL_ONE);
4062                   break;
4063                 case EVAS_RENDER_ADD_REL: /**< d = d + s*da */
4064                   glBlendFunc(GL_DST_ALPHA, GL_ONE);
4065                   break;
4066                 case EVAS_RENDER_SUB: /**< d = d - s */
4067                   glBlendFunc(GL_ZERO, GL_ONE_MINUS_SRC_COLOR);
4068                   break;
4069                 case EVAS_RENDER_SUB_REL: /**< d = d - s*da */
4070                   glBlendFunc(GL_ZERO, GL_ONE_MINUS_DST_ALPHA);
4071                   break;
4072                 case EVAS_RENDER_MASK: /**< d = d*sa */
4073                   glBlendFunc(GL_ZERO, GL_SRC_ALPHA);
4074                   break;
4075                   // FIXME: fix blend funcs below!
4076                 case EVAS_RENDER_TINT: /**< d = d*s + d*(1 - sa) + s*(1 - da) */
4077                 case EVAS_RENDER_TINT_REL: /**< d = d*(1 - sa + s) */
4078                 case EVAS_RENDER_MUL: /**< d = d*s */
4079                 default:
4080                   glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
4081                   break;
4082                }
4083           }
4084         if (gc->pipe[i].shader.blend != gc->state.current.blend)
4085           {
4086              if (gc->pipe[i].shader.blend)
4087                glEnable(GL_BLEND);
4088              else
4089                glDisable(GL_BLEND);
4090           }
4091         if ((gc->pipe[i].shader.smooth != gc->state.current.smooth) ||
4092             (gc->pipe[i].shader.cur_tex != gc->state.current.cur_tex))
4093           {
4094              if (gc->pipe[i].shader.smooth)
4095                {
4096 #ifdef GL_TEXTURE_MAX_ANISOTROPY_EXT
4097                   if (shared->info.anisotropic > 0.0)
4098                     glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, shared->info.anisotropic);
4099 #endif
4100                   glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
4101                   glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
4102                   glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
4103                   glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
4104                }
4105              else
4106                {
4107 #ifdef GL_TEXTURE_MAX_ANISOTROPY_EXT
4108                   if (shared->info.anisotropic > 0.0)
4109                     glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, 1.0);
4110 #endif
4111                   glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
4112                   glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
4113                   glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
4114                   glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
4115                }
4116           }
4117         if (gc->pipe[i].shader.clip != gc->state.current.clip)
4118           {
4119              int cx, cy, cw, ch;
4120 
4121              cx = gc->pipe[i].shader.cx;
4122              cy = gc->pipe[i].shader.cy;
4123              cw = gc->pipe[i].shader.cw;
4124              ch = gc->pipe[i].shader.ch;
4125              if ((gc->master_clip.enabled) && (!fbo))
4126                {
4127                   if (gc->pipe[i].shader.clip)
4128                     {
4129                        RECTS_CLIP_TO_RECT(cx, cy, cw, ch,
4130                                           gc->master_clip.x, gc->master_clip.y,
4131                                           gc->master_clip.w, gc->master_clip.h);
4132                     }
4133                   else
4134                     {
4135                        cx = gc->master_clip.x;
4136                        cy = gc->master_clip.y;
4137                        cw = gc->master_clip.w;
4138                        ch = gc->master_clip.h;
4139                     }
4140                }
4141              if ((glsym_glStartTiling) && (glsym_glEndTiling) &&
4142                  (gc->master_clip.enabled) &&
4143                  (gc->master_clip.w > 0) && (gc->master_clip.h > 0))
4144                {
4145                   if (!gc->master_clip.used)
4146                     {
4147                        if (!fbo)
4148                          {
4149                             start_tiling(gc, gc->rot, gw, gh,
4150                                          gc->master_clip.x + offx,
4151                                          gh - gc->master_clip.y - offy - gc->master_clip.h,
4152                                          gc->master_clip.w, gc->master_clip.h,
4153                                          gc->preserve_bit);
4154                             if (!gc->preserve_bit)
4155                               gc->preserve_bit = GL_COLOR_BUFFER_BIT0_QCOM;
4156                          }
4157                        else
4158                          start_tiling(gc, 0, gw, gh,
4159                                       gc->master_clip.x + offx,
4160                                       gc->master_clip.y + offy,
4161                                       gc->master_clip.w, gc->master_clip.h, 0);
4162                        gc->master_clip.used = EINA_TRUE;
4163                     }
4164                }
4165              if ((gc->pipe[i].shader.clip) ||
4166                  ((gc->master_clip.enabled) && (!fbo)))
4167                {
4168                   glEnable(GL_SCISSOR_TEST);
4169                   if (!fbo)
4170                     scissor_rot(gc, gc->rot, gw, gh,
4171                                 cx + offx,
4172                                 gh - cy - offy - ch,
4173                                 cw, ch);
4174                   else
4175                      glScissor(cx + offx, cy + offy, cw, ch);
4176                   setclip = EINA_TRUE;
4177                   gc->state.current.cx = cx;
4178                   gc->state.current.cy = cy;
4179                   gc->state.current.cw = cw;
4180                   gc->state.current.ch = ch;
4181                }
4182              else
4183                {
4184                   glDisable(GL_SCISSOR_TEST);
4185                   glScissor(0, 0, 0, 0);
4186                   gc->state.current.cx = 0;
4187                   gc->state.current.cy = 0;
4188                   gc->state.current.cw = 0;
4189                   gc->state.current.ch = 0;
4190                }
4191           }
4192         if (((gc->pipe[i].shader.clip) && (!setclip)) ||
4193             ((gc->master_clip.enabled) && (!fbo)))
4194           {
4195              int cx, cy, cw, ch;
4196 
4197              cx = gc->pipe[i].shader.cx;
4198              cy = gc->pipe[i].shader.cy;
4199              cw = gc->pipe[i].shader.cw;
4200              ch = gc->pipe[i].shader.ch;
4201              if ((gc->master_clip.enabled) && (!fbo))
4202                {
4203                   if (gc->pipe[i].shader.clip)
4204                     {
4205                        RECTS_CLIP_TO_RECT(cx, cy, cw, ch,
4206                                           gc->master_clip.x, gc->master_clip.y,
4207                                           gc->master_clip.w, gc->master_clip.h);
4208                     }
4209                   else
4210                     {
4211                        cx = gc->master_clip.x;
4212                        cy = gc->master_clip.y;
4213                        cw = gc->master_clip.w;
4214                        ch = gc->master_clip.h;
4215                     }
4216                }
4217              if ((cx != gc->state.current.cx) ||
4218                  (cy != gc->state.current.cy) ||
4219                  (cw != gc->state.current.cw) ||
4220                  (ch != gc->state.current.ch))
4221                {
4222                   if (!fbo)
4223                     scissor_rot(gc, gc->rot, gw, gh,
4224                                 cx + offx,
4225                                 gh - cy - offy - ch,
4226                                 cw, ch);
4227                   else
4228                     glScissor(cx, cy, cw, ch);
4229                   gc->state.current.cx = cx;
4230                   gc->state.current.cy = cy;
4231                   gc->state.current.cw = cw;
4232                   gc->state.current.ch = ch;
4233                }
4234           }
4235 
4236         unsigned char *vertex_ptr = NULL;
4237         unsigned char *color_ptr = NULL;
4238         unsigned char *texuv_ptr = NULL;
4239         unsigned char *texuv2_ptr = NULL;
4240         unsigned char *texuv3_ptr = NULL;
4241         unsigned char *texa_ptr = NULL;
4242         unsigned char *texsam_ptr = NULL;
4243         unsigned char *mask_ptr = NULL;
4244         unsigned char *masksam_ptr = NULL;
4245         GLint ACTIVE_TEXTURE = GL_TEXTURE0;
4246 
4247         if (glsym_glMapBuffer && glsym_glUnmapBuffer)
4248           {
4249              unsigned char *x;
4250 
4251 # define VERTEX_SIZE (gc->pipe[i].array.num * sizeof(GLshort) * VERTEX_CNT)
4252 # define COLOR_SIZE (gc->pipe[i].array.num * sizeof(GLubyte) * COLOR_CNT)
4253 # define TEX_SIZE (gc->pipe[i].array.num * sizeof(GLfloat) * TEX_CNT)
4254 # define SAM_SIZE (gc->pipe[i].array.num * sizeof(GLfloat) * SAM_CNT)
4255 # define MASK_SIZE (gc->pipe[i].array.num * sizeof(GLfloat) * MASK_CNT)
4256              vertex_ptr = NULL;
4257              color_ptr = vertex_ptr + VERTEX_SIZE;
4258              texuv_ptr = color_ptr + COLOR_SIZE;
4259              texuv2_ptr = texuv_ptr + TEX_SIZE;
4260              texuv3_ptr = texuv2_ptr + TEX_SIZE;
4261              texa_ptr = texuv3_ptr + TEX_SIZE;
4262              texsam_ptr = texa_ptr + TEX_SIZE;
4263              mask_ptr = texsam_ptr + SAM_SIZE;
4264              masksam_ptr = mask_ptr + MASK_SIZE;
4265 # define END_POINTER (masksam_ptr + SAM_SIZE)
4266 
4267              glBindBuffer(GL_ARRAY_BUFFER, gc->pipe[i].array.buffer);
4268              if ((gc->pipe[i].array.buffer_alloc < (long)END_POINTER) ||
4269                  (gc->pipe[i].array.buffer_use >= (ARRAY_BUFFER_USE + ARRAY_BUFFER_USE_SHIFT * i)))
4270                {
4271                   glBufferData(GL_ARRAY_BUFFER, (long)END_POINTER, NULL, GL_STATIC_DRAW);
4272                   gc->pipe[i].array.buffer_alloc = (long)END_POINTER;
4273                   gc->pipe[i].array.buffer_use = 0;
4274                }
4275              gc->pipe[i].array.buffer_use++;
4276 
4277              x = glsym_glMapBuffer(GL_ARRAY_BUFFER, GL_WRITE_ONLY);
4278              if (x)
4279                {
4280                   if (gc->pipe[i].array.use_vertex)
4281                     memcpy(x + (unsigned long)vertex_ptr, gc->pipe[i].array.vertex, VERTEX_SIZE);
4282                   if (gc->pipe[i].array.use_color)
4283                     memcpy(x + (unsigned long)color_ptr, gc->pipe[i].array.color, COLOR_SIZE);
4284                   if (gc->pipe[i].array.use_texuv)
4285                     memcpy(x + (unsigned long)texuv_ptr, gc->pipe[i].array.texuv, TEX_SIZE);
4286                   if (gc->pipe[i].array.use_texuv2)
4287                     memcpy(x + (unsigned long)texuv2_ptr, gc->pipe[i].array.texuv2, TEX_SIZE);
4288                   if (gc->pipe[i].array.use_texuv3)
4289                     memcpy(x + (unsigned long)texuv3_ptr, gc->pipe[i].array.texuv3, TEX_SIZE);
4290                   if (gc->pipe[i].array.use_texa)
4291                     memcpy(x + (unsigned long)texa_ptr, gc->pipe[i].array.texa, TEX_SIZE);
4292                   if (gc->pipe[i].array.use_texsam)
4293                     memcpy(x + (unsigned long)texsam_ptr, gc->pipe[i].array.texsam, SAM_SIZE);
4294                   if (gc->pipe[i].array.use_mask)
4295                     {
4296                        memcpy(x + (unsigned long)mask_ptr, gc->pipe[i].array.mask, MASK_SIZE);
4297                        if (gc->pipe[i].array.use_masksam)
4298                          memcpy(x + (unsigned long)masksam_ptr, gc->pipe[i].array.masksam, SAM_SIZE);
4299                     }
4300                   /*
4301                   fprintf(stderr, "copy %i bytes [%i/%i slots] [%i + %i + %i + %i + %i + %i + %i] <%i %i %i %i %i %i %i>\n",
4302                           (int)((unsigned char *)END_POINTER),
4303                           gc->pipe[i].array.num,
4304                           gc->pipe[i].array.alloc,
4305                           VERTEX_SIZE, COLOR_SIZE, TEX_SIZE, TEX_SIZE, TEX_SIZE, TEX_SIZE, TEX_SIZE,
4306                           gc->pipe[i].array.use_vertex,
4307                           gc->pipe[i].array.use_color,
4308                           gc->pipe[i].array.use_texuv,
4309                           gc->pipe[i].array.use_texuv2,
4310                           gc->pipe[i].array.use_texuv3,
4311                           gc->pipe[i].array.use_texa,
4312                           gc->pipe[i].array.use_texsam,
4313                           gc->pipe[i].array.use_texm);
4314  */
4315                   glsym_glUnmapBuffer(GL_ARRAY_BUFFER);
4316                }
4317           }
4318         else
4319           {
4320              vertex_ptr = (unsigned char *)gc->pipe[i].array.vertex;
4321              color_ptr = (unsigned char *)gc->pipe[i].array.color;
4322              texuv_ptr = (unsigned char *)gc->pipe[i].array.texuv;
4323              texuv2_ptr = (unsigned char *)gc->pipe[i].array.texuv2;
4324              texuv3_ptr = (unsigned char *)gc->pipe[i].array.texuv3;
4325              texa_ptr = (unsigned char *)gc->pipe[i].array.texa;
4326              texsam_ptr = (unsigned char *)gc->pipe[i].array.texsam;
4327              mask_ptr = (unsigned char *)gc->pipe[i].array.mask;
4328              masksam_ptr = (unsigned char *)gc->pipe[i].array.masksam;
4329           }
4330 
4331         // use_vertex is always true
4332         glVertexAttribPointer(SHAD_VERTEX, VERTEX_CNT, GL_FLOAT, GL_FALSE, 0, vertex_ptr);
4333 
4334         if (gc->pipe[i].array.use_color)
4335           {
4336              glEnableVertexAttribArray(SHAD_COLOR);
4337              glVertexAttribPointer(SHAD_COLOR, COLOR_CNT, GL_UNSIGNED_BYTE, GL_TRUE, 0, color_ptr);
4338           }
4339         else
4340           glDisableVertexAttribArray(SHAD_COLOR);
4341 
4342         if (gc->pipe[i].array.line)
4343           {
4344              //LINE_SMOOTH is supported at gles 1.x spec.
4345              if ((gc->gles_version == 1) && gc->pipe[i].array.anti_alias)
4346                {
4347                   glEnable(GL_BLEND);
4348                   glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
4349                   glHint(GL_LINE_SMOOTH, GL_NICEST);
4350                   glEnable(GL_LINE_SMOOTH);
4351                }
4352              else
4353                {
4354                   glDisable(GL_LINE_SMOOTH);
4355                }
4356 
4357              glDisableVertexAttribArray(SHAD_TEXUV);
4358              glDisableVertexAttribArray(SHAD_TEXUV2);
4359              glDisableVertexAttribArray(SHAD_TEXUV3);
4360              glDisableVertexAttribArray(SHAD_TEXA);
4361              glDisableVertexAttribArray(SHAD_TEXSAM);
4362 
4363              /* kopi pasta from below */
4364              if (gc->pipe[i].array.use_mask)
4365                {
4366                   glEnableVertexAttribArray(SHAD_MASK);
4367                   glVertexAttribPointer(SHAD_MASK, MASK_CNT, GL_FLOAT, GL_FALSE, 0, mask_ptr);
4368                   glActiveTexture(ACTIVE_TEXTURE);
4369                   glBindTexture(GL_TEXTURE_2D, gc->pipe[i].shader.cur_texm);
4370 #ifdef GL_TEXTURE_MAX_ANISOTROPY_EXT
4371                   if (shared->info.anisotropic > 0.0)
4372                     glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, shared->info.anisotropic);
4373 #endif
4374                   if (gc->pipe[i].shader.mask_smooth)
4375                     {
4376                        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
4377                        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
4378                     }
4379                   else
4380                     {
4381                        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
4382                        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
4383                     }
4384                   glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
4385                   glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
4386                   glActiveTexture(GL_TEXTURE0);
4387 
4388                   if (gc->pipe[i].array.use_masksam)
4389                     {
4390                        glEnableVertexAttribArray(SHAD_MASKSAM);
4391                        glVertexAttribPointer(SHAD_MASKSAM, SAM_CNT, GL_FLOAT, GL_FALSE, 0, masksam_ptr);
4392                     }
4393                   else glDisableVertexAttribArray(SHAD_MASKSAM);
4394                }
4395              else
4396                {
4397                   glDisableVertexAttribArray(SHAD_MASK);
4398                   glDisableVertexAttribArray(SHAD_MASKSAM);
4399                }
4400 
4401              glDrawArrays(GL_LINES, 0, gc->pipe[i].array.num);
4402           }
4403         else
4404           {
4405              if (gc->pipe[i].array.use_texuv)
4406                {
4407                   glEnableVertexAttribArray(SHAD_TEXUV);
4408                   glVertexAttribPointer(SHAD_TEXUV, TEX_CNT, GL_FLOAT, GL_FALSE, 0, texuv_ptr);
4409 
4410                   ACTIVE_TEXTURE += 1;
4411                }
4412              else
4413                {
4414                   glDisableVertexAttribArray(SHAD_TEXUV);
4415                }
4416 
4417              /* Alpha plane */
4418              if (gc->pipe[i].array.use_texa)
4419                {
4420                   glEnableVertexAttribArray(SHAD_TEXA);
4421                   glVertexAttribPointer(SHAD_TEXA, TEX_CNT, GL_FLOAT, GL_FALSE, 0, texa_ptr);
4422                   glActiveTexture(GL_TEXTURE1);
4423                   glBindTexture(GL_TEXTURE_2D, gc->pipe[i].shader.cur_texa);
4424 #ifdef GL_TEXTURE_MAX_ANISOTROPY_EXT
4425                   if (shared->info.anisotropic > 0.0)
4426                     glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, shared->info.anisotropic);
4427 #endif
4428                   if (gc->pipe[i].shader.smooth)
4429                     {
4430                        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
4431                        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
4432                     }
4433                   else
4434                     {
4435                        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
4436                        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
4437                     }
4438                   glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
4439                   glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
4440                   glActiveTexture(GL_TEXTURE0);
4441 
4442                   ACTIVE_TEXTURE += 1;
4443                }
4444              else
4445                {
4446                   glDisableVertexAttribArray(SHAD_TEXA);
4447                }
4448 
4449              if (gc->pipe[i].array.use_texsam)
4450                {
4451                   glEnableVertexAttribArray(SHAD_TEXSAM);
4452                   glVertexAttribPointer(SHAD_TEXSAM, SAM_CNT, GL_FLOAT, GL_FALSE, 0, texsam_ptr);
4453                }
4454              else
4455                {
4456                   glDisableVertexAttribArray(SHAD_TEXSAM);
4457                }
4458 
4459              if ((gc->pipe[i].array.use_texuv2) && (gc->pipe[i].array.use_texuv3))
4460                {
4461                   glEnableVertexAttribArray(SHAD_TEXUV2);
4462                   glEnableVertexAttribArray(SHAD_TEXUV3);
4463                   glVertexAttribPointer(SHAD_TEXUV2, TEX_CNT, GL_FLOAT, GL_FALSE, 0, texuv2_ptr);
4464                   glVertexAttribPointer(SHAD_TEXUV3, TEX_CNT, GL_FLOAT, GL_FALSE, 0, texuv3_ptr);
4465 
4466                   glActiveTexture(GL_TEXTURE1);
4467                   glBindTexture(GL_TEXTURE_2D, gc->pipe[i].shader.cur_texu);
4468 #ifdef GL_GLES
4469                   if (gc->pipe[i].shader.cur_texu_dyn)
4470                     secsym_glEGLImageTargetTexture2DOES(GL_TEXTURE_2D, gc->pipe[i].shader.cur_texu_dyn);
4471 #endif
4472                   glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
4473                   glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
4474                   glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
4475                   glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
4476 
4477                   glActiveTexture(GL_TEXTURE2);
4478                   glBindTexture(GL_TEXTURE_2D, gc->pipe[i].shader.cur_texv);
4479 #ifdef GL_GLES
4480                   if (gc->pipe[i].shader.cur_texv_dyn)
4481                     secsym_glEGLImageTargetTexture2DOES(GL_TEXTURE_2D, gc->pipe[i].shader.cur_texv_dyn);
4482 #endif
4483                   glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
4484                   glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
4485                   glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
4486                   glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
4487                   glActiveTexture(GL_TEXTURE0);
4488 
4489                   ACTIVE_TEXTURE += 2;
4490                }
4491              else if (gc->pipe[i].array.use_texuv2)
4492                {
4493                   glEnableVertexAttribArray(SHAD_TEXUV2);
4494                   glVertexAttribPointer(SHAD_TEXUV2, TEX_CNT, GL_FLOAT, GL_FALSE, 0, texuv2_ptr);
4495 
4496                   glActiveTexture(GL_TEXTURE1);
4497                   glBindTexture(GL_TEXTURE_2D, gc->pipe[i].shader.cur_texu);
4498 #ifdef GL_GLES
4499                   if (gc->pipe[i].shader.cur_texu_dyn)
4500                     secsym_glEGLImageTargetTexture2DOES
4501                           (GL_TEXTURE_2D, gc->pipe[i].shader.cur_texu_dyn);
4502 #endif
4503                   if (gc->pipe[i].shader.smooth)
4504                     {
4505                        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
4506                        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
4507                        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
4508                        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
4509                     }
4510                   else
4511                     {
4512                        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
4513                        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
4514                        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
4515                        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
4516                     }
4517                   glActiveTexture(GL_TEXTURE0);
4518 
4519                   glDisableVertexAttribArray(SHAD_TEXUV3);
4520                   ACTIVE_TEXTURE += 1;
4521                }
4522              else
4523                {
4524                   glDisableVertexAttribArray(SHAD_TEXUV2);
4525                   glDisableVertexAttribArray(SHAD_TEXUV3);
4526                }
4527 
4528              /* Mask surface */
4529              if (gc->pipe[i].array.use_mask)
4530                {
4531                   glEnableVertexAttribArray(SHAD_MASK);
4532                   glVertexAttribPointer(SHAD_MASK, MASK_CNT, GL_FLOAT, GL_FALSE, 0, mask_ptr);
4533                   glActiveTexture(ACTIVE_TEXTURE);
4534                   glBindTexture(GL_TEXTURE_2D, gc->pipe[i].shader.cur_texm);
4535 #ifdef GL_TEXTURE_MAX_ANISOTROPY_EXT
4536                   if (shared->info.anisotropic > 0.0)
4537                     glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, shared->info.anisotropic);
4538 #endif
4539                   if (gc->pipe[i].shader.mask_smooth)
4540                     {
4541                        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
4542                        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
4543                     }
4544                   else
4545                     {
4546                        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
4547                        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
4548                     }
4549                   glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
4550                   glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
4551                   glActiveTexture(GL_TEXTURE0);
4552 
4553                   if (gc->pipe[i].array.use_masksam)
4554                     {
4555                        glEnableVertexAttribArray(SHAD_MASKSAM);
4556                        glVertexAttribPointer(SHAD_MASKSAM, SAM_CNT, GL_FLOAT, GL_FALSE, 0, masksam_ptr);
4557                     }
4558                   else glDisableVertexAttribArray(SHAD_MASKSAM);
4559                   ACTIVE_TEXTURE += 1;
4560                }
4561              else
4562                {
4563                   glDisableVertexAttribArray(SHAD_MASK);
4564                   glDisableVertexAttribArray(SHAD_MASKSAM);
4565                }
4566 
4567              /* Gfx filters: data */
4568              if (gc->pipe[i].array.filter_data)
4569                {
4570                   for (int k = 0; k < gc->pipe[i].array.filter_data_count; k++)
4571                     glVertexAttrib2fv(prog->filter->attribute.loc[k], &gc->pipe[i].array.filter_data[k * 2]);
4572                }
4573 
4574              /* Gfx filters: texture (or data array as texture) */
4575              if (gc->pipe[i].shader.filter.map_tex)
4576                {
4577                   glActiveTexture(ACTIVE_TEXTURE);
4578                   glBindTexture(GL_TEXTURE_2D, gc->pipe[i].shader.filter.map_tex);
4579                   if (gc->pipe[i].shader.filter.map_nearest)
4580                     {
4581                        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
4582                        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
4583                     }
4584                   else
4585                     {
4586                        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
4587                        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
4588                     }
4589                   glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
4590                   glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
4591                   glActiveTexture(GL_TEXTURE0);
4592                   ACTIVE_TEXTURE += 1;
4593                }
4594 
4595              if (dbgflushnum == 1)
4596                {
4597                   const char *types[] =
4598                   { "----", "RECT", "IMAG", "FONT", "YUV-", "YUY2", "NV12", "LINE", "PAIR", "EXTR", "MAP-", "FILTER_DISPLACE" };
4599                   printf("  DRAW#%3i %4i -> %p[%4ix%4i] @ %4ix%4i -{ tex %4i type %s }-\n",
4600                          i,
4601                          gc->pipe[i].array.num / 6,
4602                          gc->pipe[0].shader.surface,
4603                          gc->pipe[0].shader.surface ? gc->pipe[0].shader.surface->w : 0,
4604                          gc->pipe[0].shader.surface ? gc->pipe[0].shader.surface->h : 0,
4605                          gw, gh,
4606                          gc->pipe[i].shader.cur_tex,
4607                          types[gc->pipe[i].region.type]
4608                          );
4609                }
4610              glDrawArrays(GL_TRIANGLES, 0, gc->pipe[i].array.num);
4611           }
4612         if (gc->pipe[i].array.im)
4613           {
4614              if (!gc->pipe[i].array.im->native.loose)
4615                {
4616                   if (gc->pipe[i].array.im->native.func.unbind)
4617                     gc->pipe[i].array.im->native.func.unbind(gc->pipe[i].array.im);
4618                }
4619              gc->pipe[i].array.im = NULL;
4620           }
4621 
4622         gc->state.current.prog      = gc->pipe[i].shader.prog;
4623         gc->state.current.cur_tex   = gc->pipe[i].shader.cur_tex;
4624         gc->state.current.cur_texm  = gc->pipe[i].shader.cur_texm;
4625         gc->state.current.cur_texa  = gc->pipe[i].shader.cur_texa;
4626         gc->state.current.cur_texu  = gc->pipe[i].shader.cur_texu;
4627         gc->state.current.cur_texv  = gc->pipe[i].shader.cur_texv;
4628         gc->state.current.tex_target = gc->pipe[i].shader.tex_target;
4629         gc->state.current.render_op = gc->pipe[i].shader.render_op;
4630 //        gc->state.current.cx        = gc->pipe[i].shader.cx;
4631 //        gc->state.current.cy        = gc->pipe[i].shader.cy;
4632 //        gc->state.current.cw        = gc->pipe[i].shader.cw;
4633 //        gc->state.current.ch        = gc->pipe[i].shader.ch;
4634         gc->state.current.smooth    = gc->pipe[i].shader.smooth;
4635         gc->state.current.blend     = gc->pipe[i].shader.blend;
4636         gc->state.current.clip      = gc->pipe[i].shader.clip;
4637         gc->state.current.anti_alias = gc->pipe[i].array.anti_alias;
4638 
4639         if (gc->pipe[i].shader.filter.map_delete)
4640           {
4641              glDeleteTextures(1, &gc->pipe[i].shader.filter.map_tex);
4642              gc->pipe[i].shader.filter.map_delete = EINA_FALSE;
4643              gc->pipe[i].shader.filter.map_tex = 0;
4644           }
4645 
4646         gc->pipe[i].array.line = 0;
4647         //gc->pipe[i].array.use_vertex = 0;
4648         gc->pipe[i].array.use_color = 0;
4649         gc->pipe[i].array.use_texuv = 0;
4650         gc->pipe[i].array.use_texuv2 = 0;
4651         gc->pipe[i].array.use_texuv3 = 0;
4652         gc->pipe[i].array.use_texa = 0;
4653         gc->pipe[i].array.use_texsam = 0;
4654         gc->pipe[i].array.use_mask = 0;
4655         gc->pipe[i].array.use_masksam = 0;
4656         gc->pipe[i].array.anti_alias = 0;
4657         gc->pipe[i].array.filter_data_count = 0;
4658 
4659         PIPE_FREE(gc->pipe[i].array.vertex);
4660         PIPE_FREE(gc->pipe[i].array.color);
4661         PIPE_FREE(gc->pipe[i].array.texuv);
4662         PIPE_FREE(gc->pipe[i].array.texuv2);
4663         PIPE_FREE(gc->pipe[i].array.texuv3);
4664         PIPE_FREE(gc->pipe[i].array.texa);
4665         PIPE_FREE(gc->pipe[i].array.texsam);
4666         PIPE_FREE(gc->pipe[i].array.mask);
4667         PIPE_FREE(gc->pipe[i].array.masksam);
4668         FREE(gc->pipe[i].array.filter_data);
4669 
4670         gc->pipe[i].array.num = 0;
4671         gc->pipe[i].array.alloc = 0;
4672 
4673         if (glsym_glMapBuffer && glsym_glUnmapBuffer)
4674           {
4675              glBindBuffer(GL_ARRAY_BUFFER, 0);
4676           }
4677 
4678         gc->pipe[i].region.x = 0;
4679         gc->pipe[i].region.y = 0;
4680         gc->pipe[i].region.w = 0;
4681         gc->pipe[i].region.h = 0;
4682         gc->pipe[i].region.type = 0;
4683      }
4684    gc->state.top_pipe = 0;
4685    if (dbgflushnum == 1)
4686      {
4687         if (pipe_done > 0) printf("DONE (pipes): %i\n", pipe_done);
4688      }
4689    gc->havestuff = EINA_FALSE;
4690 }
4691 
4692 EAPI int
evas_gl_common_buffer_dump(Evas_Engine_GL_Context * gc,const char * dname,const char * buf_name,int frame,const char * suffix)4693 evas_gl_common_buffer_dump(Evas_Engine_GL_Context *gc, const char* dname, const char* buf_name, int frame, const char *suffix)
4694 {
4695    RGBA_Image *im = NULL;
4696    DATA32 *data1, *data2;
4697    char fname[100];
4698    int ok = 0;
4699 
4700    if (suffix)
4701      snprintf(fname, sizeof(fname), "./%s/win_%s-fc_%03d_%s.png", dname, buf_name, frame, suffix);
4702    else
4703      snprintf(fname, sizeof(fname), "./%s/win_%s-fc_%03d.png", dname, buf_name, frame);
4704    fname[sizeof(fname) - 1] = '\0';
4705 
4706    data1 = (DATA32 *)malloc(gc->w * gc->h * sizeof(DATA32));
4707    data2 = (DATA32 *)malloc(gc->w * gc->h * sizeof(DATA32));
4708 
4709    if ((!data1) || (!data2)) goto finish;
4710 
4711    glReadPixels(0, 0, gc->w, gc->h, GL_RGBA,
4712                 GL_UNSIGNED_BYTE, (unsigned char*)data1);
4713 
4714    // Flip the Y and change from RGBA TO BGRA
4715    int i, j;
4716    for (j = 0; j < gc->h; j++)
4717       for (i = 0; i < gc->w; i++)
4718         {
4719            DATA32 d;
4720            int idx1 = (j * gc->w) + i;
4721            int idx2 = ((gc->h - 1) - j) * gc->w + i;
4722 
4723            d = data1[idx1];
4724            data2[idx2] = ((d & 0x000000ff) << 16) +
4725               ((d & 0x00ff0000) >> 16)  +
4726               ((d & 0xff00ff00));
4727         }
4728 
4729    evas_common_convert_argb_premul(data2, gc->w * gc->h);
4730 
4731    im = (RGBA_Image*) evas_cache_image_data(evas_common_image_cache_get(),
4732                                             gc->w,
4733                                             gc->h,
4734                                             (DATA32 *)data2,
4735                                             1,
4736                                             EVAS_COLORSPACE_ARGB8888);
4737    if (im)
4738      {
4739         im->image.data = data2;
4740         if (im->image.data)
4741           {
4742              ok = evas_common_save_image_to_file(im, fname, NULL, 0, 0, NULL);
4743 
4744              if (!ok) ERR("Error Saving file.");
4745           }
4746 
4747         evas_cache_image_drop(&im->cache_entry);
4748      }
4749 
4750 finish:
4751    if (data1) free(data1);
4752    if (data2) free(data2);
4753    if (im)  evas_cache_image_drop(&im->cache_entry);
4754 
4755    if (ok) return 1;
4756    else return 0;
4757 }
4758 
4759 Eina_Bool
evas_gl_common_module_open(void)4760 evas_gl_common_module_open(void)
4761 {
4762    if (_evas_engine_GL_common_log_dom < 0)
4763      _evas_engine_GL_common_log_dom = eina_log_domain_register
4764        ("evas-gl_common", EVAS_DEFAULT_LOG_COLOR);
4765    if (_evas_engine_GL_common_log_dom < 0)
4766      {
4767         EINA_LOG_ERR("Can not create a module log domain.");
4768         return EINA_FALSE;
4769      }
4770    return EINA_TRUE;
4771 }
4772 
4773 void
evas_gl_common_module_close(void)4774 evas_gl_common_module_close(void)
4775 {
4776    if (_evas_engine_GL_common_log_dom < 0) return;
4777    eina_log_domain_unregister(_evas_engine_GL_common_log_dom);
4778    _evas_engine_GL_common_log_dom = -1;
4779 }
4780