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