summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorCedric Bail <cedric.bail@samsung.com>2013-06-24 11:41:32 +0900
committerCedric Bail <cedric.bail@samsung.com>2013-06-24 12:04:18 +0900
commitd06a0982ef3d156059b2264d4494e036cbe409ee (patch)
tree2895f26d9a65fd81045601505d650b8e2034b79a /src
parent8e3d94d66130f16cec0d518a0ad6ec5fae04fec9 (diff)
evas: add support for asynchronously uploading GL texture.
NOTE: when using Evas_Object image preload infrastructure the GL texture upload was uploaded from the main loop during the rendering stage. This could lead to some frame drop during fast animation due to the time needed to upload that texture. This patch fix this problem by uploading a small texture quickly (16x16) and waiting for going back to the main loop to be able to use the same GL context from another thread to do the texture upload asynchronously without blocking the main loop.
Diffstat (limited to 'src')
-rw-r--r--src/Makefile_Evas.am1
-rw-r--r--src/lib/evas/cache/evas_cache_image.c1
-rw-r--r--src/lib/evas/include/evas_common_private.h2
-rw-r--r--src/modules/evas/engines/gl_common/evas_gl_common.h40
-rw-r--r--src/modules/evas/engines/gl_common/evas_gl_context.c54
-rw-r--r--src/modules/evas/engines/gl_common/evas_gl_core.c1
-rw-r--r--src/modules/evas/engines/gl_common/evas_gl_image.c5
-rw-r--r--src/modules/evas/engines/gl_common/evas_gl_preload.c441
-rw-r--r--src/modules/evas/engines/gl_common/evas_gl_texture.c111
-rw-r--r--src/modules/evas/engines/gl_x11/evas_engine.c72
-rw-r--r--src/modules/evas/engines/gl_x11/evas_x_main.c46
11 files changed, 736 insertions, 38 deletions
diff --git a/src/Makefile_Evas.am b/src/Makefile_Evas.am
index 7cc9433e06..d4fe9aabab 100644
--- a/src/Makefile_Evas.am
+++ b/src/Makefile_Evas.am
@@ -438,6 +438,7 @@ modules/evas/engines/gl_common/evas_gl_file_cache.c \
438modules/evas/engines/gl_common/evas_gl_shader.c \ 438modules/evas/engines/gl_common/evas_gl_shader.c \
439modules/evas/engines/gl_common/evas_gl_rectangle.c \ 439modules/evas/engines/gl_common/evas_gl_rectangle.c \
440modules/evas/engines/gl_common/evas_gl_texture.c \ 440modules/evas/engines/gl_common/evas_gl_texture.c \
441modules/evas/engines/gl_common/evas_gl_preload.c \
441modules/evas/engines/gl_common/evas_gl_image.c \ 442modules/evas/engines/gl_common/evas_gl_image.c \
442modules/evas/engines/gl_common/evas_gl_font.c \ 443modules/evas/engines/gl_common/evas_gl_font.c \
443modules/evas/engines/gl_common/evas_gl_polygon.c \ 444modules/evas/engines/gl_common/evas_gl_polygon.c \
diff --git a/src/lib/evas/cache/evas_cache_image.c b/src/lib/evas/cache/evas_cache_image.c
index fe779a57f1..06d74def49 100644
--- a/src/lib/evas/cache/evas_cache_image.c
+++ b/src/lib/evas/cache/evas_cache_image.c
@@ -396,6 +396,7 @@ _evas_cache_image_async_end(void *data)
396 ie->cache->pending = eina_list_remove(ie->cache->pending, ie); 396 ie->cache->pending = eina_list_remove(ie->cache->pending, ie);
397 ie->preload = NULL; 397 ie->preload = NULL;
398 ie->flags.preload_done = ie->flags.loaded; 398 ie->flags.preload_done = ie->flags.loaded;
399 ie->flags.updated_data = 1;
399 while ((tmp = ie->targets)) 400 while ((tmp = ie->targets))
400 { 401 {
401 evas_object_inform_call_image_preloaded((Evas_Object*) tmp->target); 402 evas_object_inform_call_image_preloaded((Evas_Object*) tmp->target);
diff --git a/src/lib/evas/include/evas_common_private.h b/src/lib/evas/include/evas_common_private.h
index 1a3c10c086..f051a72a0a 100644
--- a/src/lib/evas/include/evas_common_private.h
+++ b/src/lib/evas/include/evas_common_private.h
@@ -519,6 +519,8 @@ struct _Image_Entry_Flags
519 Eina_Bool rotated : 1; 519 Eina_Bool rotated : 1;
520 Eina_Bool unload_cancel : 1; 520 Eina_Bool unload_cancel : 1;
521 Eina_Bool given_mmap : 1; 521 Eina_Bool given_mmap : 1;
522
523 Eina_Bool updated_data : 1;
522}; 524};
523 525
524struct _Image_Entry_Frame 526struct _Image_Entry_Frame
diff --git a/src/modules/evas/engines/gl_common/evas_gl_common.h b/src/modules/evas/engines/gl_common/evas_gl_common.h
index 8dc08ae37f..f0f3bd1593 100644
--- a/src/modules/evas/engines/gl_common/evas_gl_common.h
+++ b/src/modules/evas/engines/gl_common/evas_gl_common.h
@@ -162,6 +162,8 @@
162#define GL_MULTISAMPLE_BUFFER_BIT7_QCOM 0x80000000 162#define GL_MULTISAMPLE_BUFFER_BIT7_QCOM 0x80000000
163#endif 163#endif
164 164
165#define EVAS_GL_TILE_SIZE 16
166
165#define SHAD_VERTEX 0 167#define SHAD_VERTEX 0
166#define SHAD_COLOR 1 168#define SHAD_COLOR 1
167#define SHAD_TEXUV 2 169#define SHAD_TEXUV 2
@@ -181,6 +183,9 @@ typedef struct _Evas_GL_Image Evas_GL_Image;
181typedef struct _Evas_GL_Font_Texture Evas_GL_Font_Texture; 183typedef struct _Evas_GL_Font_Texture Evas_GL_Font_Texture;
182typedef struct _Evas_GL_Polygon Evas_GL_Polygon; 184typedef struct _Evas_GL_Polygon Evas_GL_Polygon;
183typedef struct _Evas_GL_Polygon_Point Evas_GL_Polygon_Point; 185typedef struct _Evas_GL_Polygon_Point Evas_GL_Polygon_Point;
186typedef struct _Evas_GL_Texture_Async_Preload Evas_GL_Texture_Async_Preload;
187
188typedef Eina_Bool (*evas_gl_make_current_cb)(void *engine_data, void *doit);
184 189
185typedef enum { 190typedef enum {
186 SHADER_RECT, 191 SHADER_RECT,
@@ -494,6 +499,7 @@ struct _Evas_GL_Texture
494 Evas_GL_Texture_Alloca *apt, *aptt; 499 Evas_GL_Texture_Alloca *apt, *aptt;
495 RGBA_Font_Glyph *fglyph; 500 RGBA_Font_Glyph *fglyph;
496 int x, y, w, h; 501 int x, y, w, h;
502 int tx, ty;
497 double sx1, sy1, sx2, sy2; 503 double sx1, sy1, sx2, sy2;
498 int references; 504 int references;
499 505
@@ -503,8 +509,12 @@ struct _Evas_GL_Texture
503 int source; 509 int source;
504 } double_buffer; 510 } double_buffer;
505 511
512 Eina_List *targets;
513
506 Eina_Bool alpha : 1; 514 Eina_Bool alpha : 1;
507 Eina_Bool dyn : 1; 515 Eina_Bool dyn : 1;
516 Eina_Bool uploaded : 1;
517 Eina_Bool was_preloaded : 1;
508}; 518};
509 519
510struct _Evas_GL_Image 520struct _Evas_GL_Image
@@ -540,6 +550,7 @@ struct _Evas_GL_Image
540 int csize; 550 int csize;
541 551
542 Eina_List *filtered; 552 Eina_List *filtered;
553 Eina_List *targets;
543 554
544 unsigned char dirty : 1; 555 unsigned char dirty : 1;
545 unsigned char cached : 1; 556 unsigned char cached : 1;
@@ -563,6 +574,14 @@ struct _Evas_GL_Polygon_Point
563 int x, y; 574 int x, y;
564}; 575};
565 576
577struct _Evas_GL_Texture_Async_Preload
578{
579 Evas_GL_Texture *tex;
580 RGBA_Image *im;
581
582 Eina_Bool unpack_row_length;
583};
584
566#if 0 585#if 0
567extern Evas_GL_Program_Source shader_rect_frag_src; 586extern Evas_GL_Program_Source shader_rect_frag_src;
568extern Evas_GL_Program_Source shader_rect_vert_src; 587extern Evas_GL_Program_Source shader_rect_vert_src;
@@ -748,7 +767,19 @@ extern unsigned int (*secsym_eglUnmapImageSEC) (void *a, void *b,
748extern unsigned int (*secsym_eglGetImageAttribSEC) (void *a, void *b, int c, int *d); 767extern unsigned int (*secsym_eglGetImageAttribSEC) (void *a, void *b, int c, int *d);
749#endif 768#endif
750 769
751//#define GL_ERRORS 1 770Eina_Bool evas_gl_preload_push(Evas_GL_Texture_Async_Preload *async);
771void evas_gl_preload_pop(Evas_GL_Texture *tex);
772int evas_gl_preload_init(void);
773int evas_gl_preload_shutdown(void);
774void evas_gl_preload_render_lock(evas_gl_make_current_cb make_current, void *engine_data);
775void evas_gl_preload_render_unlock(evas_gl_make_current_cb make_current, void *engine_data);
776void evas_gl_preload_render_relax(evas_gl_make_current_cb make_current, void *engine_data);
777void evas_gl_preload_target_register(Evas_GL_Texture *tex, Eo *target);
778void evas_gl_preload_target_unregister(Evas_GL_Texture *tex, Eo *target);
779
780void pt_unref(Evas_GL_Texture_Pool *pt);
781
782#define GL_ERRORS 1
752 783
753#ifdef GL_ERRORS 784#ifdef GL_ERRORS
754# define GLERR(fn, fl, ln, op) \ 785# define GLERR(fn, fl, ln, op) \
@@ -763,4 +794,11 @@ extern unsigned int (*secsym_eglGetImageAttribSEC) (void *a, void *b,
763Eina_Bool evas_gl_common_module_open(void); 794Eina_Bool evas_gl_common_module_open(void);
764void evas_gl_common_module_close(void); 795void evas_gl_common_module_close(void);
765 796
797static inline void
798_tex_sub_2d(int x, int y, int w, int h, int fmt, int type, const void *pix)
799{
800 glTexSubImage2D(GL_TEXTURE_2D, 0, x, y, w, h, fmt, type, pix);
801 GLERR(__FUNCTION__, __FILE__, __LINE__, "");
802}
803
766#endif 804#endif
diff --git a/src/modules/evas/engines/gl_common/evas_gl_context.c b/src/modules/evas/engines/gl_common/evas_gl_context.c
index f99be54c10..1bdfac37f3 100644
--- a/src/modules/evas/engines/gl_common/evas_gl_context.c
+++ b/src/modules/evas/engines/gl_common/evas_gl_context.c
@@ -1261,8 +1261,15 @@ _evas_gl_common_context_push(int rtype,
1261 Eina_Bool clip, 1261 Eina_Bool clip,
1262 int cx, int cy, int cw, int ch) 1262 int cx, int cy, int cw, int ch)
1263{ 1263{
1264 GLuint current_tex = 0;
1265 GLuint current_texm = 0;
1264 int pn = 0; 1266 int pn = 0;
1265 1267
1268 if (tex)
1269 current_tex = tex->ptt ? tex->ptt->texture : tex->pt->texture;
1270 if (texm)
1271 current_texm = texm->ptt ? texm->ptt->texture : tex->pt->texture;
1272
1266#ifdef GLPIPES 1273#ifdef GLPIPES
1267 again: 1274 again:
1268#endif 1275#endif
@@ -1277,8 +1284,8 @@ _evas_gl_common_context_push(int rtype,
1277 for (i = pn; i >= 0; i--) 1284 for (i = pn; i >= 0; i--)
1278 { 1285 {
1279 if ((gc->pipe[i].region.type == rtype) 1286 if ((gc->pipe[i].region.type == rtype)
1280 && (!tex || gc->pipe[i].shader.cur_tex == tex->pt->texture) 1287 && (!tex || gc->pipe[i].shader.cur_tex == current_tex)
1281 && (!texm || gc->pipe[i].shader.cur_texm == texm->pt->texture) 1288 && (!texm || gc->pipe[i].shader.cur_texm == current_texm)
1282 && (gc->pipe[i].shader.cur_prog == prog) 1289 && (gc->pipe[i].shader.cur_prog == prog)
1283 && (gc->pipe[i].shader.smooth == smooth) 1290 && (gc->pipe[i].shader.smooth == smooth)
1284 && (gc->pipe[i].shader.blend == blend) 1291 && (gc->pipe[i].shader.blend == blend)
@@ -1318,8 +1325,8 @@ _evas_gl_common_context_push(int rtype,
1318 } 1325 }
1319#else 1326#else
1320 if (!((gc->pipe[pn].region.type == rtype) 1327 if (!((gc->pipe[pn].region.type == rtype)
1321 && (!tex || gc->pipe[pn].shader.cur_tex == tex->pt->texture) 1328 && (!tex || gc->pipe[pn].shader.cur_tex == current_tex)
1322 && (!texm || gc->pipe[pn].shader.cur_texm == texm->pt->texture) 1329 && (!texm || gc->pipe[pn].shader.cur_texm == current_texm)
1323 && (gc->pipe[pn].shader.cur_prog == prog) 1330 && (gc->pipe[pn].shader.cur_prog == prog)
1324 && (gc->pipe[pn].shader.smooth == smooth) 1331 && (gc->pipe[pn].shader.smooth == smooth)
1325 && (gc->pipe[pn].shader.blend == blend) 1332 && (gc->pipe[pn].shader.blend == blend)
@@ -1553,8 +1560,10 @@ evas_gl_common_context_image_push(Evas_Engine_GL_Context *gc,
1553 int r, int g, int b, int a, 1560 int r, int g, int b, int a,
1554 Eina_Bool smooth, Eina_Bool tex_only) 1561 Eina_Bool smooth, Eina_Bool tex_only)
1555{ 1562{
1563 Evas_GL_Texture_Pool *pt;
1556 int pnum, nv, nc, nu, ns, i; 1564 int pnum, nv, nc, nu, ns, i;
1557 GLfloat tx1, tx2, ty1, ty2; 1565 GLfloat tx1, tx2, ty1, ty2;
1566 GLfloat offsetx, offsety;
1558 Eina_Bool blend = EINA_FALSE; 1567 Eina_Bool blend = EINA_FALSE;
1559 GLuint prog = gc->shared->shader[SHADER_IMG].prog; 1568 GLuint prog = gc->shared->shader[SHADER_IMG].prog;
1560 int pn = 0, sam = 0; 1569 int pn = 0, sam = 0;
@@ -1693,6 +1702,25 @@ evas_gl_common_context_image_push(Evas_Engine_GL_Context *gc,
1693 } 1702 }
1694 } 1703 }
1695 1704
1705 if (tex->ptt)
1706 {
1707 pt = tex->ptt;
1708 offsetx = tex->tx;
1709 offsety = tex->ty;
1710
1711 // Adjusting sx, sy, sw and sh to real size of tiny texture
1712 sx = sx * (EVAS_GL_TILE_SIZE - 2) / tex->w;
1713 sw = sw * (EVAS_GL_TILE_SIZE - 2) / tex->w;
1714 sy = sy * (EVAS_GL_TILE_SIZE - 1) / tex->h;
1715 sh = sh * (EVAS_GL_TILE_SIZE - 1) / tex->h;
1716 }
1717 else
1718 {
1719 pt = tex->pt;
1720 offsetx = tex->x;
1721 offsety = tex->y;
1722 }
1723
1696 pn = _evas_gl_common_context_push(RTYPE_IMAGE, 1724 pn = _evas_gl_common_context_push(RTYPE_IMAGE,
1697 gc, tex, NULL, 1725 gc, tex, NULL,
1698 prog, 1726 prog,
@@ -1702,7 +1730,7 @@ evas_gl_common_context_image_push(Evas_Engine_GL_Context *gc,
1702 0, 0, 0, 0, 0); 1730 0, 0, 0, 0, 0);
1703 1731
1704 gc->pipe[pn].region.type = RTYPE_IMAGE; 1732 gc->pipe[pn].region.type = RTYPE_IMAGE;
1705 gc->pipe[pn].shader.cur_tex = tex->pt->texture; 1733 gc->pipe[pn].shader.cur_tex = pt->texture;
1706 gc->pipe[pn].shader.cur_prog = prog; 1734 gc->pipe[pn].shader.cur_prog = prog;
1707 gc->pipe[pn].shader.smooth = smooth; 1735 gc->pipe[pn].shader.smooth = smooth;
1708 gc->pipe[pn].shader.blend = blend; 1736 gc->pipe[pn].shader.blend = blend;
@@ -1731,17 +1759,17 @@ evas_gl_common_context_image_push(Evas_Engine_GL_Context *gc,
1731 1759
1732 if ((tex->im) && (tex->im->native.data) && (!tex->im->native.yinvert)) 1760 if ((tex->im) && (tex->im->native.data) && (!tex->im->native.yinvert))
1733 { 1761 {
1734 tx1 = ((double)(tex->x) + sx) / (double)tex->pt->w; 1762 tx1 = ((double)(offsetx) + sx) / (double)pt->w;
1735 ty1 = 1.0 - ((double)(tex->y) + sy) / (double)tex->pt->h; 1763 ty1 = 1.0 - ((double)(offsety) + sy) / (double)pt->h;
1736 tx2 = ((double)(tex->x) + sx + sw) / (double)tex->pt->w; 1764 tx2 = ((double)(offsetx) + sx + sw) / (double)pt->w;
1737 ty2 = 1.0 - ((double)(tex->y) + sy + sh) / (double)tex->pt->h; 1765 ty2 = 1.0 - ((double)(offsety) + sy + sh) / (double)pt->h;
1738 } 1766 }
1739 else 1767 else
1740 { 1768 {
1741 tx1 = ((double)(tex->x) + sx) / (double)tex->pt->w; 1769 tx1 = ((double)(offsetx) + sx) / (double)pt->w;
1742 ty1 = ((double)(tex->y) + sy) / (double)tex->pt->h; 1770 ty1 = ((double)(offsety) + sy) / (double)pt->h;
1743 tx2 = ((double)(tex->x) + sx + sw) / (double)tex->pt->w; 1771 tx2 = ((double)(offsetx) + sx + sw) / (double)pt->w;
1744 ty2 = ((double)(tex->y) + sy + sh) / (double)tex->pt->h; 1772 ty2 = ((double)(offsety) + sy + sh) / (double)pt->h;
1745 } 1773 }
1746 1774
1747 PUSH_VERTEX(pn, x , y , 0); 1775 PUSH_VERTEX(pn, x , y , 0);
diff --git a/src/modules/evas/engines/gl_common/evas_gl_core.c b/src/modules/evas/engines/gl_common/evas_gl_core.c
index 5145e0dfc8..8fadc27a27 100644
--- a/src/modules/evas/engines/gl_common/evas_gl_core.c
+++ b/src/modules/evas/engines/gl_common/evas_gl_core.c
@@ -117,7 +117,6 @@ _internal_resource_make_current(void *eng_data, EVGL_Context *ctx)
117 } 117 }
118 } 118 }
119 119
120
121 // Set context from input or from resource 120 // Set context from input or from resource
122 if (ctx) 121 if (ctx)
123 context = ctx->context; 122 context = ctx->context;
diff --git a/src/modules/evas/engines/gl_common/evas_gl_image.c b/src/modules/evas/engines/gl_common/evas_gl_image.c
index f8cdd111f8..8e721f82bc 100644
--- a/src/modules/evas/engines/gl_common/evas_gl_image.c
+++ b/src/modules/evas/engines/gl_common/evas_gl_image.c
@@ -13,7 +13,7 @@ evas_gl_common_image_all_unload(Evas_Engine_GL_Context *gc)
13 { 13 {
14 if (!im->tex->pt->dyn.img) 14 if (!im->tex->pt->dyn.img)
15 { 15 {
16 evas_gl_common_texture_free(im->tex, EINA_TRUE); 16 evas_gl_common_texture_free(im->tex, EINA_TRUE);
17 im->tex = NULL; 17 im->tex = NULL;
18 } 18 }
19 } 19 }
@@ -574,11 +574,12 @@ evas_gl_common_image_update(Evas_Engine_GL_Context *gc, Evas_GL_Image *im)
574 { 574 {
575 case EVAS_COLORSPACE_ARGB8888: 575 case EVAS_COLORSPACE_ARGB8888:
576 if ((im->tex) && 576 if ((im->tex) &&
577 ((im->dirty) || (ie->animated.animated))) 577 ((im->dirty) || (ie->animated.animated) || (ie->flags.updated_data)))
578 { 578 {
579 evas_cache_image_load_data(&im->im->cache_entry); 579 evas_cache_image_load_data(&im->im->cache_entry);
580 evas_gl_common_texture_update(im->tex, im->im); 580 evas_gl_common_texture_update(im->tex, im->im);
581 evas_cache_image_unload_data(&im->im->cache_entry); 581 evas_cache_image_unload_data(&im->im->cache_entry);
582 ie->flags.updated_data = 0;
582 } 583 }
583 if (!im->tex) 584 if (!im->tex)
584 { 585 {
diff --git a/src/modules/evas/engines/gl_common/evas_gl_preload.c b/src/modules/evas/engines/gl_common/evas_gl_preload.c
new file mode 100644
index 0000000000..ffdb9093e7
--- /dev/null
+++ b/src/modules/evas/engines/gl_common/evas_gl_preload.c
@@ -0,0 +1,441 @@
1#include "evas_gl_private.h"
2
3static Eina_Thread async_loader_thread;
4static Eina_Condition async_loader_cond;
5static Eina_Lock async_loader_lock;
6
7static Evas_GL_Texture_Async_Preload *async_current = NULL;
8static Eina_List *async_loader_tex = NULL;
9static Eina_List *async_loader_todie = NULL;
10static Eina_Bool async_loader_exit = EINA_FALSE;
11static Eina_Bool async_loader_running = EINA_FALSE;
12static Eina_Bool async_loader_standby = EINA_FALSE;
13static Eina_Bool async_current_cancel = EINA_FALSE;
14static int async_loader_init = 0;
15
16static void *async_engine_data = NULL;
17static evas_gl_make_current_cb async_gl_make_current = NULL;
18
19Eina_Bool
20evas_gl_preload_push(Evas_GL_Texture_Async_Preload *async)
21{
22 if (!async_loader_init) return EINA_FALSE;
23
24 eina_lock_take(&async_loader_lock);
25 async_loader_tex = eina_list_append(async_loader_tex, async);
26 eina_lock_release(&async_loader_lock);
27
28 return EINA_TRUE;
29}
30
31void
32evas_gl_preload_pop(Evas_GL_Texture *tex)
33{
34 Evas_GL_Texture_Async_Preload *async;
35 Eina_List *l;
36
37 if (!async_loader_init) return ;
38
39 eina_lock_take(&async_loader_lock);
40
41 if (async_gl_make_current && async_current && async_current->tex == tex)
42 {
43 Eina_Bool running = async_loader_running;
44 evas_gl_make_current_cb tmp_cb = async_gl_make_current;
45 void *tmp_data = async_engine_data;
46
47 async_current_cancel = EINA_TRUE;
48 eina_lock_release(&async_loader_lock);
49
50 if (running) evas_gl_preload_render_lock(tmp_cb, tmp_data);
51
52 evas_gl_common_texture_free(async_current->tex, EINA_FALSE);
53 evas_cache_image_drop(&async_current->im->cache_entry);
54 free(async_current);
55
56 async_current = NULL;
57
58 if (running) evas_gl_preload_render_unlock(tmp_cb, tmp_data);
59
60 return ;
61 }
62
63 EINA_LIST_FOREACH(async_loader_tex, l, async)
64 if (async->tex == tex)
65 {
66 async_loader_tex = eina_list_remove_list(async_loader_tex, l);
67
68 evas_gl_common_texture_free(async->tex, EINA_FALSE);
69 evas_cache_image_drop(&async->im->cache_entry);
70 free(async);
71
72 break;
73 }
74
75 eina_lock_release(&async_loader_lock);
76}
77
78static void
79_evas_gl_preload_main_loop_wakeup(void)
80{
81 Evas_GL_Texture_Async_Preload *async;
82 evas_gl_make_current_cb cb = async_gl_make_current;
83 void *data = async_engine_data;
84 Eina_Bool running = async_loader_running;
85
86 if (running) evas_gl_preload_render_lock(cb, data);
87 EINA_LIST_FREE(async_loader_todie, async)
88 {
89 Eo *target;
90
91 EINA_LIST_FREE(async->tex->targets, target)
92 eo_do(target, evas_obj_image_pixels_dirty_set(EINA_TRUE));
93 async->im->cache_entry.flags.preload_done = 0;
94 async->tex->was_preloaded = EINA_TRUE;
95
96 async->tex->ptt->allocations = eina_list_remove(async->tex->ptt->allocations, async->tex->aptt);
97 pt_unref(async->tex->ptt);
98 async->tex->ptt = NULL;
99 free(async->tex->aptt);
100 async->tex->aptt = NULL;
101
102 evas_gl_common_texture_free(async->tex, EINA_FALSE);
103 evas_cache_image_drop(&async->im->cache_entry);
104 free(async);
105 }
106 if (running) evas_gl_preload_render_unlock(cb, data);
107}
108
109static void
110_evas_gl_preload_main_loop_wakeup_cb(void *target EINA_UNUSED,
111 Evas_Callback_Type type EINA_UNUSED,
112 void *event_info EINA_UNUSED)
113{
114 _evas_gl_preload_main_loop_wakeup();
115}
116
117static Eina_Bool
118_evas_gl_preload_lock(void)
119{
120 eina_lock_take(&async_loader_lock);
121 if (async_loader_standby)
122 {
123 async_gl_make_current(async_engine_data, NULL);
124
125 async_loader_running = EINA_FALSE;
126
127 eina_condition_signal(&async_loader_cond);
128
129 eina_condition_wait(&async_loader_cond);
130 if (async_loader_exit) return EINA_FALSE;
131
132 async_gl_make_current(async_engine_data, async_engine_data);
133 }
134 async_loader_running = EINA_TRUE;
135 eina_lock_release(&async_loader_lock);
136
137 return EINA_TRUE;
138}
139
140static void *
141_evas_gl_preload_tile_async(void *data EINA_UNUSED, Eina_Thread t EINA_UNUSED)
142{
143 eina_lock_take(&async_loader_lock);
144 while (!async_loader_exit)
145 {
146 Evas_GL_Texture_Async_Preload *async;
147 GLuint fmt;
148
149 if (!async_loader_standby && async_loader_tex)
150 goto get_next;
151
152 retry:
153 eina_condition_wait(&async_loader_cond);
154 if (async_loader_exit) break ;
155
156 get_next:
157 // Get a texture to upload
158 async = eina_list_data_get(async_loader_tex);
159 async_loader_tex = eina_list_remove_list(async_loader_tex, async_loader_tex);
160 if (!async) continue;
161
162 async_loader_running = EINA_TRUE;
163 async_current = async;
164
165 eina_lock_release(&async_loader_lock);
166
167 // Switch context to this thread
168 if (!async_gl_make_current(async_engine_data, async_engine_data))
169 {
170 eina_lock_take(&async_loader_lock);
171 async_loader_tex = eina_list_append(async_loader_tex, async_current);
172 async_loader_running = EINA_FALSE;
173 async_current = NULL;
174
175 if (async_loader_standby)
176 eina_condition_signal(&async_loader_cond);
177
178 goto retry;
179 }
180
181 // FIXME: loop until all subtile are uploaded or the image is about to be deleted
182
183 // TEMPORARY CODE JUST TO SEE IF IT WORK
184 fmt = async->tex->pt->format;
185 glBindTexture(GL_TEXTURE_2D, async->tex->pt->texture);
186 GLERR(__FUNCTION__, __FILE__, __LINE__, "");
187 if (async->unpack_row_length)
188 {
189 glPixelStorei(GL_UNPACK_ROW_LENGTH, 0);
190 GLERR(__FUNCTION__, __FILE__, __LINE__, "");
191 }
192 glPixelStorei(GL_UNPACK_ALIGNMENT, 4);
193 GLERR(__FUNCTION__, __FILE__, __LINE__, "");
194
195 // +-+
196 // +-+
197 //
198 _tex_sub_2d(async->tex->x, async->tex->y,
199 async->im->cache_entry.w, async->im->cache_entry.h,
200 fmt, async->tex->pt->dataformat,
201 async->im->image.data);
202 // xxx
203 // xxx
204 // ---
205 _tex_sub_2d(async->tex->x, async->tex->y + async->im->cache_entry.h,
206 async->im->cache_entry.w, 1,
207 fmt, async->tex->pt->dataformat,
208 async->im->image.data + ((async->im->cache_entry.h - 1) * async->im->cache_entry.w));
209 // xxx
210 // xxx
211 // o
212 _tex_sub_2d(async->tex->x - 1, async->tex->y + async->im->cache_entry.h,
213 1, 1,
214 fmt, async->tex->pt->dataformat,
215 async->im->image.data + ((async->im->cache_entry.h - 1) * async->im->cache_entry.w));
216 // xxx
217 // xxx
218 // o
219 _tex_sub_2d(async->tex->x + async->im->cache_entry.w, async->tex->y + async->im->cache_entry.h,
220 1, 1,
221 fmt, async->tex->pt->dataformat,
222 async->im->image.data + ((async->im->cache_entry.h - 1) * async->im->cache_entry.w) + (async->im->cache_entry.w - 1));
223 if (async->unpack_row_length)
224 {
225 glPixelStorei(GL_UNPACK_ROW_LENGTH, async->im->cache_entry.w);
226 GLERR(__FUNCTION__, __FILE__, __LINE__, "");
227 // |xxx
228 // |xxx
229 //
230 _tex_sub_2d(async->tex->x - 1, async->tex->y,
231 1, async->im->cache_entry.h,
232 fmt, async->tex->pt->dataformat,
233 async->im->image.data);
234 // xxx|
235 // xxx|
236 //
237 _tex_sub_2d(async->tex->x + async->im->cache_entry.w, async->tex->y,
238 1, async->im->cache_entry.h,
239 fmt, async->tex->pt->dataformat,
240 async->im->image.data + (async->im->cache_entry.w - 1));
241 }
242 else
243 {
244 DATA32 *tpix, *ps, *pd;
245 int i;
246
247 tpix = alloca(async->im->cache_entry.h * sizeof(DATA32));
248 pd = tpix;
249 ps = async->im->image.data;
250 for (i = 0; i < (int)async->im->cache_entry.h; i++)
251 {
252 *pd = *ps;
253 pd++;
254 ps += async->im->cache_entry.w;
255 }
256 // |xxx
257 // |xxx
258 //
259 _tex_sub_2d(async->tex->x - 1, async->tex->y,
260 1, async->im->cache_entry.h,
261 fmt, async->tex->pt->dataformat,
262 tpix);
263 pd = tpix;
264 ps = async->im->image.data + (async->im->cache_entry.w - 1);
265 for (i = 0; i < (int)async->im->cache_entry.h; i++)
266 {
267 *pd = *ps;
268 pd++;
269 ps += async->im->cache_entry.w;
270 }
271 // xxx|
272 // xxx|
273 //
274 _tex_sub_2d(async->tex->x + async->im->cache_entry.w, async->tex->y,
275 1, async->im->cache_entry.h,
276 fmt, async->tex->pt->dataformat,
277 tpix);
278 }
279
280 // Switch back to current texture
281 if (async->tex->ptt->texture != async->tex->gc->pipe[0].shader.cur_tex)
282 {
283 glBindTexture(GL_TEXTURE_2D, async->tex->gc->pipe[0].shader.cur_tex);
284 GLERR(__FUNCTION__, __FILE__, __LINE__, "");
285 }
286
287 // Shall we block now ?
288 if (!_evas_gl_preload_lock())
289 break;
290
291 // Release context
292 async_gl_make_current(async_engine_data, NULL);
293
294 evas_async_events_put(NULL, 0, NULL, _evas_gl_preload_main_loop_wakeup_cb);
295
296 eina_lock_take(&async_loader_lock);
297 async_current = NULL;
298 async_loader_todie = eina_list_append(async_loader_todie, async);
299 async_loader_running = EINA_FALSE;
300
301 if (async_loader_standby)
302 eina_condition_signal(&async_loader_cond);
303 }
304 eina_lock_release(&async_loader_lock);
305
306 return NULL;
307}
308
309// In the main loop
310// Push stuff on the todo queue
311// Upload the mini texture
312// Use the mini texture
313// Once download of the big texture, destroy mini texture and image data
314
315
316// Put the async preloader on standby
317void
318evas_gl_preload_render_lock(evas_gl_make_current_cb make_current, void *engine_data)
319{
320 if (!async_loader_init) return ;
321 eina_lock_take(&async_loader_lock);
322 if (async_loader_running)
323 {
324 async_loader_standby = EINA_TRUE;
325 eina_condition_wait(&async_loader_cond);
326
327 make_current(engine_data, engine_data);
328
329 async_engine_data = NULL;
330 async_gl_make_current = NULL;
331 }
332
333 eina_lock_release(&async_loader_lock);
334}
335
336// Let the async preloader run !
337void
338evas_gl_preload_render_unlock(evas_gl_make_current_cb make_current, void *engine_data)
339{
340 if (!async_loader_init) return ;
341 if (!make_current) return ;
342
343 eina_lock_take(&async_loader_lock);
344 if (!async_loader_running && (async_loader_tex || async_current))
345 {
346 make_current(engine_data, NULL);
347
348 async_gl_make_current = make_current;
349 async_engine_data = engine_data;
350
351 async_loader_standby = EINA_FALSE;
352 eina_condition_signal(&async_loader_cond);
353 }
354 eina_lock_release(&async_loader_lock);
355}
356
357// add a way to destroy surface and temporarily stop the rendering of the image
358void
359evas_gl_preload_render_relax(evas_gl_make_current_cb make_current, void *engine_data)
360{
361 if (engine_data != async_engine_data) return ;
362
363 evas_gl_preload_render_lock(make_current, engine_data);
364}
365
366static Eina_Bool
367_evas_gl_preload_target_die(void *data, Eo *obj,
368 const Eo_Event_Description *desc EINA_UNUSED, void *event_info EINA_UNUSED)
369{
370 Evas_GL_Texture *tex = data;
371
372 evas_gl_preload_target_unregister(tex, obj);
373
374 return EO_CALLBACK_CONTINUE;
375}
376
377void
378evas_gl_preload_target_register(Evas_GL_Texture *tex, Eo *target)
379{
380 eo_do(target,
381 eo_event_callback_add(EO_EV_DEL, _evas_gl_preload_target_die, tex));
382 tex->targets = eina_list_append(tex->targets, target);
383 tex->references++;
384}
385
386void
387evas_gl_preload_target_unregister(Evas_GL_Texture *tex, Eo *target)
388{
389 Eina_List *l;
390 const Eo *o;
391
392 eo_do(target,
393 eo_event_callback_del(EO_EV_DEL, _evas_gl_preload_target_die, tex));
394
395 EINA_LIST_FOREACH(tex->targets, l, o)
396 if (o == target)
397 {
398 void *data = async_engine_data;
399 evas_gl_make_current_cb cb = async_gl_make_current;
400 Eina_Bool running = async_loader_running;
401
402 if (running) evas_gl_preload_render_lock(cb, data);
403 tex->targets = eina_list_remove_list(tex->targets, l);
404 evas_gl_common_texture_free(tex, EINA_FALSE);
405 if (running) evas_gl_preload_render_unlock(cb, data);
406
407 break;
408 }
409}
410
411int
412evas_gl_preload_init(void)
413{
414 if (async_loader_init++) return async_loader_init;
415
416 eina_lock_new(&async_loader_lock);
417 eina_condition_new(&async_loader_cond, &async_loader_lock);
418
419 if (!eina_thread_create(&async_loader_thread, EINA_THREAD_BACKGROUND, 0, _evas_gl_preload_tile_async, NULL))
420 {
421 // FIXME: handle error case
422 }
423
424 return async_loader_init;
425}
426
427int
428evas_gl_preload_shutdown(void)
429{
430 if (--async_loader_init) return async_loader_init;
431
432 async_loader_exit = EINA_TRUE;
433 eina_condition_signal(&async_loader_cond);
434
435 eina_thread_join(async_loader_thread);
436
437 eina_condition_free(&async_loader_cond);
438 eina_lock_free(&async_loader_lock);
439
440 return async_loader_init;
441}
diff --git a/src/modules/evas/engines/gl_common/evas_gl_texture.c b/src/modules/evas/engines/gl_common/evas_gl_texture.c
index 0c07ffa383..426549cc74 100644
--- a/src/modules/evas/engines/gl_common/evas_gl_texture.c
+++ b/src/modules/evas/engines/gl_common/evas_gl_texture.c
@@ -194,13 +194,6 @@ evas_gl_common_texture_light_free(Evas_GL_Texture *tex)
194 free(tex); 194 free(tex);
195} 195}
196 196
197static void
198_tex_sub_2d(int x, int y, int w, int h, int fmt, int type, const void *pix)
199{
200 glTexSubImage2D(GL_TEXTURE_2D, 0, x, y, w, h, fmt, type, pix);
201 GLERR(__FUNCTION__, __FILE__, __LINE__, "");
202}
203
204static Evas_GL_Texture_Pool * 197static Evas_GL_Texture_Pool *
205_pool_tex_new(Evas_Engine_GL_Context *gc, int w, int h, int intformat, GLenum format) 198_pool_tex_new(Evas_Engine_GL_Context *gc, int w, int h, int intformat, GLenum format)
206{ 199{
@@ -711,7 +704,7 @@ evas_gl_texture_pool_empty(Evas_GL_Texture_Pool *pt)
711 pt->h = 0; 704 pt->h = 0;
712} 705}
713 706
714static void 707void
715pt_unref(Evas_GL_Texture_Pool *pt) 708pt_unref(Evas_GL_Texture_Pool *pt)
716{ 709{
717 if (!pt) return; 710 if (!pt) return;
@@ -814,7 +807,7 @@ evas_gl_common_texture_update(Evas_GL_Texture *tex, RGBA_Image *im)
814{ 807{
815 GLuint fmt; 808 GLuint fmt;
816 809
817 if (!im->image.data) return; 810 if (!im->cache_entry.flags.loaded) return;
818 811
819 if (tex->alpha != im->cache_entry.flags.alpha) 812 if (tex->alpha != im->cache_entry.flags.alpha)
820 { 813 {
@@ -830,8 +823,101 @@ evas_gl_common_texture_update(Evas_GL_Texture *tex, RGBA_Image *im)
830 *matching_format[lformat].intformat, 823 *matching_format[lformat].intformat,
831 *matching_format[lformat].format); 824 *matching_format[lformat].format);
832 } 825 }
826 // If image was preloaded then we need a ptt
833 if (!tex->pt) return; 827 if (!tex->pt) return;
834 828
829 // if preloaded, then async push it in after uploading a miniature of it
830 if (im->cache_entry.flags.preload_done && tex->w > 2 * EVAS_GL_TILE_SIZE && tex->h > 2 * EVAS_GL_TILE_SIZE)
831 {
832 Evas_GL_Texture_Async_Preload *async;
833 int *in;
834 int out[EVAS_GL_TILE_SIZE * EVAS_GL_TILE_SIZE];
835 float xstep, ystep;
836 float x, y;
837 int i, j;
838 int lformat;
839 int u, v;
840
841 if (tex->ptt) return ;
842
843 xstep = (float)tex->w / (EVAS_GL_TILE_SIZE - 2);
844 ystep = (float)tex->h / (EVAS_GL_TILE_SIZE - 1);
845 in = (int*) im->image.data;
846
847 for (y = 0, j = 0; j < EVAS_GL_TILE_SIZE - 1; y += ystep, j++)
848 {
849 out[j * EVAS_GL_TILE_SIZE] = in[(int)y * im->cache_entry.w];
850 for (x = 0, i = 1; i < EVAS_GL_TILE_SIZE - 1; x += xstep, i++)
851 out[j * EVAS_GL_TILE_SIZE + i] = in[(int)y * im->cache_entry.w + (int)x];
852 out[j * EVAS_GL_TILE_SIZE + i] = in[(int)y * im->cache_entry.w + (int)(x - xstep)];
853 }
854
855 memcpy(&out[j * EVAS_GL_TILE_SIZE], &out[(j - 1) * EVAS_GL_TILE_SIZE], EVAS_GL_TILE_SIZE * sizeof (int));
856
857 // out is a miniature of the texture, upload that now and schedule the data for later.
858
859 // Creating the mini picture texture
860 lformat = _evas_gl_texture_search_format(tex->alpha, tex->gc->shared->info.bgra);
861 tex->ptt = _pool_tex_find(tex->gc, EVAS_GL_TILE_SIZE, EVAS_GL_TILE_SIZE,
862 *matching_format[lformat].intformat,
863 *matching_format[lformat].format,
864 &u, &v, &tex->aptt,
865 tex->gc->shared->info.tune.atlas.max_alloc_size);
866 if (!tex->ptt)
867 goto upload;
868 tex->aptt->tex = tex;
869
870 tex->tx = u + 1;
871 tex->ty = v;
872 tex->ptt->references++;
873
874 // Bind and upload ! Vooom !
875 fmt = tex->ptt->format;
876 glBindTexture(GL_TEXTURE_2D, tex->ptt->texture);
877 GLERR(__FUNCTION__, __FILE__, __LINE__, "");
878 if (tex->gc->shared->info.unpack_row_length)
879 {
880 glPixelStorei(GL_UNPACK_ROW_LENGTH, 0);
881 GLERR(__FUNCTION__, __FILE__, __LINE__, "");
882 }
883 glPixelStorei(GL_UNPACK_ALIGNMENT, 4);
884 GLERR(__FUNCTION__, __FILE__, __LINE__, "");
885
886 _tex_sub_2d(u, tex->ty, EVAS_GL_TILE_SIZE, EVAS_GL_TILE_SIZE, fmt, tex->ptt->dataformat, out);
887
888 // Switch back to current texture
889 if (tex->ptt->texture != tex->gc->pipe[0].shader.cur_tex)
890 {
891 glBindTexture(GL_TEXTURE_2D, tex->gc->pipe[0].shader.cur_tex);
892 GLERR(__FUNCTION__, __FILE__, __LINE__, "");
893 }
894
895 // Now prepare uploading the main texture before returning;
896 async = malloc(sizeof (Evas_GL_Texture_Async_Preload));
897 if (!async)
898 {
899 goto upload;
900 }
901
902 async->tex = tex;
903 async->tex->references++;
904 async->im = im;
905 evas_cache_image_ref(&async->im->cache_entry);
906 async->unpack_row_length = tex->gc->shared->info.unpack_row_length;
907
908 if (evas_gl_preload_push(async))
909 return ;
910
911 // Failed to start asynchronous upload, likely due to preload not being supported by the backend
912 async->tex->references--;
913 evas_cache_image_drop(&async->im->cache_entry);
914 free(async);
915
916 upload:
917 pt_unref(tex->ptt);
918 tex->ptt = NULL;
919 }
920
835 fmt = tex->pt->format; 921 fmt = tex->pt->format;
836 glBindTexture(GL_TEXTURE_2D, tex->pt->texture); 922 glBindTexture(GL_TEXTURE_2D, tex->pt->texture);
837 GLERR(__FUNCTION__, __FILE__, __LINE__, ""); 923 GLERR(__FUNCTION__, __FILE__, __LINE__, "");
@@ -939,6 +1025,13 @@ void
939evas_gl_common_texture_free(Evas_GL_Texture *tex, Eina_Bool force EINA_UNUSED) 1025evas_gl_common_texture_free(Evas_GL_Texture *tex, Eina_Bool force EINA_UNUSED)
940{ 1026{
941 if (!tex) return; 1027 if (!tex) return;
1028 if (force)
1029 {
1030 evas_gl_preload_pop(tex);
1031
1032 while (tex->targets)
1033 evas_gl_preload_target_unregister(tex, eina_list_data_get(tex->targets));
1034 }
942 tex->references--; 1035 tex->references--;
943 if (tex->references != 0) return; 1036 if (tex->references != 0) return;
944 if (tex->fglyph) 1037 if (tex->fglyph)
diff --git a/src/modules/evas/engines/gl_x11/evas_engine.c b/src/modules/evas/engines/gl_x11/evas_engine.c
index 7f408fdd91..9441d6dccd 100644
--- a/src/modules/evas/engines/gl_x11/evas_engine.c
+++ b/src/modules/evas/engines/gl_x11/evas_engine.c
@@ -73,6 +73,8 @@ typedef int (*glsym_func_int) ();
73typedef unsigned int (*glsym_func_uint) (); 73typedef unsigned int (*glsym_func_uint) ();
74typedef const char *(*glsym_func_const_char_ptr) (); 74typedef const char *(*glsym_func_const_char_ptr) ();
75 75
76static Eina_Bool eng_preload_make_current(void *data, void *doit);
77
76#ifdef GL_GLES 78#ifdef GL_GLES
77 79
78#ifndef EGL_NATIVE_PIXMAP_KHR 80#ifndef EGL_NATIVE_PIXMAP_KHR
@@ -702,10 +704,6 @@ gl_extn_veto(Render_Engine *re)
702 { 704 {
703 extn_have_buffer_age = 0; 705 extn_have_buffer_age = 0;
704 } 706 }
705 if (!strstr(str, "swap_buffers_with_damage"))
706 {
707 glsym_eglSwapBuffersWithDamage = NULL;
708 }
709 } 707 }
710 else 708 else
711 { 709 {
@@ -808,6 +806,7 @@ static void
808_re_winfree(Render_Engine *re) 806_re_winfree(Render_Engine *re)
809{ 807{
810 if (!re->win->surf) return; 808 if (!re->win->surf) return;
809 evas_gl_preload_render_relax(eng_preload_make_current, re);
811 eng_window_unsurf(re->win); 810 eng_window_unsurf(re->win);
812} 811}
813 812
@@ -877,6 +876,7 @@ eng_setup(Evas *eo_e, void *in)
877 evas_common_font_init(); 876 evas_common_font_init();
878 evas_common_draw_init(); 877 evas_common_draw_init();
879 evas_common_tilebuf_init(); 878 evas_common_tilebuf_init();
879 evas_gl_preload_init();
880 gl_extn_veto(re); 880 gl_extn_veto(re);
881// evgl_engine_init(re, &evgl_funcs); 881// evgl_engine_init(re, &evgl_funcs);
882 initted = 1; 882 initted = 1;
@@ -1033,6 +1033,8 @@ eng_output_free(void *data)
1033 1033
1034 if (re) 1034 if (re)
1035 { 1035 {
1036 evas_gl_preload_render_relax(eng_preload_make_current, re);
1037
1036#if 0 1038#if 0
1037#ifdef GL_GLES 1039#ifdef GL_GLES
1038 // Destroy the resource surface 1040 // Destroy the resource surface
@@ -1070,6 +1072,7 @@ eng_output_free(void *data)
1070 } 1072 }
1071 if ((initted == 1) && (gl_wins == 0)) 1073 if ((initted == 1) && (gl_wins == 0))
1072 { 1074 {
1075 evas_gl_preload_shutdown();
1073 evas_common_image_shutdown(); 1076 evas_common_image_shutdown();
1074 evas_common_font_shutdown(); 1077 evas_common_font_shutdown();
1075 initted = 0; 1078 initted = 0;
@@ -1213,6 +1216,42 @@ _merge_rects(Tilebuf *tb, Tilebuf_Rect *r1, Tilebuf_Rect *r2, Tilebuf_Rect *r3)
1213/* vsync games - not for now though */ 1216/* vsync games - not for now though */
1214#define VSYNC_TO_SCREEN 1 1217#define VSYNC_TO_SCREEN 1
1215 1218
1219static Eina_Bool
1220eng_preload_make_current(void *data, void *doit)
1221{
1222 Render_Engine *re = data;
1223
1224 if (doit)
1225 {
1226#ifdef GL_GLES
1227 if (!eglMakeCurrent(re->win->egl_disp, re->win->egl_surface[0], re->win->egl_surface[0], re->win->egl_context[0]))
1228 return EINA_FALSE;
1229#else
1230 if (!glXMakeCurrent(re->info->info.display, re->win->win, re->win->context))
1231 {
1232 ERR("glXMakeCurrent(%p, 0x%x, %p) failed", re->info->info.display, (unsigned int)re->win->win, (void *)re->win->context);
1233 GLERR(__FUNCTION__, __FILE__, __LINE__, "");
1234 return EINA_FALSE;
1235 }
1236#endif
1237 }
1238 else
1239 {
1240#ifdef GL_GLES
1241 if (!eglMakeCurrent(re->win->egl_disp, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT))
1242 return EINA_FALSE;
1243#else
1244 if (!glXMakeCurrent(re->info->info.display, None, NULL))
1245 {
1246 ERR("glXMakeCurrent(%p, None, NULL) failed", re->info->info.display);
1247 GLERR(__FUNCTION__, __FILE__, __LINE__, "");
1248 return EINA_FALSE;
1249 }
1250#endif
1251 }
1252 return EINA_TRUE;
1253}
1254
1216static void * 1255static void *
1217eng_output_redraws_next_update_get(void *data, int *x, int *y, int *w, int *h, int *cx, int *cy, int *cw, int *ch) 1256eng_output_redraws_next_update_get(void *data, int *x, int *y, int *w, int *h, int *cx, int *cy, int *cw, int *ch)
1218{ 1257{
@@ -1353,6 +1392,7 @@ eng_output_redraws_next_update_get(void *data, int *x, int *y, int *w, int *h, i
1353 } 1392 }
1354 if (first_rect) 1393 if (first_rect)
1355 { 1394 {
1395 evas_gl_preload_render_lock(eng_preload_make_current, re);
1356#ifdef GL_GLES 1396#ifdef GL_GLES
1357 // dont need to for egl - eng_window_use() can check for other ctxt's 1397 // dont need to for egl - eng_window_use() can check for other ctxt's
1358#else 1398#else
@@ -1433,11 +1473,11 @@ eng_output_flush(void *data, Evas_Render_Mode render_mode)
1433{ 1473{
1434 Render_Engine *re; 1474 Render_Engine *re;
1435 1475
1436 if (render_mode == EVAS_RENDER_MODE_ASYNC_INIT) return; 1476 if (render_mode == EVAS_RENDER_MODE_ASYNC_INIT) goto end;
1437 1477
1438 re = (Render_Engine *)data; 1478 re = (Render_Engine *)data;
1439 if (!_re_wincheck(re)) return; 1479 if (!_re_wincheck(re)) goto end;
1440 if (!re->win->draw.drew) return; 1480 if (!re->win->draw.drew) goto end;
1441 1481
1442 re->win->draw.drew = 0; 1482 re->win->draw.drew = 0;
1443 eng_window_use(re->win); 1483 eng_window_use(re->win);
@@ -1454,7 +1494,7 @@ eng_output_flush(void *data, Evas_Render_Mode render_mode)
1454 { 1494 {
1455 re->info->callback.pre_swap(re->info->callback.data, re->evas); 1495 re->info->callback.pre_swap(re->info->callback.data, re->evas);
1456 } 1496 }
1457 if ((glsym_eglSwapBuffersWithDamage) && (re->mode != MODE_FULL)) 1497 if ((glsym_eglSwapBuffersRegion) && (re->mode != MODE_FULL))
1458 { 1498 {
1459 EGLint num = 0, *rects = NULL, i = 0; 1499 EGLint num = 0, *rects = NULL, i = 0;
1460 Tilebuf_Rect *r; 1500 Tilebuf_Rect *r;
@@ -1505,9 +1545,9 @@ eng_output_flush(void *data, Evas_Render_Mode render_mode)
1505 } 1545 }
1506 i += 4; 1546 i += 4;
1507 } 1547 }
1508 glsym_eglSwapBuffersWithDamage(re->win->egl_disp, 1548 glsym_eglSwapBuffersRegion(re->win->egl_disp,
1509 re->win->egl_surface[0], 1549 re->win->egl_surface[0],
1510 rects, num); 1550 num, rects);
1511 } 1551 }
1512 } 1552 }
1513 else 1553 else
@@ -1574,6 +1614,9 @@ eng_output_flush(void *data, Evas_Render_Mode render_mode)
1574 evas_common_tilebuf_free_render_rects(re->rects); 1614 evas_common_tilebuf_free_render_rects(re->rects);
1575 re->rects = NULL; 1615 re->rects = NULL;
1576 } 1616 }
1617
1618 end:
1619 evas_gl_preload_render_unlock(eng_preload_make_current, re);
1577} 1620}
1578 1621
1579static void 1622static void
@@ -2771,9 +2814,10 @@ eng_image_data_put(void *data, void *image, DATA32 *image_data)
2771} 2814}
2772 2815
2773static void 2816static void
2774eng_image_data_preload_request(void *data EINA_UNUSED, void *image, const Eo *target) 2817eng_image_data_preload_request(void *data, void *image, const Eo *target)
2775{ 2818{
2776 Evas_GL_Image *gim = image; 2819 Evas_GL_Image *gim = image;
2820 Render_Engine *re = data;
2777 RGBA_Image *im; 2821 RGBA_Image *im;
2778 2822
2779 if (!gim) return; 2823 if (!gim) return;
@@ -2781,6 +2825,9 @@ eng_image_data_preload_request(void *data EINA_UNUSED, void *image, const Eo *ta
2781 im = (RGBA_Image *)gim->im; 2825 im = (RGBA_Image *)gim->im;
2782 if (!im) return; 2826 if (!im) return;
2783 evas_cache_image_preload_data(&im->cache_entry, target, NULL, NULL, NULL); 2827 evas_cache_image_preload_data(&im->cache_entry, target, NULL, NULL, NULL);
2828 if (!gim->tex)
2829 gim->tex = evas_gl_common_texture_new(re->win->gl_context, gim->im);
2830 evas_gl_preload_target_register(gim->tex, (Eo*) target);
2784} 2831}
2785 2832
2786static void 2833static void
@@ -2794,6 +2841,7 @@ eng_image_data_preload_cancel(void *data EINA_UNUSED, void *image, const Eo *tar
2794 im = (RGBA_Image *)gim->im; 2841 im = (RGBA_Image *)gim->im;
2795 if (!im) return; 2842 if (!im) return;
2796 evas_cache_image_preload_cancel(&im->cache_entry, target); 2843 evas_cache_image_preload_cancel(&im->cache_entry, target);
2844 evas_gl_preload_target_unregister(gim->tex, (Eo*) target);
2797} 2845}
2798 2846
2799static Eina_Bool 2847static Eina_Bool
diff --git a/src/modules/evas/engines/gl_x11/evas_x_main.c b/src/modules/evas/engines/gl_x11/evas_x_main.c
index d0de1df8ae..91015dcb3f 100644
--- a/src/modules/evas/engines/gl_x11/evas_x_main.c
+++ b/src/modules/evas/engines/gl_x11/evas_x_main.c
@@ -454,11 +454,57 @@ eng_window_free(Evas_GL_X11_Window *gw)
454 free(gw); 454 free(gw);
455} 455}
456 456
457static Eina_Bool
458eng_window_make_current(void *data, void *doit)
459{
460 Evas_GL_X11_Window *gw = data;
461
462#ifdef GL_GLES
463 if (doit)
464 {
465 if (!eglMakeCurrent(gw->egl_disp, gw->egl_surface[0], gw->egl_surface[0], gw->egl_context[0]))
466 return EINA_FALSE;
467 }
468 else
469 {
470 if (!eglMakeCurrent(gw->egl_disp, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT))
471 return EINA_FALSE;
472 }
473#else
474 if (doit)
475 {
476 if (gw->glxwin)
477 {
478 if (!glXMakeContextCurrent(gw->disp, gw->glxwin, gw->glxwin, gw->context))
479 {
480 ERR("glXMakeContextCurrent(%p, %p, %p, %p)", (void *)gw->disp, (void *)gw->glxwin, (void *)gw->glxwin, (void *)gw->context);
481 return EINA_FALSE;
482 }
483 }
484 else
485 {
486 if (!glXMakeCurrent(gw->disp, gw->win, gw->context))
487 {
488 ERR("glXMakeCurrent(%p, 0x%x, %p) failed", gw->disp, (unsigned int)gw->win, (void *)gw->context);
489 return EINA_FALSE;
490 }
491 }
492 }
493 else
494 {
495 if (!glXMakeCurrent(gw->disp, None, NULL))
496 return EINA_FALSE;
497 }
498#endif
499 return EINA_TRUE;
500}
501
457void 502void
458eng_window_use(Evas_GL_X11_Window *gw) 503eng_window_use(Evas_GL_X11_Window *gw)
459{ 504{
460 Eina_Bool force_use = EINA_FALSE; 505 Eina_Bool force_use = EINA_FALSE;
461 506
507 evas_gl_preload_render_lock(eng_window_make_current, gw);
462#ifdef GL_GLES 508#ifdef GL_GLES
463 if (_evas_gl_x11_window) 509 if (_evas_gl_x11_window)
464 { 510 {