evas-gl_cocoa: migrate to gl_generic infrastructure

It has been a long journey, but here we are at last...
The infamous gl_cocoa engine has been migrated to the
gl_generic infrastructure. This should provide great
improvements and hopefully reduce side-channels b0rkage.

Fonts seems better, scrolling is smoother, expedite
does not segfault anymore... I haven't found a
regression with elementary_test, elementary_config,
terminology, expedite.
This commit is contained in:
Jean Guyomarc'h 2016-08-24 17:58:29 +02:00 committed by Jean Guyomarc'h
parent d8e488b1c8
commit 60215a5c53
5 changed files with 411 additions and 1343 deletions

View File

@ -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"

View File

@ -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

File diff suppressed because it is too large Load Diff

View File

@ -7,7 +7,7 @@
#include <OpenGL/gl.h>
#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__ */

View File

@ -5,7 +5,17 @@
#include <dlfcn.h>
#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);
}