diff --git a/m4/evas_check_engine.m4 b/m4/evas_check_engine.m4 index b385076cb8..a7e00851ec 100644 --- a/m4/evas_check_engine.m4 +++ b/m4/evas_check_engine.m4 @@ -393,6 +393,7 @@ window = [[NSWindow alloc] [ have_dep="yes" evas_engine_[]$1[]_libs="-framework Cocoa -framework OpenGL" + evas_engine_gl_common_libs="$evas_engine_[]$1[]_libdirs" ], [have_dep="no"]) LIBS="$LIBS_save" diff --git a/src/Makefile_Evas.am b/src/Makefile_Evas.am index 0695e0a19b..e86f8617bc 100644 --- a/src/Makefile_Evas.am +++ b/src/Makefile_Evas.am @@ -903,6 +903,9 @@ endif if BUILD_ENGINE_EGLFS modules_evas_engines_gl_common_libevas_engine_gl_common_la_CPPFLAGS += @evas_engine_eglfs_cflags@ endif +if BUILD_ENGINE_GL_COCOA +modules_evas_engines_gl_common_libevas_engine_gl_common_la_CPPFLAGS += @evas_engine_gl_cocoa_cflags@ +endif modules_evas_engines_gl_common_libevas_engine_gl_common_la_LIBADD = @USE_EVAS_LIBS@ modules_evas_engines_gl_common_libevas_engine_gl_common_la_DEPENDENCIES = @USE_EVAS_INTERNAL_LIBS@ modules_evas_engines_gl_common_libevas_engine_gl_common_la_LDFLAGS = -module @EFL_LTMODULE_FLAGS@ @@ -915,12 +918,11 @@ dist_installed_evasmainheaders_DATA += modules/evas/engines/gl_cocoa/Evas_Engine GL_COCOA_SOURCES = \ modules/evas/engines/gl_cocoa/evas_engine.c \ modules/evas/engines/gl_cocoa/evas_outbuf.m \ -modules/evas/engines/gl_cocoa/evas_engine.h +modules/evas/engines/gl_cocoa/evas_engine.h \ +modules/evas/engines/gl_cocoa/Evas_Engine_GL_Cocoa.h if EVAS_STATIC_BUILD_GL_COCOA lib_evas_libevas_la_SOURCES += $(GL_COCOA_SOURCES) -lib_evas_libevas_la_CPPFLAGS += \ --I$(top_srcdir)/src/modules/evas/engines/gl_common \ -@evas_engine_gl_cocoa_cflags@ +lib_evas_libevas_la_CPPFLAGS += @evas_engine_gl_cocoa_cflags@ lib_evas_libevas_la_LIBADD += @evas_engine_gl_cocoa_libs@ else engineglcocoapkgdir = $(libdir)/evas/modules/engines/gl_cocoa/$(MODULE_ARCH) @@ -935,20 +937,13 @@ modules_evas_engines_gl_cocoa_module_la_SOURCES = $(GL_COCOA_SOURCES) modules_evas_engines_gl_cocoa_module_la_CPPFLAGS = -I$(top_builddir)/src/lib/efl \ -I$(top_srcdir)/src/lib/evas/include \ -I$(top_srcdir)/src/lib/evas/cserve2 \ --I$(top_srcdir)/src/modules/evas/engines/gl_common \ @EVAS_CFLAGS@ \ @evas_engine_gl_cocoa_cflags@ -modules_evas_engines_gl_cocoa_module_la_LIBADD = -if ! EVAS_STATIC_BUILD_GL_COMMON -modules_evas_engines_gl_cocoa_module_la_LIBADD += \ -modules/evas/engines/gl_common/libevas_engine_gl_common.la -endif -modules_evas_engines_gl_cocoa_module_la_LIBADD += \ +modules_evas_engines_gl_cocoa_module_la_LIBADD = \ @USE_EVAS_LIBS@ \ @evas_engine_gl_cocoa_libs@ modules_evas_engines_gl_cocoa_module_la_DEPENDENCIES = \ -@USE_EVAS_INTERNAL_LIBS@ \ -modules/evas/engines/gl_common/libevas_engine_gl_common.la +@USE_EVAS_INTERNAL_LIBS@ modules_evas_engines_gl_cocoa_module_la_LDFLAGS = -module @EFL_LTMODULE_FLAGS@ modules_evas_engines_gl_cocoa_module_la_LIBTOOLFLAGS = --tag=disable-static endif diff --git a/src/modules/evas/engines/gl_cocoa/evas_engine.c b/src/modules/evas/engines/gl_cocoa/evas_engine.c index d4c2f371d5..20311669d1 100644 --- a/src/modules/evas/engines/gl_cocoa/evas_engine.c +++ b/src/modules/evas/engines/gl_cocoa/evas_engine.c @@ -13,23 +13,114 @@ Evas_GL_Common_Context_New glsym_evas_gl_common_context_new = NULL; Evas_GL_Common_Context_Call glsym_evas_gl_common_context_free = NULL; Evas_GL_Common_Context_Call glsym_evas_gl_common_context_flush = NULL; Evas_GL_Common_Context_Call glsym_evas_gl_common_context_use = NULL; +Evas_GL_Common_Context_Call glsym_evas_gl_common_context_done = NULL; Evas_GL_Common_Context_Resize_Call glsym_evas_gl_common_context_resize = NULL; +Evas_GL_Common_Context_Call glsym_evas_gl_common_context_newframe = NULL; +Evas_GL_Preload_Render_Call glsym_evas_gl_preload_render_lock = NULL; +Evas_GL_Preload_Render_Call glsym_evas_gl_preload_render_unlock = NULL; +static Evas_GL_Preload glsym_evas_gl_preload_init = NULL; +static Evas_GL_Preload glsym_evas_gl_preload_shutdown = NULL; int _evas_engine_gl_cocoa_log_dom = -1; /* function tables - filled in later (func and parent func) */ static Evas_Func func, pfunc; -/* Function table for GL APIs */ -static Evas_GL_API gl_funcs; - static Eina_Bool _initted = EINA_FALSE; -Eina_Bool _need_context_restore = EINA_FALSE; +static int _gl_wins = 0; -void -_context_restore(void) + +static void * +evgl_eng_native_window_create(void *data EINA_UNUSED) { + GL_COCOA_UNIMPLEMENTED_CALL_SO_RETURN(NULL); } +static int +evgl_eng_native_window_destroy(void *data EINA_UNUSED, + void *native_window EINA_UNUSED) +{ + GL_COCOA_UNIMPLEMENTED_CALL_SO_RETURN(1); +} + +static void * +evgl_eng_window_surface_create(void *data EINA_UNUSED, + void *native_window EINA_UNUSED) +{ + GL_COCOA_UNIMPLEMENTED_CALL_SO_RETURN(NULL); +} + +static int +evgl_eng_window_surface_destroy(void *data EINA_UNUSED, + void *surface EINA_UNUSED) +{ + GL_COCOA_UNIMPLEMENTED_CALL_SO_RETURN(1); +} + +static void * +evgl_eng_context_create(void *data EINA_UNUSED, + void *share_ctx EINA_UNUSED, + Evas_GL_Context_Version version EINA_UNUSED) +{ + GL_COCOA_UNIMPLEMENTED_CALL_SO_RETURN(NULL); +} + +static int +evgl_eng_context_destroy(void *data EINA_UNUSED, + void *context EINA_UNUSED) +{ + GL_COCOA_UNIMPLEMENTED_CALL_SO_RETURN(1); +} + +static int +evgl_eng_make_current(void *data EINA_UNUSED, + void *surface EINA_UNUSED, + void *context EINA_UNUSED, + int flush EINA_UNUSED) +{ + GL_COCOA_UNIMPLEMENTED_CALL_SO_RETURN(EINA_FALSE); +} + +static void * +evgl_eng_proc_address_get(const char *name EINA_UNUSED) +{ + GL_COCOA_UNIMPLEMENTED_CALL_SO_RETURN(NULL); +} + +static const char * +evgl_eng_string_get(void *data EINA_UNUSED) +{ + GL_COCOA_UNIMPLEMENTED_CALL_SO_RETURN(NULL); +} + +static int +evgl_eng_rotation_angle_get(void *data EINA_UNUSED) +{ + GL_COCOA_UNIMPLEMENTED_CALL_SO_RETURN(0); +} + +static const EVGL_Interface evgl_funcs = +{ + NULL, + NULL, + evgl_eng_native_window_create, + evgl_eng_native_window_destroy, + evgl_eng_window_surface_create, + evgl_eng_window_surface_destroy, + evgl_eng_context_create, + evgl_eng_context_destroy, + evgl_eng_make_current, + evgl_eng_proc_address_get, + evgl_eng_string_get, + evgl_eng_rotation_angle_get, + NULL, // PBuffer + NULL, // PBuffer + NULL, // OpenGL-ES 1 + NULL, // OpenGL-ES 1 + NULL, // OpenGL-ES 1 + NULL, // native_win_surface_config_get +}; + + static void * eng_info(Evas *e EINA_UNUSED) { @@ -38,7 +129,7 @@ eng_info(Evas *e EINA_UNUSED) info = calloc(1, sizeof(*info)); if (EINA_UNLIKELY(!info)) { - CRI("Faield to allocate memory"); + CRI("Failed to allocate memory"); return NULL; } info->magic.magic = rand(); @@ -61,8 +152,8 @@ eng_setup(Evas *evas, void *in) Evas_Public_Data *e; Render_Engine *re = NULL; Outbuf *ob; + Eina_Bool chk; - DBG("Engine Setup"); e = efl_data_scope_get(evas, EVAS_CANVAS_CLASS); if (EINA_UNLIKELY(!e)) { @@ -77,7 +168,7 @@ eng_setup(Evas *evas, void *in) if (!_initted) { evas_common_init(); - // TODO gl_preload_init() + glsym_evas_gl_preload_init(); _initted = EINA_TRUE; } @@ -88,29 +179,56 @@ eng_setup(Evas *evas, void *in) goto err; } - ob = evas_outbuf_new(info, - e->output.w, - e->output.h); + ob = evas_outbuf_new(info, + e->output.w, + e->output.h); if (EINA_UNLIKELY(!ob)) { CRI("Failed to create outbuf"); goto err; } - re->win = ob; // FIXME REMVOE ME + ob->evas = evas; info->view = ob->ns_gl_view; + + chk = evas_render_engine_gl_generic_init(&re->generic, ob, + evas_outbuf_buffer_state_get, + evas_outbuf_rot_get, + evas_outbuf_reconfigure, + evas_outbuf_update_region_first_rect, + NULL, + evas_outbuf_update_region_new, + evas_outbuf_update_region_push, + evas_outbuf_update_region_free, + NULL, + evas_outbuf_flush, + evas_outbuf_free, + evas_outbuf_use, + evas_outbuf_gl_context_get, + evas_outbuf_egl_display_get, + evas_outbuf_gl_context_new, + evas_outbuf_gl_context_use, + &evgl_funcs, ob->w, ob->h); + if (EINA_UNLIKELY(!ob)) + { + CRI("Failed to initialize gl_generic"); + evas_outbuf_free(re->win); + goto err; + } + re->win = ob; e->engine.data.output = re; + _gl_wins++; } else { - re = e->engine.data.output; - evas_outbuf_free(re->win); - re->win = evas_outbuf_new(info, - e->output.w, - e->output.h); - info->view = re->win->ns_gl_view; + CRI("ALREADY A DATA OUTPUT. THIS PART IS NOT IMPLEMENTED YET. PLEASE REPORT."); + return 0; + } + if (EINA_UNLIKELY(!e->engine.data.output)) + { + CRI("Failed to create a data output"); + return 0; } - if (!e->engine.data.output) return 0; if (!e->engine.data.context) e->engine.data.context = @@ -126,1184 +244,63 @@ err: static void eng_output_free(void *data) { - Render_Engine *re; + Render_Engine *const re = data; - DBG("Output free"); - re = (Render_Engine *)data; evas_outbuf_free(re->win); free(re); - if (_initted) + _gl_wins--; + if (_initted && (_gl_wins == 0)) { - // TODO gl_preload_shutdown + glsym_evas_gl_preload_shutdown(); evas_common_shutdown(); _initted = EINA_FALSE; } } -static void -eng_output_resize(void *data, int w, int h) -{ - Render_Engine *re; - - DBG("Output Resize %d %d", w, h); - - re = (Render_Engine *)data; - re->win->width = w; - re->win->height = h; - - evas_gl_common_context_resize(re->win->gl_context, w, h, 0); - evas_outbuf_resize(re->win, w, h); -} - -static void -eng_output_tile_size_set(void *data EINA_UNUSED, int w EINA_UNUSED, int h EINA_UNUSED) -{ - DBG("tile size set"); -} - -static void -eng_output_redraws_rect_add(void *data, int x, int y, int w, int h) -{ - Render_Engine *re; - - DBG("Redraw rect %d %d %d %d", x, y, w, h); - re = (Render_Engine *)data; - evas_outbuf_lock_focus(re->win); - evas_gl_common_context_resize(re->win->gl_context, re->win->width, re->win->height, 0); - /* simple bounding box */ - RECTS_CLIP_TO_RECT(x, y, w, h, 0, 0, re->win->width, re->win->height); - if ((w <= 0) || (h <= 0)) goto end; - if (!re->win->draw.redraw) - { -#if 0 - re->win->draw.x1 = x; - re->win->draw.y1 = y; - re->win->draw.x2 = x + w - 1; - re->win->draw.y2 = y + h - 1; -#else - re->win->draw.x1 = 0; - re->win->draw.y1 = 0; - re->win->draw.x2 = re->win->width - 1; - re->win->draw.y2 = re->win->height - 1; -#endif - } - else - { - if (x < re->win->draw.x1) re->win->draw.x1 = x; - if (y < re->win->draw.y1) re->win->draw.y1 = y; - if ((x + w - 1) > re->win->draw.x2) re->win->draw.x2 = x + w - 1; - if ((y + h - 1) > re->win->draw.y2) re->win->draw.y2 = y + h - 1; - } - re->win->draw.redraw = 1; -end: - evas_outbuf_unlock_focus(re->win); -} - -static void -eng_output_redraws_rect_del(void *data EINA_UNUSED, int x EINA_UNUSED, int y EINA_UNUSED, int w EINA_UNUSED, int h EINA_UNUSED) -{ -} - -static void -eng_output_redraws_clear(void *data) -{ - Render_Engine *re; - - re = (Render_Engine *)data; - re->win->draw.redraw = 0; -} - -//#define SLOW_GL_COPY_RECT 1 -/* vsync games - not for now though */ -#define VSYNC_TO_SCREEN 1 - -static void * -eng_output_redraws_next_update_get(void *data, int *x, int *y, int *w, int *h, int *cx, int *cy, int *cw, int *ch) -{ - Render_Engine *re; - - re = (Render_Engine *)data; - evas_gl_common_context_flush(re->win->gl_context); - evas_gl_common_context_newframe(re->win->gl_context); - /* get the upate rect surface - return engine data as dummy */ - if (!re->win->draw.redraw) - { - // printf("GL: NO updates!\n"); - return NULL; - } - // printf("GL: update....!\n"); -#ifdef SLOW_GL_COPY_RECT - /* if any update - just return the whole canvas - works with swap - * buffers then */ - if (x) *x = 0; - if (y) *y = 0; - if (w) *w = re->win->width; - if (h) *h = re->win->height; - if (cx) *cx = 0; - if (cy) *cy = 0; - if (cw) *cw = re->win->width; - if (ch) *ch = re->win->height; -#else - /* 1 update - INCREDIBLY SLOW if combined with swap_rect in flush. a gl - * problem where there just is no hardware path for somethnig that - * obviously SHOULD be there */ - /* only 1 update to minimise gl context games and rendering multiple update - * regions as evas does with other engines - */ - if (x) *x = re->win->draw.x1; - if (y) *y = re->win->draw.y1; - if (w) *w = re->win->draw.x2 - re->win->draw.x1 + 1; - if (h) *h = re->win->draw.y2 - re->win->draw.y1 + 1; - if (cx) *cx = re->win->draw.x1; - if (cy) *cy = re->win->draw.y1; - if (cw) *cw = re->win->draw.x2 - re->win->draw.x1 + 1; - if (ch) *ch = re->win->draw.y2 - re->win->draw.y1 + 1; -#endif - // clear buffer. only needed for dest alpha - // glClearColor(0.0f, 0.0f, 0.0f, 0.0f); - // glClear(GL_COLOR_BUFFER_BIT); - //x// printf("frame -> new\n"); - return re->win->gl_context->def_surface; -} - -static void -eng_output_redraws_next_update_push(void *data, void *surface EINA_UNUSED, int x EINA_UNUSED, int y EINA_UNUSED, int w EINA_UNUSED, int h EINA_UNUSED, Evas_Render_Mode render_mode) -{ - Render_Engine *re; - - if (render_mode == EVAS_RENDER_MODE_ASYNC_INIT) return; - - re = (Render_Engine *)data; - /* put back update surface.. in this case just unflag redraw */ - re->win->draw.redraw = 0; - re->win->draw.drew = 1; - evas_gl_common_context_flush(re->win->gl_context); -} - -static void -eng_output_flush(void *data, Evas_Render_Mode render_mode) -{ - Render_Engine *re; - - if (render_mode == EVAS_RENDER_MODE_ASYNC_INIT) return; - - re = (Render_Engine *)data; - if (!re->win->draw.drew) return; - - re->win->draw.drew = 0; - evas_outbuf_use(re->win); - -#ifdef VSYNC_TO_SCREEN - evas_outbuf_vsync_set(1); -#endif - evas_outbuf_lock_focus(re->win); - evas_outbuf_swap_buffers(re->win); - evas_outbuf_unlock_focus(re->win); -} - -static void -eng_context_cutout_add(void *data EINA_UNUSED, void *context, int x, int y, int w, int h) -{ - evas_common_draw_context_add_cutout(context, x, y, w, h); -} - -static void -eng_context_cutout_clear(void *data EINA_UNUSED, void *context) -{ - evas_common_draw_context_clear_cutouts(context); -} - -static void -eng_rectangle_draw(void *data, void *context, void *surface, int x, int y, int w, int h, Eina_Bool do_async EINA_UNUSED) -{ - Render_Engine *re; - - re = (Render_Engine *)data; - evas_outbuf_use(re->win); - evas_gl_common_context_target_surface_set(re->win->gl_context, surface); - re->win->gl_context->dc = context; - evas_gl_common_rect_draw(re->win->gl_context, x, y, w, h); -} - -static void -eng_line_draw(void *data, void *context, void *surface, int p1x, int p1y, int p2x, int p2y, Eina_Bool do_async EINA_UNUSED) -{ - Render_Engine *re; - - re = (Render_Engine *)data; - evas_outbuf_use(re->win); - evas_gl_common_context_target_surface_set(re->win->gl_context, surface); - re->win->gl_context->dc = context; - evas_gl_common_line_draw(re->win->gl_context, p1x, p1y, p2x, p2y); -} - -static void * -eng_polygon_point_add(void *data, void *context EINA_UNUSED, void *polygon, int x, int y) -{ - Render_Engine *re; - - re = (Render_Engine *)data; - return evas_gl_common_poly_point_add(polygon, x, y); -} - -static void * -eng_polygon_points_clear(void *data, void *context EINA_UNUSED, void *polygon) -{ - Render_Engine *re; - - re = (Render_Engine *)data; - return evas_gl_common_poly_points_clear(polygon); -} - -static void -eng_polygon_draw(void *data, void *context, void *surface EINA_UNUSED, void *polygon, int x, int y, Eina_Bool do_async EINA_UNUSED) -{ - Render_Engine *re; - - re = (Render_Engine *)data; - evas_outbuf_use(re->win); - evas_gl_common_context_target_surface_set(re->win->gl_context, surface); - re->win->gl_context->dc = context; - evas_gl_common_poly_draw(re->win->gl_context, polygon, x, y); -} - -static int -eng_image_alpha_get(void *data EINA_UNUSED, void *image) -{ - Evas_GL_Image *im; - - if (!image) return 1; - im = image; - return im->alpha; -} - -static Evas_Colorspace -eng_image_colorspace_get(void *data EINA_UNUSED, void *image) -{ - Evas_GL_Image *im; - - if (!image) return EVAS_COLORSPACE_ARGB8888; - im = image; - return im->cs.space; -} - -static void * -eng_image_alpha_set(void *data, void *image, int has_alpha) -{ - Render_Engine *re; - Evas_GL_Image *im; - - re = (Render_Engine *)data; - if (!image) return NULL; - im = image; - if (im->alpha == has_alpha) return image; - if (im->native.data) - { - im->alpha = has_alpha; - return image; - } - evas_outbuf_use(re->win); - if ((im->tex) && (im->tex->pt->dyn.img)) - { - im->alpha = has_alpha; - im->tex->alpha = im->alpha; - return image; - } - /* FIXME: can move to gl_common */ - if (im->cs.space != EVAS_COLORSPACE_ARGB8888) return im; - if ((has_alpha) && (im->im->cache_entry.flags.alpha)) return image; - else if ((!has_alpha) && (!im->im->cache_entry.flags.alpha)) return image; - if (im->references > 1) - { - Evas_GL_Image *im_new; - - if (!im->im->image.data) - evas_cache_image_load_data(&im->im->cache_entry); - evas_gl_common_image_alloc_ensure(im); - im_new = evas_gl_common_image_new_from_copied_data - (im->gc, im->im->cache_entry.w, im->im->cache_entry.h, - im->im->image.data, - eng_image_alpha_get(data, image), - eng_image_colorspace_get(data, image)); - if (!im_new) return im; - evas_gl_common_image_free(im); - im = im_new; - } - else - evas_gl_common_image_dirty(im, 0, 0, 0, 0); - return evas_gl_common_image_alpha_set(im, has_alpha ? 1 : 0); - // im->im->cache_entry.flags.alpha = has_alpha ? 1 : 0; - // return image; -} - -static Evas_Colorspace -eng_image_file_colorspace_get(void *data EINA_UNUSED, void *image) -{ - Evas_GL_Image *im = image; - - if (!im || !im->im) return EVAS_COLORSPACE_ARGB8888; - if (im->im->cache_entry.cspaces) - return im->im->cache_entry.cspaces[0]; - return im->im->cache_entry.space; -} - -static void * -eng_image_data_direct(void *data EINA_UNUSED, void *image, Evas_Colorspace *cspace) -{ - Evas_GL_Image *im = image; - - if (!im || !im->im) return NULL; - if (cspace) *cspace = im->im->cache_entry.space; - return im->im->image.data; -} - -static void -eng_image_colorspace_set(void *data, void *image, Evas_Colorspace cspace) -{ - Render_Engine *re; - Evas_GL_Image *im; - - re = (Render_Engine *)data; - if (!image) return; - im = image; - if (im->native.data) return; - /* FIXME: can move to gl_common */ - if (im->cs.space == cspace) return; - evas_outbuf_use(re->win); - evas_gl_common_image_alloc_ensure(im); - evas_cache_image_colorspace(&im->im->cache_entry, cspace); - switch (cspace) - { - case EVAS_COLORSPACE_ARGB8888: - if (im->cs.data) - { - if (!im->cs.no_free) free(im->cs.data); - im->cs.data = NULL; - im->cs.no_free = 0; - } - break; - case EVAS_COLORSPACE_YCBCR422P601_PL: - case EVAS_COLORSPACE_YCBCR422P709_PL: - case EVAS_COLORSPACE_YCBCR422601_PL: - case EVAS_COLORSPACE_YCBCR420NV12601_PL: - case EVAS_COLORSPACE_YCBCR420TM12601_PL: - if (im->tex) evas_gl_common_texture_free(im->tex, EINA_TRUE); - im->tex = NULL; - if (im->cs.data) - { - if (!im->cs.no_free) free(im->cs.data); - } - if (im->im->cache_entry.h > 0) - im->cs.data = - calloc(1, im->im->cache_entry.h * sizeof(unsigned char *) * 2); - else - im->cs.data = NULL; - im->cs.no_free = 0; - break; - default: - abort(); - break; - } - im->cs.space = cspace; -} - -///////////////////////////////////////////////////////////////////////// -// -// - -// FIXME: this is enabled so updates happen - but its SLOOOOOOOOOOOOOOOW -// (i am sure this is the reason) not to mention seemingly superfluous. but -// i need to enable it for it to work on fglrx at least. havent tried nvidia. -// -// why is this the case? does anyone know? has anyone tried it on other gfx -// drivers? -// -//#define GLX_TEX_PIXMAP_RECREATE 1 - -// -// -///////////////////////////////////////////////////////////////////////// - -static void * -eng_image_load(void *data, const char *file, const char *key, int *error, Evas_Image_Load_Opts *lo) -{ - Render_Engine *re; - - re = (Render_Engine *)data; - *error = EVAS_LOAD_ERROR_NONE; - evas_outbuf_use(re->win); - return evas_gl_common_image_load(re->win->gl_context, file, key, lo, error); -} - -static void * -eng_image_mmap(void *data, Eina_File *f, const char *key, int *error, Evas_Image_Load_Opts *lo) -{ - Render_Engine *re; - - re = (Render_Engine *)data; - *error = EVAS_LOAD_ERROR_NONE; - evas_outbuf_use(re->win); - return evas_gl_common_image_mmap(re->win->gl_context, f, key, lo, error); -} - -static void * -eng_image_new_from_data(void *data, int w, int h, DATA32 *image_data, int alpha, Evas_Colorspace cspace) -{ - Render_Engine *re; - - re = (Render_Engine *)data; - evas_outbuf_use(re->win); - return evas_gl_common_image_new_from_data(re->win->gl_context, w, h, image_data, alpha, cspace); -} - -static void * -eng_image_new_from_copied_data(void *data, int w, int h, DATA32 *image_data, int alpha, Evas_Colorspace cspace) -{ - Render_Engine *re; - - re = (Render_Engine *)data; - evas_outbuf_use(re->win); - return evas_gl_common_image_new_from_copied_data(re->win->gl_context, w, h, image_data, alpha, cspace); -} - -static void -eng_image_free(void *data, void *image) -{ - Render_Engine *re; - - re = (Render_Engine *)data; - if (!image) return; - evas_outbuf_use(re->win); - evas_gl_common_image_unref(image); -} - -static void -eng_image_size_get(void *data EINA_UNUSED, void *image, int *w, int *h) -{ - if (!image) - { - *w = 0; - *h = 0; - return; - } - if (w) *w = ((Evas_GL_Image *)image)->w; - if (h) *h = ((Evas_GL_Image *)image)->h; -} - -static void * -eng_image_size_set(void *data, void *image, int w, int h) -{ - Render_Engine *re; - Evas_GL_Image *im = image; - Evas_GL_Image *im_old; - - re = (Render_Engine *)data; - if (!im) return NULL; - if (im->native.data) - { - im->w = w; - im->h = h; - return image; - } - evas_outbuf_use(re->win); - if ((im->tex) && (im->tex->pt->dyn.img)) - { - evas_gl_common_texture_free(im->tex, EINA_TRUE); - im->tex = NULL; - im->w = w; - im->h = h; - im->tex = evas_gl_common_texture_dynamic_new(im->gc, im); - return image; - } - im_old = image; - - switch (eng_image_colorspace_get(data, image)) - { - case EVAS_COLORSPACE_YCBCR422P601_PL: - case EVAS_COLORSPACE_YCBCR422P709_PL: - case EVAS_COLORSPACE_YCBCR422601_PL: - case EVAS_COLORSPACE_YCBCR420NV12601_PL: - case EVAS_COLORSPACE_YCBCR420TM12601_PL: - w &= ~0x1; - default: - break; - } - - evas_gl_common_image_alloc_ensure(im_old); - if ((im_old->im) && - ((int)im_old->im->cache_entry.w == w) && - ((int)im_old->im->cache_entry.h == h)) - return image; - - im = evas_gl_common_image_new(re->win->gl_context, w, h, - eng_image_alpha_get(data, image), - eng_image_colorspace_get(data, image)); - evas_gl_common_image_free(im_old); - - return im; -} - -static void * -eng_image_dirty_region(void *data, void *image, int x, int y, int w, int h) -{ - Render_Engine *re; - Evas_GL_Image *im = image; - - re = (Render_Engine *)data; - if (!image) return NULL; - if (im->native.data) return image; - evas_outbuf_use(re->win); - evas_gl_common_image_dirty(image, x, y, w, h); - return image; -} - -static void * -eng_image_data_get(void *data, void *image, int to_write, DATA32 **image_data, int *err, Eina_Bool *tofree EINA_UNUSED) -{ - Render_Engine *re; - Evas_GL_Image *im; - int error; - - re = (Render_Engine *)data; - if (!image) - { - *image_data = NULL; - if (err) *err = EVAS_LOAD_ERROR_GENERIC; - return NULL; - } - im = image; - if (im->native.data) - { - *image_data = NULL; - if (err) *err = EVAS_LOAD_ERROR_NONE; - return im; - } - if ((im->tex) && (im->tex->pt) && (im->tex->pt->dyn.data)) - { - *image_data = im->tex->pt->dyn.data; - if (err) *err = EVAS_LOAD_ERROR_NONE; - return im; - } - evas_outbuf_use(re->win); - error = evas_cache_image_load_data(&im->im->cache_entry); - evas_gl_common_image_alloc_ensure(im); - switch (im->cs.space) - { - case EVAS_COLORSPACE_ARGB8888: - if (to_write) - { - if (im->references > 1) - { - Evas_GL_Image *im_new; - - im_new = evas_gl_common_image_new_from_copied_data - (im->gc, im->im->cache_entry.w, im->im->cache_entry.h, - im->im->image.data, - eng_image_alpha_get(data, image), - eng_image_colorspace_get(data, image)); - if (!im_new) - { - *image_data = NULL; - if (err) *err = EVAS_LOAD_ERROR_RESOURCE_ALLOCATION_FAILED; - return im; - } - evas_gl_common_image_free(im); - im = im_new; - } - else - evas_gl_common_image_dirty(im, 0, 0, 0, 0); - } - *image_data = im->im->image.data; - break; - case EVAS_COLORSPACE_YCBCR422P601_PL: - case EVAS_COLORSPACE_YCBCR422P709_PL: - case EVAS_COLORSPACE_YCBCR422601_PL: - case EVAS_COLORSPACE_YCBCR420NV12601_PL: - case EVAS_COLORSPACE_YCBCR420TM12601_PL: - *image_data = im->cs.data; - break; - default: - abort(); - break; - } - if (err) *err = error; - return im; -} - -static void * -eng_image_data_put(void *data, void *image, DATA32 *image_data) -{ - Render_Engine *re; - Evas_GL_Image *im, *im2; - - re = (Render_Engine *)data; - if (!image) return NULL; - im = image; - if (im->native.data) return image; - evas_outbuf_use(re->win); - evas_gl_common_image_alloc_ensure(im); - if ((im->tex) && (im->tex->pt) && (im->tex->pt->dyn.data)) - { - if (im->tex->pt->dyn.data == image_data) - { - return image; - } - else - { - int w, h; - - w = im->im->cache_entry.w; - h = im->im->cache_entry.h; - im2 = eng_image_new_from_data(data, w, h, image_data, - eng_image_alpha_get(data, image), - eng_image_colorspace_get(data, image)); - if (!im2) return im; - evas_gl_common_image_free(im); - im = im2; - evas_gl_common_image_dirty(im, 0, 0, 0, 0); - return im; - } - } - switch (im->cs.space) - { - case EVAS_COLORSPACE_ARGB8888: - if (image_data != im->im->image.data) - { - int w, h; - - w = im->im->cache_entry.w; - h = im->im->cache_entry.h; - im2 = eng_image_new_from_data(data, w, h, image_data, - eng_image_alpha_get(data, image), - eng_image_colorspace_get(data, image)); - if (!im2) return im; - evas_gl_common_image_free(im); - im = im2; - } - break; - case EVAS_COLORSPACE_YCBCR422P601_PL: - case EVAS_COLORSPACE_YCBCR422P709_PL: - if (image_data != im->cs.data) - { - if (im->cs.data) - { - if (!im->cs.no_free) free(im->cs.data); - } - im->cs.data = image_data; - } - break; - default: - abort(); - break; - } - /* hmmm - but if we wrote... why bother? */ - evas_gl_common_image_dirty(im, 0, 0, 0, 0); - return im; -} - -static void -eng_image_data_preload_request(void *data EINA_UNUSED, void *image, const Eo *target) -{ - Evas_GL_Image *gim = image; - RGBA_Image *im; - - if (!gim) return; - if (gim->native.data) return; - im = (RGBA_Image *)gim->im; - if (!im) return; - evas_cache_image_preload_data(&im->cache_entry, target, NULL, NULL, NULL); -} - -static void -eng_image_data_preload_cancel(void *data EINA_UNUSED, void *image, const Eo *target) -{ - Evas_GL_Image *gim = image; - RGBA_Image *im; - - if (!gim) return; - if (gim->native.data) return; - im = (RGBA_Image *)gim->im; - if (!im) return; - evas_cache_image_preload_cancel(&im->cache_entry, target); -} - -static Eina_Bool -eng_image_draw(void *data, void *context, void *surface, void *image, int src_x, int src_y, int src_w, int src_h, int dst_x, int dst_y, int dst_w, int dst_h, int smooth, Eina_Bool do_async EINA_UNUSED) -{ - Render_Engine *re; - - re = (Render_Engine *)data; - if (!image) return EINA_FALSE; - evas_outbuf_use(re->win); - evas_gl_common_context_target_surface_set(re->win->gl_context, surface); - re->win->gl_context->dc = context; - evas_gl_common_image_draw(re->win->gl_context, image, - src_x, src_y, src_w, src_h, - dst_x, dst_y, dst_w, dst_h, - smooth); - return EINA_FALSE; -} - -static void -eng_image_scale_hint_set(void *data EINA_UNUSED, void *image, int hint) -{ - if (image) evas_gl_common_image_scale_hint_set(image, hint); -} - -static int -eng_image_scale_hint_get(void *data EINA_UNUSED, void *image) -{ - Evas_GL_Image *gim = image; - if (!gim) return EVAS_IMAGE_SCALE_HINT_NONE; - return gim->scale_hint; -} - -static Eina_Bool -eng_image_map_draw(void *data, void *context, void *surface, void *image, RGBA_Map *m, int smooth, int level, Eina_Bool do_async) -{ - Evas_GL_Image *gim = image; - Render_Engine *re; - - re = (Render_Engine *)data; - if (!image) return EINA_FALSE; - evas_outbuf_use(re->win); - evas_gl_common_context_target_surface_set(re->win->gl_context, surface); - re->win->gl_context->dc = context; - if (m->count != 4) - { - // FIXME: nash - you didn't fix this - abort(); - } - if ((m->pts[0].x == m->pts[3].x) && - (m->pts[1].x == m->pts[2].x) && - (m->pts[0].y == m->pts[1].y) && - (m->pts[3].y == m->pts[2].y) && - (m->pts[0].x <= m->pts[1].x) && - (m->pts[0].y <= m->pts[2].y) && - (m->pts[0].u == 0) && - (m->pts[0].v == 0) && - (m->pts[1].u == (gim->w << FP)) && - (m->pts[1].v == 0) && - (m->pts[2].u == (gim->w << FP)) && - (m->pts[2].v == (gim->h << FP)) && - (m->pts[3].u == 0) && - (m->pts[3].v == (gim->h << FP)) && - (m->pts[0].col == 0xffffffff) && - (m->pts[1].col == 0xffffffff) && - (m->pts[2].col == 0xffffffff) && - (m->pts[3].col == 0xffffffff)) - { - int dx, dy, dw, dh; - - dx = m->pts[0].x >> FP; - dy = m->pts[0].y >> FP; - dw = (m->pts[2].x >> FP) - dx; - dh = (m->pts[2].y >> FP) - dy; - eng_image_draw(data, context, surface, image, - 0, 0, gim->w, gim->h, dx, dy, dw, dh, smooth, do_async); - } - else - { - evas_gl_common_image_map_draw(re->win->gl_context, image, m->count, &m->pts[0], - smooth, level); - } - - return EINA_FALSE; -} - -static void * -eng_image_map_surface_new(void *data EINA_UNUSED, int w, int h, int alpha) -{ - Render_Engine *re; - - re = (Render_Engine *)data; - return evas_gl_common_image_surface_new(re->win->gl_context, w, h, alpha); -} - -static void -eng_image_content_hint_set(void *data, void *image, int hint) -{ - Render_Engine *re; - re = (Render_Engine *)data; - - if (re) evas_outbuf_use(re->win); - if (image) evas_gl_common_image_content_hint_set(image, hint); -} - -static int -eng_image_content_hint_get(void *data EINA_UNUSED, void *image) -{ - Evas_GL_Image *gim = image; - if (!gim) return EVAS_IMAGE_CONTENT_HINT_NONE; - return gim->content_hint; -} - -static void -eng_image_cache_flush(void *data EINA_UNUSED) -{ - Render_Engine *re; - int tmp_size; - - re = (Render_Engine *)data; - - tmp_size = evas_common_image_get_cache(); - evas_common_image_set_cache(0); - evas_common_rgba_image_scalecache_flush(); - evas_gl_common_image_cache_flush(re->win->gl_context); - evas_common_image_set_cache(tmp_size); -} - -static void -eng_image_cache_set(void *data EINA_UNUSED, int bytes) -{ - Render_Engine *re; - - re = (Render_Engine *)data; - evas_common_image_set_cache(bytes); - evas_common_rgba_image_scalecache_size_set(bytes); - evas_gl_common_image_cache_flush(re->win->gl_context); -} - -static int -eng_image_cache_get(void *data EINA_UNUSED) -{ - Render_Engine *re; - - re = (Render_Engine *)data; - return evas_common_image_get_cache(); -} - - -static void -eng_image_stride_get(void *data EINA_UNUSED, void *image, int *stride) -{ - Evas_GL_Image *im = image; - *stride = im->w * 4; - if ((im->tex) && (im->tex->pt->dyn.img)) - { - *stride = im->tex->pt->dyn.w * 4; - // FIXME: for other image formats (yuv etc.) different stride needed - } -} - -static Eina_Bool -eng_font_draw(void *data, void *context, void *surface, Evas_Font_Set *font EINA_UNUSED, int x, int y, int w EINA_UNUSED, int h EINA_UNUSED, int ow EINA_UNUSED, int oh EINA_UNUSED, Evas_Text_Props *intl_props, Eina_Bool do_async EINA_UNUSED) -{ - Render_Engine *re = data; - evas_outbuf_use(re->win); - - evas_gl_common_context_target_surface_set(re->win->gl_context, surface); - re->win->gl_context->dc = context; - { - if (!re->win->gl_context->font_surface) - re->win->gl_context->font_surface = (RGBA_Image *)evas_cache_image_empty(evas_common_image_cache_get()); - re->win->gl_context->font_surface->cache_entry.w = re->win->gl_context->shared->w; - re->win->gl_context->font_surface->cache_entry.h = re->win->gl_context->shared->h; - - evas_common_draw_context_font_ext_set(context, - re->win->gl_context, - evas_gl_font_texture_new, - evas_gl_font_texture_free, - evas_gl_font_texture_draw, - NULL, - NULL, - NULL); - evas_common_font_draw_prepare(intl_props); - evas_common_font_draw(re->win->gl_context->font_surface, context, x, y, intl_props->glyphs); - evas_common_draw_context_font_ext_set(context, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL); - } - - return EINA_FALSE; -} - - static Eina_Bool eng_canvas_alpha_get(void *data EINA_UNUSED, void *info EINA_UNUSED) { - // FIXME: support ARGB gl targets!!! - return EINA_FALSE; -} - - -#if 1 -static void -evgl_glBindFramebuffer(GLenum target, GLuint framebuffer) -{ - // Add logic to take care when framebuffer=0 - glBindFramebuffer(target, framebuffer); + return EINA_TRUE; } static void -evgl_glBindRenderbuffer(GLenum target, GLuint renderbuffer) +_gl_symbols(void) { - // Add logic to take care when renderbuffer=0 - glBindRenderbuffer(target, renderbuffer); + static Eina_Bool done = EINA_FALSE; + + if (done) return; + +#define LINK2GENERIC(sym) \ + glsym_##sym = dlsym(RTLD_DEFAULT, #sym); + + LINK2GENERIC(evas_gl_common_context_new); + LINK2GENERIC(evas_gl_common_context_flush); + LINK2GENERIC(evas_gl_common_context_free); + LINK2GENERIC(evas_gl_common_context_use); + LINK2GENERIC(evas_gl_common_context_done); + LINK2GENERIC(evas_gl_common_context_resize); + LINK2GENERIC(evas_gl_common_context_newframe); + LINK2GENERIC(evas_gl_preload_render_lock); + LINK2GENERIC(evas_gl_preload_render_unlock); + LINK2GENERIC(evas_gl_preload_init); + LINK2GENERIC(evas_gl_preload_shutdown); + + LINK2GENERIC(evas_gl_symbols); + +#undef LINK2GENERIC + + done = EINA_TRUE; } -static void -evgl_glClearDepthf(GLclampf depth) -{ -#ifdef GL_GLES - glClearDepthf(depth); -#else - glClearDepth(depth); -#endif -} - -static void -evgl_glDepthRangef(GLclampf zNear, GLclampf zFar) -{ -#ifdef GL_GLES - glDepthRangef(zNear, zFar); -#else - glDepthRange(zNear, zFar); -#endif -} - -static void -evgl_glGetShaderPrecisionFormat(GLenum shadertype, GLenum precisiontype, GLint* range, GLint* precision) -{ -#ifdef GL_GLES - glGetShaderPrecisionFormat(shadertype, precisiontype, range, precision); -#else - if (range) - { - range[0] = -126; // floor(log2(FLT_MIN)) - range[1] = 127; // floor(log2(FLT_MAX)) - } - if (precision) - { - precision[0] = 24; // floor(-log2((1.0/16777218.0))); - } - return; - shadertype = precisiontype = 0; -#endif -} - -static void -evgl_glReleaseShaderCompiler(void) -{ -#ifdef GL_GLES - glReleaseShaderCompiler(); -#else -#endif -} - -static void -evgl_glShaderBinary(GLsizei n, const GLuint* shaders, GLenum binaryformat, const void* binary, GLsizei length) -{ -#ifdef GL_GLES - glShaderBinary(n, shaders, binaryformat, binary, length); -#else - // FIXME: need to dlsym/getprocaddress for this - return; - n = binaryformat = length = 0; - shaders = binary = 0; -#endif -} - -#endif - -static void -eng_output_idle_flush(void *data EINA_UNUSED) -{ -} - -static void * -eng_gl_api_get(void *data, int version EINA_UNUSED) -{ - Render_Engine *re; - - re = (Render_Engine *)data; - - gl_funcs.version = EVAS_GL_API_VERSION; -#if 1 -#define ORD(f) EVAS_API_OVERRIDE(f, &gl_funcs, ) - ORD(glActiveTexture); - ORD(glAttachShader); - ORD(glBindAttribLocation); - ORD(glBindBuffer); - ORD(glBindTexture); - ORD(glBlendColor); - ORD(glBlendEquation); - ORD(glBlendEquationSeparate); - ORD(glBlendFunc); - ORD(glBlendFuncSeparate); - ORD(glBufferData); - ORD(glBufferSubData); - ORD(glCheckFramebufferStatus); - ORD(glClear); - ORD(glClearColor); - // ORD(glClearDepthf); - ORD(glClearStencil); - ORD(glColorMask); - ORD(glCompileShader); - ORD(glCompressedTexImage2D); - ORD(glCompressedTexSubImage2D); - ORD(glCopyTexImage2D); - ORD(glCopyTexSubImage2D); - ORD(glCreateProgram); - ORD(glCreateShader); - ORD(glCullFace); - ORD(glDeleteBuffers); - ORD(glDeleteFramebuffers); - ORD(glDeleteProgram); - ORD(glDeleteRenderbuffers); - ORD(glDeleteShader); - ORD(glDeleteTextures); - ORD(glDepthFunc); - ORD(glDepthMask); - // ORD(glDepthRangef); - ORD(glDetachShader); - ORD(glDisable); - ORD(glDisableVertexAttribArray); - ORD(glDrawArrays); - ORD(glDrawElements); - ORD(glEnable); - ORD(glEnableVertexAttribArray); - ORD(glFinish); - ORD(glFlush); - ORD(glFramebufferRenderbuffer); - ORD(glFramebufferTexture2D); - ORD(glFrontFace); - ORD(glGenBuffers); - ORD(glGenerateMipmap); - ORD(glGenFramebuffers); - ORD(glGenRenderbuffers); - ORD(glGenTextures); - ORD(glGetActiveAttrib); - ORD(glGetActiveUniform); - ORD(glGetAttachedShaders); - ORD(glGetAttribLocation); - ORD(glGetBooleanv); - ORD(glGetBufferParameteriv); - ORD(glGetError); - ORD(glGetFloatv); - ORD(glGetFramebufferAttachmentParameteriv); - ORD(glGetIntegerv); - ORD(glGetProgramiv); - ORD(glGetProgramInfoLog); - ORD(glGetRenderbufferParameteriv); - ORD(glGetShaderiv); - ORD(glGetShaderInfoLog); - // ORD(glGetShaderPrecisionFormat); - ORD(glGetShaderSource); - ORD(glGetString); - ORD(glGetTexParameterfv); - ORD(glGetTexParameteriv); - ORD(glGetUniformfv); - ORD(glGetUniformiv); - ORD(glGetUniformLocation); - ORD(glGetVertexAttribfv); - ORD(glGetVertexAttribiv); - ORD(glGetVertexAttribPointerv); - ORD(glHint); - ORD(glIsBuffer); - ORD(glIsEnabled); - ORD(glIsFramebuffer); - ORD(glIsProgram); - ORD(glIsRenderbuffer); - ORD(glIsShader); - ORD(glIsTexture); - ORD(glLineWidth); - ORD(glLinkProgram); - ORD(glPixelStorei); - ORD(glPolygonOffset); - ORD(glReadPixels); - // ORD(glReleaseShaderCompiler); - ORD(glRenderbufferStorage); - ORD(glSampleCoverage); - ORD(glScissor); - // ORD(glShaderBinary); - ORD(glShaderSource); - ORD(glStencilFunc); - ORD(glStencilFuncSeparate); - ORD(glStencilMask); - ORD(glStencilMaskSeparate); - ORD(glStencilOp); - ORD(glStencilOpSeparate); - ORD(glTexImage2D); - ORD(glTexParameterf); - ORD(glTexParameterfv); - ORD(glTexParameteri); - ORD(glTexParameteriv); - ORD(glTexSubImage2D); - ORD(glUniform1f); - ORD(glUniform1fv); - ORD(glUniform1i); - ORD(glUniform1iv); - ORD(glUniform2f); - ORD(glUniform2fv); - ORD(glUniform2i); - ORD(glUniform2iv); - ORD(glUniform3f); - ORD(glUniform3fv); - ORD(glUniform3i); - ORD(glUniform3iv); - ORD(glUniform4f); - ORD(glUniform4fv); - ORD(glUniform4i); - ORD(glUniform4iv); - ORD(glUniformMatrix2fv); - ORD(glUniformMatrix3fv); - ORD(glUniformMatrix4fv); - ORD(glUseProgram); - ORD(glValidateProgram); - ORD(glVertexAttrib1f); - ORD(glVertexAttrib1fv); - ORD(glVertexAttrib2f); - ORD(glVertexAttrib2fv); - ORD(glVertexAttrib3f); - ORD(glVertexAttrib3fv); - ORD(glVertexAttrib4f); - ORD(glVertexAttrib4fv); - ORD(glVertexAttribPointer); - ORD(glViewport); -#undef ORD - - // Override functions wrapped by Evas_GL -#define ORD(f) EVAS_API_OVERRIDE(f, &gl_funcs, evgl_) - ORD(glBindFramebuffer); - ORD(glBindRenderbuffer); - - // GLES2.0 API compat on top of desktop gl - ORD(glClearDepthf); - ORD(glDepthRangef); - ORD(glGetShaderPrecisionFormat); - ORD(glReleaseShaderCompiler); - ORD(glShaderBinary); -#undef ORD - -#endif - - return &gl_funcs; -} - -static int -eng_image_load_error_get(void *data EINA_UNUSED, void *image) -{ - Evas_GL_Image *im; - - if (!image) return EVAS_LOAD_ERROR_NONE; - im = image; - return im->im->cache_entry.load_error; -} static int module_open(Evas_Module *em) { if (!em) return 0; - if (!evas_gl_common_module_open()) return 0; + /* get whatever engine module we inherit from */ - if (!_evas_module_engine_inherit(&pfunc, "software_generic")) return 0; + if (!_evas_module_engine_inherit(&pfunc, "gl_generic")) return 0; if (_evas_engine_gl_cocoa_log_dom < 0) { @@ -1315,8 +312,10 @@ module_open(Evas_Module *em) return 0; } } + /* store it for later use */ func = pfunc; + /* now to override methods */ #define ORD(f) EVAS_API_OVERRIDE(f, &func, eng_) ORD(info); @@ -1324,75 +323,8 @@ module_open(Evas_Module *em) ORD(setup); ORD(canvas_alpha_get); ORD(output_free); - ORD(output_resize); - ORD(output_tile_size_set); - ORD(output_redraws_rect_add); - ORD(output_redraws_rect_del); - ORD(output_redraws_clear); - ORD(output_redraws_next_update_get); - ORD(output_redraws_next_update_push); - ORD(context_cutout_add); - ORD(context_cutout_clear); - ORD(output_flush); - ORD(output_idle_flush); - // ORD(output_dump); - ORD(rectangle_draw); - ORD(line_draw); - ORD(polygon_point_add); - ORD(polygon_points_clear); - ORD(polygon_draw); - ORD(image_load); - ORD(image_mmap); - ORD(image_new_from_data); - ORD(image_new_from_copied_data); - ORD(image_free); - ORD(image_size_get); - ORD(image_size_set); - ORD(image_dirty_region); - ORD(image_data_get); - ORD(image_data_put); - ORD(image_data_direct); - ORD(image_data_preload_request); - ORD(image_data_preload_cancel); - ORD(image_alpha_set); - ORD(image_alpha_get); - ORD(image_draw); - ORD(image_colorspace_set); - ORD(image_colorspace_get); - ORD(image_file_colorspace_get); - // ORD(image_native_set); - // ORD(image_native_get); - - ORD(font_draw); - - ORD(image_scale_hint_set); - ORD(image_scale_hint_get); - ORD(image_stride_get); - - ORD(image_map_draw); - ORD(image_map_surface_new); - - ORD(image_content_hint_set); - ORD(image_content_hint_get); - - ORD(image_cache_flush); - ORD(image_cache_set); - ORD(image_cache_get); - - ORD(gl_api_get); - - ORD(image_load_error_get); - -#define LINK2GENERIC(sym) \ - glsym_##sym = dlsym(RTLD_DEFAULT, #sym); - - LINK2GENERIC(evas_gl_common_context_new); - LINK2GENERIC(evas_gl_common_context_flush); - LINK2GENERIC(evas_gl_common_context_free); - LINK2GENERIC(evas_gl_common_context_use); - LINK2GENERIC(evas_gl_common_context_resize); - LINK2GENERIC(evas_gl_symbols); + _gl_symbols(); /* now advertise out own api */ em->functions = (void *)(&func); @@ -1407,7 +339,6 @@ module_close(Evas_Module *em EINA_UNUSED) eina_log_domain_unregister(_evas_engine_gl_cocoa_log_dom); _evas_engine_gl_cocoa_log_dom = -1; } - evas_gl_common_module_close(); } static Evas_Module_Api evas_modapi = diff --git a/src/modules/evas/engines/gl_cocoa/evas_engine.h b/src/modules/evas/engines/gl_cocoa/evas_engine.h index 9c7cbdd554..6e56809c40 100644 --- a/src/modules/evas/engines/gl_cocoa/evas_engine.h +++ b/src/modules/evas/engines/gl_cocoa/evas_engine.h @@ -7,7 +7,7 @@ #include -#include "evas_gl_common.h" +#include "../gl_common/evas_gl_common.h" #include "Evas_Engine_GL_Cocoa.h" #include "../gl_generic/Evas_Engine_GL_Generic.h" @@ -46,7 +46,12 @@ struct _Render_Engine Render_Engine_GL_Generic generic; Outbuf *win; - int end; +}; + +struct _Context_3D +{ + Outbuf *ob; + void *ns_gl_context; }; struct _Outbuf @@ -58,36 +63,53 @@ struct _Outbuf void *ns_gl_view; // NSOpenGLView* void *ns_window; // NSWindow* - int width; - int height; - - // FIXME - struct { - int x1; - int y1; - int x2; - int y2; - int redraw : 1; - int drew : 1; - } draw; + int w; + int h; + int rot; + Render_Engine_Swap_Mode swap_mode; + Eina_Bool drew; }; -extern Evas_Gl_Symbols glsym_evas_gl_symbols; +static inline Outbuf * +eng_get_ob(const Render_Engine *re) +{ + return re->generic.software.ob; +} + extern Evas_GL_Common_Context_New glsym_evas_gl_common_context_new; extern Evas_GL_Common_Context_Call glsym_evas_gl_common_context_free; extern Evas_GL_Common_Context_Call glsym_evas_gl_common_context_flush; extern Evas_GL_Common_Context_Call glsym_evas_gl_common_context_use; +extern Evas_GL_Common_Context_Call glsym_evas_gl_common_context_done; extern Evas_GL_Common_Context_Resize_Call glsym_evas_gl_common_context_resize; +extern Evas_GL_Common_Context_Call glsym_evas_gl_common_context_newframe; +extern Evas_GL_Preload_Render_Call glsym_evas_gl_preload_render_lock; +extern Evas_GL_Preload_Render_Call glsym_evas_gl_preload_render_unlock; +extern Evas_Gl_Symbols glsym_evas_gl_symbols; Outbuf *evas_outbuf_new(Evas_Engine_Info_GL_Cocoa *info, int w, int h); void evas_outbuf_free(Outbuf *ob); void evas_outbuf_use(Outbuf *ob); -void evas_outbuf_lock_focus(Outbuf *ob); -void evas_outbuf_unlock_focus(Outbuf *ob); -void evas_outbuf_resize(Outbuf *ob, int w, int h); -void evas_outbuf_swap_buffers(Outbuf *ob); -void evas_outbuf_vsync_set(int on); // FIXME +int evas_outbuf_rot_get(Outbuf *ob); +Render_Engine_Swap_Mode evas_outbuf_buffer_state_get(Outbuf *ob); +void evas_outbuf_gl_context_use(Context_3D *ctx); +Eina_Bool evas_outbuf_update_region_first_rect(Outbuf *ob); +void *evas_outbuf_update_region_new(Outbuf *ob, int x, int y, int w, int h, int *cx, int *cy, int *cw, int *ch); +void evas_outbuf_update_region_push(Outbuf *ob, RGBA_Image *update, int x, int y, int w, int h); +void evas_outbuf_update_region_free(Outbuf *ob, RGBA_Image *update); +void evas_outbuf_flush(Outbuf *ob, Tilebuf_Rect *rects, Evas_Render_Mode render_mode); +Evas_Engine_GL_Context *evas_outbuf_gl_context_get(Outbuf *ob); +Context_3D *evas_outbuf_gl_context_new(Outbuf *ob); +void evas_outbuf_gl_context_use(Context_3D *ctx); +void evas_outbuf_reconfigure(Outbuf *ob, int w, int h, int rot, Outbuf_Depth depth); +void *evas_outbuf_egl_display_get(Outbuf *ob); + +#define GL_COCOA_UNIMPLEMENTED_CALL_SO_RETURN(...) \ + do { \ + CRI("[%s] IS AN IMPLEMENTED CALL. PLEASE REPORT!!", __func__); \ + return __VA_ARGS__; \ + } while (0) #endif /* __EVAS_ENGINE_H__ */ diff --git a/src/modules/evas/engines/gl_cocoa/evas_outbuf.m b/src/modules/evas/engines/gl_cocoa/evas_outbuf.m index 56a1b809b9..3382797844 100644 --- a/src/modules/evas/engines/gl_cocoa/evas_outbuf.m +++ b/src/modules/evas/engines/gl_cocoa/evas_outbuf.m @@ -5,7 +5,17 @@ #include +#define TRACE +#undef TRACE // Remove me for intense debug + +#ifdef TRACE +# define TRC(...) DBG(__VA_ARGS__) +#else +# define TRC(...) +#endif + static Outbuf *_evas_gl_cocoa_window = NULL; +static NSOpenGLContext *_evas_gl_cocoa_shared_context = nil; static int _win_count = 0; @interface EvasGLView : NSOpenGLView @@ -18,14 +28,10 @@ static int _win_count = 0; + (NSOpenGLPixelFormat*) basicPixelFormat { - NSOpenGLPixelFormatAttribute attributes [] = { - NSOpenGLPFAWindow, - NSOpenGLPFAAccelerated, - NSOpenGLPFADoubleBuffer, - /*NSOpenGLPFAColorSize, 24, - NSOpenGLPFAAlphaSize, 8, - NSOpenGLPFADepthSize, 24,*/ - 0 + const NSOpenGLPixelFormatAttribute attributes[] = { + NSOpenGLPFAAccelerated, + NSOpenGLPFADoubleBuffer, + 0 /* Terminator */ }; return [[[NSOpenGLPixelFormat alloc] initWithAttributes:attributes] autorelease]; } @@ -38,11 +44,26 @@ static int _win_count = 0; pf = [EvasGLView basicPixelFormat]; self = [super initWithFrame: frameRect pixelFormat: pf]; - ctx = [[NSOpenGLContext alloc] initWithFormat:pf - shareContext: nil]; + + /* + * Evas GL backend uses a global OpenGL context for all windows inside + * an application. Each window has its own texture to render its + * content. We use a singleton NSOpenGLContext shared between all + * NSOpenGLView, it solves rendering issues for multiple windows. + */ + if (!_evas_gl_cocoa_shared_context) + { + _evas_gl_cocoa_shared_context = [[NSOpenGLContext alloc] initWithFormat: pf + shareContext: nil]; + ctx = _evas_gl_cocoa_shared_context; + } + else + { + ctx = [[NSOpenGLContext alloc] initWithFormat: pf + shareContext: _evas_gl_cocoa_shared_context]; + } [self setOpenGLContext: ctx]; - [ctx setView: self]; return self; } @@ -54,7 +75,9 @@ static int _win_count = 0; - (void)lockFocus { - NSOpenGLContext* context = [self openGLContext]; + NSOpenGLContext *context; + + context = [self openGLContext]; //[super lockFocus]; if ([context view] != self) { @@ -65,6 +88,7 @@ static int _win_count = 0; @end + static void * _dlsym(const char *sym) { @@ -79,6 +103,7 @@ evas_outbuf_new(Evas_Engine_Info_GL_Cocoa *info, EINA_SAFETY_ON_NULL_RETURN_VAL(info, NULL); Outbuf *ob; + EvasGLView *glview; ob = calloc(1, sizeof(*ob)); if (EINA_UNLIKELY(!ob)) @@ -86,22 +111,24 @@ evas_outbuf_new(Evas_Engine_Info_GL_Cocoa *info, CRI("Failed to allocate memory"); goto die; } - _win_count++; - ob->width = w; - ob->height = h; + ob->w = w; + ob->h = h; ob->info = info; ob->ns_window = info->window; + ob->rot = 0; + ob->swap_mode = MODE_DOUBLE; - ob->ns_gl_view = [[EvasGLView alloc] initWithFrame: NSMakeRect(0, 0, w, h)]; - if (EINA_UNLIKELY(!ob->ns_gl_view)) + glview = [[EvasGLView alloc] initWithFrame: NSMakeRect(0, 0, w, h)]; + if (EINA_UNLIKELY(!glview)) { CRI("Failed to create gl_view"); goto die; } - [[(NSOpenGLView *)ob->ns_gl_view openGLContext] makeCurrentContext]; - + ob->ns_gl_view = glview; + [[glview openGLContext] makeCurrentContext]; glsym_evas_gl_symbols(_dlsym); + ob->gl_context = glsym_evas_gl_common_context_new(); if (EINA_UNLIKELY(!ob->gl_context)) { @@ -109,11 +136,11 @@ evas_outbuf_new(Evas_Engine_Info_GL_Cocoa *info, goto die; } - evas_outbuf_use(ob); - - glsym_evas_gl_common_context_resize(ob->gl_context, ob->width, ob->height, 0); // TODO rotation - + glsym_evas_gl_common_context_resize(ob->gl_context, + ob->w, ob->h, ob->rot); + _win_count++; + TRC("add: %p", ob); return ob; die: @@ -124,94 +151,186 @@ die: void evas_outbuf_free(Outbuf *ob) { - int refs = 0; + TRC("del: %p", ob); - _win_count--; evas_outbuf_use(ob); + _win_count--; if (_win_count == 0) evas_common_font_ext_clear(); if (ob == _evas_gl_cocoa_window) _evas_gl_cocoa_window = NULL; if (ob->gl_context) { - refs = ob->gl_context->references - 1; glsym_evas_gl_common_context_free(ob->gl_context); [(NSOpenGLView *) ob->ns_gl_view release]; } - if (refs == 0) - { - // TODO - } free(ob); } +static Eina_Bool +_evas_outbuf_make_current(void *data EINA_UNUSED, + void *doit EINA_UNUSED) +{ + GL_COCOA_UNIMPLEMENTED_CALL_SO_RETURN(EINA_FALSE); +} + void evas_outbuf_use(Outbuf *ob) { - Eina_Bool force = EINA_FALSE; - - // TODO preload_render_Lock - - if (_evas_gl_cocoa_window) - { - // TODO ifcurrent context is not glcontext - force = EINA_TRUE; - } - - if ((_evas_gl_cocoa_window != ob) || (force)) + if (_evas_gl_cocoa_window != ob) { if (_evas_gl_cocoa_window) { glsym_evas_gl_common_context_use(_evas_gl_cocoa_window->gl_context); glsym_evas_gl_common_context_flush(_evas_gl_cocoa_window->gl_context); } - - [[(NSOpenGLView *)ob->ns_gl_view openGLContext] makeCurrentContext]; _evas_gl_cocoa_window = ob; - // TODO blah + } + [[(NSOpenGLView* )ob->ns_gl_view openGLContext] makeCurrentContext]; + glsym_evas_gl_common_context_use(ob->gl_context); +} + +int +evas_outbuf_rot_get(Outbuf *ob) +{ + return ob->rot; +} + +Render_Engine_Swap_Mode +evas_outbuf_buffer_state_get(Outbuf *ob) +{ + return ob->swap_mode; +} + +Evas_Engine_GL_Context * +evas_outbuf_gl_context_get(Outbuf *ob) +{ + return ob->gl_context; +} + +void +evas_outbuf_update_region_push(Outbuf *ob, + RGBA_Image *update EINA_UNUSED, + int x EINA_UNUSED, + int y EINA_UNUSED, + int w EINA_UNUSED, + int h EINA_UNUSED) +{ + TRC(""); + /* Is it really necessary to flush per region ? Shouldn't we be able to + still do that for the full canvas when doing partial update */ + ob->drew = EINA_TRUE; + glsym_evas_gl_common_context_flush(ob->gl_context); +} + +void +evas_outbuf_update_region_free(Outbuf *ob EINA_UNUSED, RGBA_Image *update EINA_UNUSED) +{ + TRC(""); + /* Nothing to do here as we don't really create an image per area */ +} + +void * +evas_outbuf_update_region_new(Outbuf *ob, + int x, + int y, + int w, + int h, + int *cx EINA_UNUSED, + int *cy EINA_UNUSED, + int *cw EINA_UNUSED, + int *ch EINA_UNUSED) +{ + TRC("x,y,w,h = %i,%i,%i,%i", x, y, w, h); + + if ((w == ob->w) && (h == ob->h)) + ob->gl_context->master_clip.enabled = EINA_FALSE; + else + { + ob->gl_context->master_clip.enabled = EINA_TRUE; + ob->gl_context->master_clip.x = x; + ob->gl_context->master_clip.y = y; + ob->gl_context->master_clip.w = w; + ob->gl_context->master_clip.h = h; } - if (ob) glsym_evas_gl_common_context_use(ob->gl_context); + return ob->gl_context->def_surface; +} + +Eina_Bool +evas_outbuf_update_region_first_rect(Outbuf *ob) +{ + TRC(""); + + glsym_evas_gl_preload_render_lock(_evas_outbuf_make_current, ob); + evas_outbuf_use(ob); + + glsym_evas_gl_common_context_resize(ob->gl_context, + ob->w, ob->h, + ob->rot); + glsym_evas_gl_common_context_flush(ob->gl_context); + glsym_evas_gl_common_context_newframe(ob->gl_context); + + /* To debug partial rendering */ + //glClearColor(0.2, 0.5, 1.0, 1.0); + //glClear(GL_COLOR_BUFFER_BIT); + + return EINA_FALSE; } void -evas_outbuf_resize(Outbuf *ob, - int w, - int h) +evas_outbuf_flush(Outbuf *ob, + Tilebuf_Rect *rects EINA_UNUSED, + Evas_Render_Mode render_mode) { - NSRect view_frame; NSOpenGLView *const view = ob->ns_gl_view; - INF("Resize %d %d\n", w, h); + TRC("drew is %s", ob->drew ? "true" : "false"); - view_frame = [view frame]; - view_frame.size.height = h; - view_frame.size.width = w; + if (render_mode == EVAS_RENDER_MODE_ASYNC_INIT) goto end; + if (!ob->drew) goto end; + + ob->drew = EINA_FALSE; + evas_outbuf_use(ob); + glsym_evas_gl_common_context_done(ob->gl_context); - [view setFrame:view_frame]; [[view openGLContext] flushBuffer]; +end: + glsym_evas_gl_preload_render_unlock(_evas_outbuf_make_current, ob); } void -evas_outbuf_lock_focus(Outbuf *ob) +evas_outbuf_reconfigure(Outbuf *ob, + int w, + int h, + int rot, + Outbuf_Depth depth EINA_UNUSED) { - [(NSOpenGLView *)ob->ns_gl_view lockFocus]; -} + TRC("w,h = %i,%i", w, h); -void -evas_outbuf_unlock_focus(Outbuf *ob) -{ - [(NSOpenGLView *)ob->ns_gl_view unlockFocus]; -} - -void -evas_outbuf_swap_buffers(Outbuf *ob) -{ + ob->w = w; + ob->h = h; + ob->rot = rot; + evas_outbuf_use(ob); [[(NSOpenGLView *)ob->ns_gl_view openGLContext] flushBuffer]; + glsym_evas_gl_common_context_resize(ob->gl_context, w, h, rot); } -void // FIXME -evas_outbuf_vsync_set(int on EINA_UNUSED) +void +evas_outbuf_gl_context_use(Context_3D *ctx EINA_UNUSED) { + GL_COCOA_UNIMPLEMENTED_CALL_SO_RETURN(); +} + +Context_3D * +evas_outbuf_gl_context_new(Outbuf *ob EINA_UNUSED) +{ + GL_COCOA_UNIMPLEMENTED_CALL_SO_RETURN(NULL); +} + +void * +evas_outbuf_egl_display_get(Outbuf *ob EINA_UNUSED) +{ + GL_COCOA_UNIMPLEMENTED_CALL_SO_RETURN(NULL); }