summaryrefslogtreecommitdiff
path: root/src/modules
diff options
context:
space:
mode:
authorJean-Philippe Andre <jp.andre@samsung.com>2014-12-09 21:36:45 +0900
committerJean-Philippe Andre <jp.andre@samsung.com>2014-12-10 10:52:22 +0900
commit4cf2d75715d6d9c3bc7f02a246997b0ca7a330cd (patch)
tree924d4e228e9c5c4a1b428fac0e9033aed7681788 /src/modules
parentf52be78699a2a3165a74f37910eabefec68a977d (diff)
Evas GL: Fix direct rendering with client-side rotation
There was a problem when checking whether the current surface is compatible with direct rendering. In case of client-side rotation (it's a flag set on the surface by the app), a surface can be directly rendered even if the rotation is not 0. But, before this patch, it was assumed that the surface was current. Which doesn't make sense because make_current is called by the pixel callback, from the application, and this happens *after* we check for direct rendering. As a consequence, it was not possible to mix directly rendered surfaces with FBO-based ones, and use client-side rotation. This patch should solve that issue.
Diffstat (limited to 'src/modules')
-rw-r--r--src/modules/evas/engines/gl_common/evas_gl_core.c154
-rw-r--r--src/modules/evas/engines/gl_common/evas_gl_core.h7
-rw-r--r--src/modules/evas/engines/gl_common/evas_gl_core_private.h3
-rw-r--r--src/modules/evas/engines/gl_generic/evas_engine.c26
-rw-r--r--src/modules/evas/engines/software_generic/evas_engine.c3
5 files changed, 155 insertions, 38 deletions
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 c0d7a2be2a..9d58f02a72 100644
--- a/src/modules/evas/engines/gl_common/evas_gl_core.c
+++ b/src/modules/evas/engines/gl_common/evas_gl_core.c
@@ -1111,7 +1111,7 @@ _internal_config_set(EVGL_Surface *sfc, Evas_GL_Config *cfg)
1111 // TODO: Implement surface reconfigure and add depth+stencil support 1111 // TODO: Implement surface reconfigure and add depth+stencil support
1112 1112
1113 // Direct Rendering Option 1113 // Direct Rendering Option
1114 if ((!depth_bit && !stencil_bit) || evgl_engine->direct_override) 1114 if ((!depth_bit && !stencil_bit && !msaa_samples) || evgl_engine->direct_override)
1115 sfc->direct_fb_opt = cfg->options_bits & EVAS_GL_OPTIONS_DIRECT; 1115 sfc->direct_fb_opt = cfg->options_bits & EVAS_GL_OPTIONS_DIRECT;
1116 1116
1117 // Extra flags for direct rendering 1117 // Extra flags for direct rendering
@@ -1271,6 +1271,27 @@ _evgl_not_in_pixel_get(void)
1271 1271
1272 EVGL_Context *ctx = rsc->current_ctx; 1272 EVGL_Context *ctx = rsc->current_ctx;
1273 1273
1274 if (evgl_engine->direct_force_off)
1275 return 0;
1276
1277 if (rsc->id != evgl_engine->main_tid)
1278 return 0;
1279
1280 if (!ctx || !ctx->current_sfc)
1281 return 0;
1282
1283 if (!ctx->current_sfc->direct_fb_opt)
1284 return 0;
1285
1286 if (rsc->direct.rot == 0)
1287 return !rsc->direct.enabled;
1288
1289 if (!ctx->current_sfc->client_side_rotation)
1290 return 0;
1291
1292 return !rsc->direct.enabled;
1293
1294 /* was:
1274 if ((!evgl_engine->direct_force_off) && 1295 if ((!evgl_engine->direct_force_off) &&
1275 (rsc->id == evgl_engine->main_tid) && 1296 (rsc->id == evgl_engine->main_tid) &&
1276 (ctx) && 1297 (ctx) &&
@@ -1280,6 +1301,7 @@ _evgl_not_in_pixel_get(void)
1280 return 1; 1301 return 1;
1281 else 1302 else
1282 return 0; 1303 return 0;
1304 */
1283} 1305}
1284 1306
1285int 1307int
@@ -1354,6 +1376,7 @@ EVGL_Engine *
1354evgl_engine_init(void *eng_data, const EVGL_Interface *efunc) 1376evgl_engine_init(void *eng_data, const EVGL_Interface *efunc)
1355{ 1377{
1356 int direct_mem_opt = 0, direct_off = 0, direct_soff = 0, debug_mode = 0; 1378 int direct_mem_opt = 0, direct_off = 0, direct_soff = 0, debug_mode = 0;
1379 int direct_override = 0;
1357 char *s = NULL; 1380 char *s = NULL;
1358 1381
1359 if (evgl_engine) return evgl_engine; 1382 if (evgl_engine) return evgl_engine;
@@ -1436,6 +1459,12 @@ evgl_engine_init(void *eng_data, const EVGL_Interface *efunc)
1436 if (direct_mem_opt == 1) 1459 if (direct_mem_opt == 1)
1437 evgl_engine->direct_mem_opt = 1; 1460 evgl_engine->direct_mem_opt = 1;
1438 1461
1462 // Check for Direct rendering override env var.
1463 s = getenv("EVAS_GL_DIRECT_OVERRIDE");
1464 if (s) direct_override = atoi(s);
1465 if (direct_override == 1)
1466 evgl_engine->direct_override = 1;
1467
1439 // Check if Direct Rendering Override Force Off flag is on 1468 // Check if Direct Rendering Override Force Off flag is on
1440 s = getenv("EVAS_GL_DIRECT_OVERRIDE_FORCE_OFF"); 1469 s = getenv("EVAS_GL_DIRECT_OVERRIDE_FORCE_OFF");
1441 if (s) direct_off = atoi(s); 1470 if (s) direct_off = atoi(s);
@@ -1461,6 +1490,9 @@ evgl_engine_init(void *eng_data, const EVGL_Interface *efunc)
1461 if (!gl_funcs) gl_funcs = calloc(1, EVAS_GL_API_STRUCT_SIZE); 1490 if (!gl_funcs) gl_funcs = calloc(1, EVAS_GL_API_STRUCT_SIZE);
1462 if (!gles1_funcs) gles1_funcs = calloc(1, EVAS_GL_API_STRUCT_SIZE); 1491 if (!gles1_funcs) gles1_funcs = calloc(1, EVAS_GL_API_STRUCT_SIZE);
1463 1492
1493 // Direct surfaces map texid->Evas_GL_Surface
1494 evgl_engine->direct_surfaces = eina_hash_int32_new(NULL);
1495
1464 return evgl_engine; 1496 return evgl_engine;
1465 1497
1466error: 1498error:
@@ -1496,6 +1528,12 @@ evgl_engine_shutdown(void *eng_data)
1496 // Destroy internal resources 1528 // Destroy internal resources
1497 _evgl_tls_resource_destroy(eng_data); 1529 _evgl_tls_resource_destroy(eng_data);
1498 1530
1531 if (evgl_engine->direct_surfaces)
1532 {
1533 eina_hash_free(evgl_engine->direct_surfaces);
1534 evgl_engine->direct_surfaces = NULL;
1535 }
1536
1499 LKD(evgl_engine->resource_lock); 1537 LKD(evgl_engine->resource_lock);
1500 1538
1501 // Free engine 1539 // Free engine
@@ -1507,8 +1545,6 @@ void *
1507evgl_surface_create(void *eng_data, Evas_GL_Config *cfg, int w, int h) 1545evgl_surface_create(void *eng_data, Evas_GL_Config *cfg, int w, int h)
1508{ 1546{
1509 EVGL_Surface *sfc = NULL; 1547 EVGL_Surface *sfc = NULL;
1510 char *s = NULL;
1511 int direct_override = 0, direct_mem_opt = 0;
1512 Eina_Bool need_reconfigure = EINA_FALSE; 1548 Eina_Bool need_reconfigure = EINA_FALSE;
1513 Eina_Bool dbg; 1549 Eina_Bool dbg;
1514 1550
@@ -1537,25 +1573,6 @@ evgl_surface_create(void *eng_data, Evas_GL_Config *cfg, int w, int h)
1537 return NULL; 1573 return NULL;
1538 } 1574 }
1539 1575
1540 // Check for Direct rendering override env var.
1541 if (!evgl_engine->direct_override)
1542 if ((s = getenv("EVAS_GL_DIRECT_OVERRIDE")))
1543 {
1544 direct_override = atoi(s);
1545 if (direct_override == 1)
1546 evgl_engine->direct_override = 1;
1547 }
1548
1549 // Check if Direct Rendering Memory Optimzation flag is on
1550 // Creates resources on demand when it fallsback to fbo rendering
1551 if (!evgl_engine->direct_mem_opt)
1552 if ((s = getenv("EVAS_GL_DIRECT_MEM_OPT")))
1553 {
1554 direct_mem_opt = atoi(s);
1555 if (direct_mem_opt == 1)
1556 evgl_engine->direct_mem_opt = 1;
1557 }
1558
1559 // Allocate surface structure 1576 // Allocate surface structure
1560 sfc = calloc(1, sizeof(EVGL_Surface)); 1577 sfc = calloc(1, sizeof(EVGL_Surface));
1561 if (!sfc) 1578 if (!sfc)
@@ -1629,6 +1646,12 @@ evgl_surface_create(void *eng_data, Evas_GL_Config *cfg, int w, int h)
1629 LKL(evgl_engine->resource_lock); 1646 LKL(evgl_engine->resource_lock);
1630 evgl_engine->surfaces = eina_list_prepend(evgl_engine->surfaces, sfc); 1647 evgl_engine->surfaces = eina_list_prepend(evgl_engine->surfaces, sfc);
1631 1648
1649 if (sfc->direct_fb_opt)
1650 {
1651 eina_hash_add(evgl_engine->direct_surfaces, &sfc->color_buf, sfc);
1652 DBG("Added tex %d as direct surface: %p", sfc->color_buf, sfc);
1653 }
1654
1632 if (sfc->direct_fb_opt && 1655 if (sfc->direct_fb_opt &&
1633 (sfc->depth_fmt || sfc->stencil_fmt || sfc->depth_stencil_fmt)) 1656 (sfc->depth_fmt || sfc->stencil_fmt || sfc->depth_stencil_fmt))
1634 { 1657 {
@@ -1776,6 +1799,7 @@ evgl_surface_destroy(void *eng_data, EVGL_Surface *sfc)
1776 EVGL_Resource *rsc; 1799 EVGL_Resource *rsc;
1777 Eina_Bool need_reconfigure = EINA_FALSE; 1800 Eina_Bool need_reconfigure = EINA_FALSE;
1778 Eina_Bool dbg; 1801 Eina_Bool dbg;
1802 GLuint texid;
1779 1803
1780 // FIXME: This does some make_current(0,0) which may have side effects 1804 // FIXME: This does some make_current(0,0) which may have side effects
1781 1805
@@ -1842,6 +1866,7 @@ evgl_surface_destroy(void *eng_data, EVGL_Surface *sfc)
1842 1866
1843 1867
1844 // Destroy created buffers 1868 // Destroy created buffers
1869 texid = sfc->color_buf;
1845 if (!_surface_buffers_destroy(sfc)) 1870 if (!_surface_buffers_destroy(sfc))
1846 { 1871 {
1847 ERR("Error deleting surface resources."); 1872 ERR("Error deleting surface resources.");
@@ -1875,6 +1900,12 @@ evgl_surface_destroy(void *eng_data, EVGL_Surface *sfc)
1875 LKL(evgl_engine->resource_lock); 1900 LKL(evgl_engine->resource_lock);
1876 evgl_engine->surfaces = eina_list_remove(evgl_engine->surfaces, sfc); 1901 evgl_engine->surfaces = eina_list_remove(evgl_engine->surfaces, sfc);
1877 1902
1903 if (sfc->direct_fb_opt)
1904 {
1905 eina_hash_del(evgl_engine->direct_surfaces, &texid, sfc);
1906 DBG("Removed tex %d from the direct surface: %p", texid, sfc);
1907 }
1908
1878 if (sfc->direct_fb_opt && 1909 if (sfc->direct_fb_opt &&
1879 (sfc->depth_fmt || sfc->stencil_fmt || sfc->depth_stencil_fmt)) 1910 (sfc->depth_fmt || sfc->stencil_fmt || sfc->depth_stencil_fmt))
1880 { 1911 {
@@ -2369,23 +2400,77 @@ evgl_direct_rendered()
2369 return rsc->direct.rendered; 2400 return rsc->direct.rendered;
2370} 2401}
2371 2402
2403/*
2404 * This function can tell the engine whether a surface can be directly
2405 * rendered to the Evas, despite any window rotation. For that purpose,
2406 * we let the engine know the surface flags for this texture
2407 */
2408Eina_Bool
2409evgl_native_surface_direct_opts_get(Evas_Native_Surface *ns,
2410 Eina_Bool *direct_render,
2411 Eina_Bool *client_side_rotation)
2412{
2413 EVGL_Surface *sfc;
2414
2415 if (direct_render) *direct_render = EINA_FALSE;
2416 if (client_side_rotation) *client_side_rotation = EINA_FALSE;
2417
2418 if (!evgl_engine) return EINA_FALSE;
2419 if (!ns || (ns->type != EVAS_NATIVE_SURFACE_OPENGL)) return EINA_FALSE;
2420 if (ns->data.opengl.framebuffer_id != 0) return EINA_FALSE;
2421 if (ns->data.opengl.texture_id == 0) return EINA_FALSE;
2422
2423 sfc = eina_hash_find(evgl_engine->direct_surfaces, &ns->data.opengl.texture_id);
2424 if (!sfc)
2425 {
2426 DBG("Native surface %p (color_buf %d) was not found.",
2427 ns, ns->data.opengl.texture_id);
2428 return EINA_FALSE;
2429 }
2430
2431 if (evgl_engine->api_debug_mode)
2432 {
2433 DBG("Found native surface: texid:%u DR:%d CSR:%d",
2434 ns->data.opengl.texture_id, (int) sfc->direct_fb_opt,
2435 (int) sfc->client_side_rotation);
2436 }
2437
2438 if (direct_render) *direct_render = sfc->direct_fb_opt;
2439 if (client_side_rotation) *client_side_rotation = sfc->client_side_rotation;
2440 return EINA_TRUE;
2441}
2442
2372void 2443void
2373evgl_direct_info_set(int win_w, int win_h, int rot, 2444evgl_direct_info_set(int win_w, int win_h, int rot,
2374 int img_x, int img_y, int img_w, int img_h, 2445 int img_x, int img_y, int img_w, int img_h,
2375 int clip_x, int clip_y, int clip_w, int clip_h) 2446 int clip_x, int clip_y, int clip_w, int clip_h,
2447 unsigned int texid)
2376{ 2448{
2377 EVGL_Resource *rsc; 2449 EVGL_Resource *rsc;
2450 EVGL_Surface *sfc;
2378 2451
2379 if (!(rsc=_evgl_tls_resource_get())) return; 2452 if (!(rsc = _evgl_tls_resource_get()))
2380 2453 return;
2381 /* Normally direct rendering isn't allowed if rotation is not 0. 2454
2382 * BUT, if client_side_rotation or override is on, allow it. 2455 /* Check for direct rendering
2456 *
2457 * DR is allowed iif:
2458 * - Rotation == 0
2459 * OR: - Client-Side Rotation is set on the surface
2460 * - Direct Override is set
2461 *
2462 * If the surface is not found, we assume indirect rendering.
2383 */ 2463 */
2384 if ((rot == 0) || evgl_engine->direct_override || 2464
2385 (rsc->current_ctx && 2465 sfc = eina_hash_find(evgl_engine->direct_surfaces, &texid);
2386 rsc->current_ctx->current_sfc && 2466
2387 rsc->current_ctx->current_sfc->client_side_rotation)) 2467 if ((rot == 0) ||
2468 evgl_engine->direct_override ||
2469 (sfc && sfc->client_side_rotation))
2388 { 2470 {
2471 if (evgl_engine->api_debug_mode)
2472 DBG("Direct rendering is enabled.");
2473
2389 rsc->direct.enabled = EINA_TRUE; 2474 rsc->direct.enabled = EINA_TRUE;
2390 2475
2391 rsc->direct.win_w = win_w; 2476 rsc->direct.win_w = win_w;
@@ -2404,6 +2489,9 @@ evgl_direct_info_set(int win_w, int win_h, int rot,
2404 } 2489 }
2405 else 2490 else
2406 { 2491 {
2492 if (evgl_engine->api_debug_mode)
2493 DBG("Direct rendering is disabled.");
2494
2407 rsc->direct.enabled = EINA_FALSE; 2495 rsc->direct.enabled = EINA_FALSE;
2408 } 2496 }
2409} 2497}
@@ -2459,8 +2547,8 @@ evgl_direct_partial_info_clear()
2459void 2547void
2460evgl_direct_override_get(int *override, int *force_off) 2548evgl_direct_override_get(int *override, int *force_off)
2461{ 2549{
2462 *override = evgl_engine->direct_override; 2550 if (override) *override = evgl_engine->direct_override;
2463 *force_off = evgl_engine->direct_force_off; 2551 if (force_off) *force_off = evgl_engine->direct_force_off;
2464} 2552}
2465 2553
2466void 2554void
diff --git a/src/modules/evas/engines/gl_common/evas_gl_core.h b/src/modules/evas/engines/gl_common/evas_gl_core.h
index f74a9c1656..9dcb5bb0f1 100644
--- a/src/modules/evas/engines/gl_common/evas_gl_core.h
+++ b/src/modules/evas/engines/gl_common/evas_gl_core.h
@@ -40,9 +40,14 @@ int evgl_direct_rendered();
40void evgl_direct_override_get(int *override, int *force_off); 40void evgl_direct_override_get(int *override, int *force_off);
41void evgl_direct_info_set(int win_w, int win_h, int rot, 41void evgl_direct_info_set(int win_w, int win_h, int rot,
42 int img_x, int img_y, int img_w, int img_h, 42 int img_x, int img_y, int img_w, int img_h,
43 int clip_x, int clip_y, int clip_w, int clip_h); 43 int clip_x, int clip_y, int clip_w, int clip_h,
44 unsigned int texid);
44void evgl_direct_info_clear(); 45void evgl_direct_info_clear();
45 46
47Eina_Bool evgl_native_surface_direct_opts_get(Evas_Native_Surface *ns,
48 Eina_Bool *direct_render,
49 Eina_Bool *client_side_rotation);
50
46void evgl_direct_partial_info_set(int pres); 51void evgl_direct_partial_info_set(int pres);
47void evgl_direct_partial_info_clear(); 52void evgl_direct_partial_info_clear();
48void evgl_direct_partial_render_start(); 53void evgl_direct_partial_render_start();
diff --git a/src/modules/evas/engines/gl_common/evas_gl_core_private.h b/src/modules/evas/engines/gl_common/evas_gl_core_private.h
index ec30529073..a13d36904e 100644
--- a/src/modules/evas/engines/gl_common/evas_gl_core_private.h
+++ b/src/modules/evas/engines/gl_common/evas_gl_core_private.h
@@ -294,6 +294,8 @@ struct _EVGL_Engine
294 294
295 int direct_override; 295 int direct_override;
296 int direct_mem_opt; 296 int direct_mem_opt;
297
298 // Add more debug logs (DBG levels 4 and 6)
297 int api_debug_mode; 299 int api_debug_mode;
298 300
299 // Force Off for Debug purposes 301 // Force Off for Debug purposes
@@ -305,6 +307,7 @@ struct _EVGL_Engine
305 // Keep track of all the current surfaces/contexts 307 // Keep track of all the current surfaces/contexts
306 Eina_List *surfaces; 308 Eina_List *surfaces;
307 Eina_List *contexts; 309 Eina_List *contexts;
310 Eina_Hash *direct_surfaces; // unsigned (texid) --> EVGL_Surface*
308 Eina_List *direct_depth_stencil_surfaces; 311 Eina_List *direct_depth_stencil_surfaces;
309 312
310 //void *engine_data; 313 //void *engine_data;
diff --git a/src/modules/evas/engines/gl_generic/evas_engine.c b/src/modules/evas/engines/gl_generic/evas_engine.c
index 6371fe79f6..45d35ea587 100644
--- a/src/modules/evas/engines/gl_generic/evas_engine.c
+++ b/src/modules/evas/engines/gl_generic/evas_engine.c
@@ -818,8 +818,6 @@ eng_image_draw(void *data, void *context, void *surface, void *image, int src_x,
818 (n->data.opengl.framebuffer_id == 0) && 818 (n->data.opengl.framebuffer_id == 0) &&
819 re->func.get_pixels) 819 re->func.get_pixels)
820 { 820 {
821 DBG("Rendering Directly to the window: %p", data);
822
823 gl_context->dc = context; 821 gl_context->dc = context;
824 if ((gl_context->master_clip.enabled) && 822 if ((gl_context->master_clip.enabled) &&
825 (gl_context->master_clip.w > 0) && 823 (gl_context->master_clip.w > 0) &&
@@ -837,7 +835,8 @@ eng_image_draw(void *data, void *context, void *surface, void *image, int src_x,
837 gl_context->dc->clip.x, 835 gl_context->dc->clip.x,
838 gl_context->dc->clip.y, 836 gl_context->dc->clip.y,
839 gl_context->dc->clip.w, 837 gl_context->dc->clip.w,
840 gl_context->dc->clip.h); 838 gl_context->dc->clip.h,
839 n->data.opengl.texture_id);
841 840
842 // Call pixel get function 841 // Call pixel get function
843 re->func.get_pixels(re->func.get_pixels_data, re->func.obj); 842 re->func.get_pixels(re->func.get_pixels_data, re->func.obj);
@@ -1245,6 +1244,26 @@ eng_gl_direct_override_get(void *data, int *override, int *force_off)
1245 evgl_direct_override_get(override, force_off); 1244 evgl_direct_override_get(override, force_off);
1246} 1245}
1247 1246
1247static Eina_Bool
1248eng_gl_surface_direct_renderable_get(void *data, Evas_Native_Surface *ns)
1249{
1250 Render_Engine_GL_Generic *re = data;
1251 Eina_Bool direct_render, client_side_rotation;
1252
1253 EVGLINIT(data, EINA_FALSE);
1254 if (!re || !ns) return EINA_FALSE;
1255 if (!evgl_native_surface_direct_opts_get(ns, &direct_render, &client_side_rotation))
1256 return EINA_FALSE;
1257
1258 if (!direct_render)
1259 return EINA_FALSE;
1260
1261 if ((re->software.outbuf_get_rot(re->software.ob) != 0) && (!client_side_rotation))
1262 return EINA_FALSE;
1263
1264 return EINA_TRUE;
1265}
1266
1248static void 1267static void
1249eng_gl_get_pixels_set(void *data, void *get_pixels, void *get_pixels_data, void *obj) 1268eng_gl_get_pixels_set(void *data, void *get_pixels, void *get_pixels_data, void *obj)
1250{ 1269{
@@ -1926,6 +1945,7 @@ module_open(Evas_Module *em)
1926 ORD(gl_native_surface_get); 1945 ORD(gl_native_surface_get);
1927 ORD(gl_api_get); 1946 ORD(gl_api_get);
1928 ORD(gl_direct_override_get); 1947 ORD(gl_direct_override_get);
1948 ORD(gl_surface_direct_renderable_get);
1929 ORD(gl_get_pixels_set); 1949 ORD(gl_get_pixels_set);
1930 ORD(gl_surface_lock); 1950 ORD(gl_surface_lock);
1931 ORD(gl_surface_read_pixels); 1951 ORD(gl_surface_read_pixels);
diff --git a/src/modules/evas/engines/software_generic/evas_engine.c b/src/modules/evas/engines/software_generic/evas_engine.c
index f2a355aab7..ac9e086b0d 100644
--- a/src/modules/evas/engines/software_generic/evas_engine.c
+++ b/src/modules/evas/engines/software_generic/evas_engine.c
@@ -3098,6 +3098,7 @@ static Evas_Func func =
3098 NULL, // need software mesa for gl rendering <- gl_current_surface_get 3098 NULL, // need software mesa for gl rendering <- gl_current_surface_get
3099 NULL, // need software mesa for gl rendering <- gl_rotation_angle_get 3099 NULL, // need software mesa for gl rendering <- gl_rotation_angle_get
3100 NULL, // need software mesa for gl rendering <- gl_surface_query 3100 NULL, // need software mesa for gl rendering <- gl_surface_query
3101 NULL, // need software mesa for gl rendering <- gl_surface_direct_renderable_get
3101 eng_image_load_error_get, 3102 eng_image_load_error_get,
3102 eng_font_run_font_end_get, 3103 eng_font_run_font_end_get,
3103 eng_image_animated_get, 3104 eng_image_animated_get,
@@ -3106,7 +3107,7 @@ static Evas_Func func =
3106 eng_image_animated_loop_count_get, 3107 eng_image_animated_loop_count_get,
3107 eng_image_animated_frame_duration_get, 3108 eng_image_animated_frame_duration_get,
3108 eng_image_animated_frame_set, 3109 eng_image_animated_frame_set,
3109 NULL, 3110 NULL, // image_max_size_get
3110 eng_multi_font_draw, 3111 eng_multi_font_draw,
3111 eng_pixel_alpha_get, 3112 eng_pixel_alpha_get,
3112 NULL, // eng_context_flush - software doesn't use it 3113 NULL, // eng_context_flush - software doesn't use it