diff --git a/include/Mw/LowLevel/Wayland.h b/include/Mw/LowLevel/Wayland.h index 99ac280..0d3227f 100644 --- a/include/Mw/LowLevel/Wayland.h +++ b/include/Mw/LowLevel/Wayland.h @@ -170,8 +170,7 @@ struct _MwLLWayland { struct wl_keyboard* keyboard; MwU32 keyboard_serial; - MwU64 events_pending; - MwBool test; + MwU64 events_pending; MwU32 mod_state; @@ -186,8 +185,7 @@ struct _MwLLWayland { MwBool force_render; - MwBool break_dispatch; - MwBool break_pending; + MwBool hmmmm; struct _MwLLWaylandShmBuffer framebuffer; struct _MwLLWaylandShmBuffer cursor; diff --git a/pl/rules.pl b/pl/rules.pl index 1ad3ff3..123c128 100644 --- a/pl/rules.pl +++ b/pl/rules.pl @@ -32,6 +32,10 @@ if (grep(/^wayland$/, @backends)) { add_cflags(`pkg-config --cflags cairo wayland-client xkbcommon`); add_libs(`pkg-config --libs cairo wayland-client xkbcommon`); + if (param_get("opengl")) { + add_libs(`pkg-config --libs egl wayland-egl`); + } + scan_wayland_protocol("stable", "xdg-shell", ""); scan_wayland_protocol("stable", "tablet", "-v2"); scan_wayland_protocol("staging", "xdg-toplevel-icon", "-v1"); @@ -39,7 +43,7 @@ if (grep(/^wayland$/, @backends)) { scan_wayland_protocol("unstable", "xdg-decoration", "-unstable-v1"); scan_wayland_protocol("unstable", "primary-selection", "-unstable-v1"); - $gl_libs = "-lEGL -lwayland-egl lGL -lGLU"; + $gl_libs = "-lGL -lGLU"; } if (param_get("stb-image")) { @@ -48,6 +52,11 @@ if (param_get("stb-image")) { if (param_get("stb-truetype")) { add_cflags("-DUSE_STB_TRUETYPE"); } + +if (param_get("opengl")) { + add_cflags("-DHAS_OPENGL"); +} + if (param_get("freetype2")) { add_cflags("-DUSE_FREETYPE2"); if ($cross) { diff --git a/src/backend/wayland.c b/src/backend/wayland.c index 515e88b..6108aa7 100644 --- a/src/backend/wayland.c +++ b/src/backend/wayland.c @@ -8,7 +8,6 @@ #include #include #include -#include /* TODO: * - MwLLGrabPointerImpl @@ -360,6 +359,7 @@ static void pointer_motion(void* data, struct wl_pointer* wl_pointer, MwU32 time p.point = self->wayland.cur_mouse_pos; MwLLDispatch(self, move, &p); + self->wayland.events_pending += 1; /*timed_redraw(self, time, 50, &self->wayland.cooldown_timer);*/ @@ -396,8 +396,10 @@ static void pointer_button(void* data, struct wl_pointer* wl_pointer, MwU32 seri } } - MwLLDispatch(self, draw, NULL); - self->wayland.events_pending += 1; + if(!self->wayland.always_render) { + MwLLDispatch(self, draw, NULL); + self->wayland.events_pending += 1; + } }; /* `wl_pointer.axis` callback */ @@ -556,8 +558,11 @@ static void keyboard_key(void* data, } } } - MwLLDispatch(self, draw, NULL); - self->wayland.events_pending += 1; + + if(!self->wayland.always_render) { + MwLLDispatch(self, draw, NULL); + self->wayland.events_pending += 1; + } }; /* `wl_keyboard.modifiers` callback */ @@ -783,6 +788,8 @@ static void xdg_toplevel_configure(void* data, MwLLDispatch(self, resize, NULL); MwLLDispatch(self, draw, NULL); + MwLLForceRender(self); + /*if(!self->wayland.egl_setup) { self->wayland.egl_setup = egl_setup(self, self->wayland.x, self->wayland.y, width, height); } else { @@ -891,6 +898,7 @@ static void framebuffer_setup(struct _MwLLWayland* wayland) { memset(wayland->framebuffer.buf, 255, wayland->framebuffer.buf_size); update_buffer(&wayland->framebuffer); + wayland->events_pending += 1; }; static void framebuffer_destroy(struct _MwLLWayland* wayland) { @@ -1287,9 +1295,6 @@ static MwLL MwLLCreateImpl(MwLL parent, int x, int y, int width, int height) { MwLLForceRender(r); - pthread_mutex_init(&r->wayland.dispatch_mutex, NULL); - pthread_mutex_init(&r->wayland.pending_mutex, NULL); - return r; } @@ -1398,6 +1403,7 @@ static void MwLLPolygonImpl(MwLL handle, MwPoint* points, int points_count, MwLL } cairo_close_path(handle->wayland.cairo); cairo_fill(handle->wayland.cairo); + handle->wayland.events_pending += 1; } @@ -1416,6 +1422,7 @@ static void MwLLLineImpl(MwLL handle, MwPoint* points, MwLLColor color) { } cairo_close_path(handle->wayland.cairo); cairo_stroke(handle->wayland.cairo); + handle->wayland.events_pending += 1; } @@ -1424,6 +1431,7 @@ static void MwLLBeginDrawImpl(MwLL handle) { static void MwLLEndDrawImpl(MwLL handle) { update_buffer(&handle->wayland.framebuffer); + handle->wayland.events_pending += 1; } @@ -1451,20 +1459,29 @@ static int MwLLPendingImpl(MwLL handle) { MwBool pending = MwFALSE; struct timespec timeout; - timeout.tv_nsec = 100; - timeout.tv_sec = 0; - - while(pending == 0 && !handle->wayland.break_dispatch) { - pending = wl_display_dispatch_timeout(handle->wayland.display, &timeout); + if(handle->wayland.always_render) { + /* call event loop twice to make it to flush out events like mouse events and ensure we don't lag the render when doing that + */ + event_loop(handle); + return event_loop(handle); } - return handle->wayland.force_render || handle->wayland.events_pending || pending; + timeout.tv_nsec = 10; + timeout.tv_sec = 0; + + printf("%d\n", handle->wayland.force_render); + return handle->wayland.force_render || handle->wayland.events_pending || wl_display_dispatch_timeout(handle->wayland.display, &timeout); } static void MwLLNextEventImpl(MwLL handle) { - event_loop(handle); - if(handle->wayland.events_pending) { - handle->wayland.events_pending = 0; + if(!handle->wayland.always_render) { + event_loop(handle); + if(handle->wayland.events_pending) { + handle->wayland.events_pending = 0; + } + if(handle->wayland.force_render) { + handle->wayland.force_render = 0; + } } } @@ -1575,6 +1592,8 @@ static void MwLLSetIconImpl(MwLL handle, MwLLPixmap pixmap) { static void MwLLForceRenderImpl(MwLL handle) { wl_surface_damage(handle->wayland.framebuffer.surface, 0, 0, handle->wayland.ww, handle->wayland.wh); + handle->wayland.force_render = MwTRUE; + /* if(handle->wayland.egl_setup) { timed_redraw_by_epoch(handle, 25); diff --git a/src/widget/opengl.c b/src/widget/opengl.c index a1c36d9..1391fa4 100644 --- a/src/widget/opengl.c +++ b/src/widget/opengl.c @@ -1,6 +1,7 @@ #include #include +#ifdef HAS_OPENGL #ifdef USE_GDI typedef HGLRC(WINAPI* MWwglCreateContext)(HDC); typedef BOOL(WINAPI* MWwglMakeCurrent)(HDC, HGLRC); @@ -42,6 +43,19 @@ typedef struct x11opengl { } x11opengl_t; #endif +#ifdef USE_WAYLAND +#include +#include + +typedef struct waylandopengl { + EGLNativeWindowType egl_window_native; + EGLDisplay egl_display; + EGLContext egl_context; + EGLSurface egl_surface; + EGLConfig egl_config; +} waylandopengl_t; +#endif + static int create(MwWidget handle) { void* r = NULL; #ifdef USE_GDI @@ -105,7 +119,85 @@ static int create(MwWidget handle) { #endif #ifdef USE_WAYLAND if(handle->lowlevel->common.type == MwLLBackendWayland) { - /* todo */ + int err; + EGLint numConfigs; + EGLint majorVersion; + EGLint minorVersion; + EGLContext context; + EGLSurface surface; + EGLint fbAttribs[] = + { + EGL_SURFACE_TYPE, EGL_WINDOW_BIT, + EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT, + EGL_RED_SIZE, 8, + EGL_GREEN_SIZE, 8, + EGL_BLUE_SIZE, 8, + EGL_RENDERABLE_TYPE, EGL_OPENGL_BIT, + EGL_NONE}; + EGLint contextAttribs[] = { + EGL_CONTEXT_CLIENT_VERSION, 1, + EGL_CONTEXT_MAJOR_VERSION, 1, + EGL_CONTEXT_MINOR_VERSION, 1, + EGL_NONE}; + EGLDisplay display; + waylandopengl_t* o = r = malloc(sizeof(*o)); + + handle->lowlevel->wayland.parent->wayland.always_render = MwTRUE; + handle->lowlevel->wayland.always_render = MwTRUE; + + display = eglGetDisplay(handle->lowlevel->wayland.display); + if(display == EGL_NO_DISPLAY) { + printf("ERROR: eglGetDisplay, %0X\n", eglGetError()); + return MwFALSE; + } + /* Initialize EGL */ + if(!eglInitialize(display, &majorVersion, &minorVersion)) { + printf("ERROR: eglInitialize, %0X\n", eglGetError()); + return MwFALSE; + } + + /* Get configs */ + if((eglGetConfigs(display, NULL, 0, &numConfigs) != EGL_TRUE) || (numConfigs == 0)) { + printf("ERROR: eglGetConfigs, %0X\n", eglGetError()); + return MwFALSE; + } + + /* Choose config */ + if((eglChooseConfig(display, fbAttribs, &o->egl_config, 1, &numConfigs) != EGL_TRUE) || (numConfigs != 1)) { + printf("ERROR: eglChooseConfig, %0X\n", eglGetError()); + return MwFALSE; + } + + o->egl_window_native = + (EGLNativeWindowType)wl_egl_window_create(handle->lowlevel->wayland.framebuffer.surface, handle->lowlevel->wayland.ww, handle->lowlevel->wayland.wh); + if(o->egl_window_native == EGL_NO_SURFACE) { + printf("ERROR: wl_egl_window_create, EGL_NO_SURFACE\n"); + return MwFALSE; + } + + /* Create a surface */ + surface = eglCreateWindowSurface(display, o->egl_config, o->egl_window_native, NULL); + if(surface == EGL_NO_SURFACE) { + printf("ERROR: eglCreateWindowSurface, %0X\n", eglGetError()); + return MwFALSE; + } + + eglBindAPI(EGL_OPENGL_API); + + /* Create a GL context */ + context = eglCreateContext(display, o->egl_config, EGL_NO_CONTEXT, contextAttribs); + if(context == EGL_NO_CONTEXT) { + printf("ERROR: eglCreateContext, %0X\n", eglGetError()); + return MwFALSE; + } + + if(!eglMakeCurrent(display, surface, surface, context)) { + printf("ERROR: eglMakeCurrent (setup): %0X\n", eglGetError()); + } + + o->egl_display = display; + o->egl_surface = surface; + o->egl_context = context; } #endif @@ -165,7 +257,11 @@ static void mwOpenGLMakeCurrentImpl(MwWidget handle) { #endif #ifdef USE_WAYLAND if(handle->lowlevel->common.type == MwLLBackendWayland) { - /* todo */ + waylandopengl_t* o = handle->internal; + + if(!eglMakeCurrent(o->egl_display, o->egl_surface, o->egl_surface, o->egl_context)) { + printf("ERROR: eglMakeCurrent, %0X\n", eglGetError()); + } } #endif } @@ -187,7 +283,12 @@ static void mwOpenGLSwapBufferImpl(MwWidget handle) { #endif #ifdef USE_WAYLAND if(handle->lowlevel->common.type == MwLLBackendWayland) { - /* todo */ + waylandopengl_t* o = handle->internal; + if(!eglSwapBuffers(o->egl_display, o->egl_surface)) { + printf("ERROR: eglSwapBuffers, %0X\n", eglGetError()); + }; + wl_egl_window_resize((struct wl_egl_window*)o->egl_window_native, handle->lowlevel->wayland.ww, handle->lowlevel->wayland.wh, 0, 0); + MwLLForceRender(handle->lowlevel); } #endif } @@ -209,11 +310,85 @@ static void* mwOpenGLGetProcAddressImpl(MwWidget handle, const char* name) { #endif #ifdef USE_WAYLAND if(handle->lowlevel->common.type == MwLLBackendWayland) { - /* todo */ + return eglGetProcAddress(name); } #endif return NULL; } +#else +#ifdef USE_GDI +typedef HGLRC(WINAPI* MWwglCreateContext)(HDC); +typedef BOOL(WINAPI* MWwglMakeCurrent)(HDC, HGLRC); +typedef PROC(WINAPI* MWwglGetProcAddress)(LPCSTR); +typedef BOOL(WINAPI* MWwglDeleteContext)(HGLRC); + +typedef struct gdiopengl { + HDC dc; + HGLRC gl; + + void* lib; + + MWwglCreateContext wglCreateContext; + MWwglMakeCurrent wglMakeCurrent; + MWwglDeleteContext wglDeleteContext; + MWwglGetProcAddress wglGetProcAddress; +} gdiopengl_t; +#endif +#ifdef USE_X11 +typedef XVisualInfo* (*MWglXChooseVisual)(Display* dpy, int screen, int* attribList); +typedef GLXContext (*MWglXCreateContext)(Display* dpy, XVisualInfo* vis, GLXContext shareList, Bool direct); +typedef void (*MWglXDestroyContext)(Display* dpy, GLXContext ctx); +typedef Bool (*MWglXMakeCurrent)(Display* dpy, GLXDrawable drawable, GLXContext ctx); +typedef void (*MWglXSwapBuffers)(Display* dpy, GLXDrawable drawable); +typedef void* (*MWglXGetProcAddress)(const GLubyte* procname); + +typedef struct x11opengl { + XVisualInfo* visual; + GLXContext gl; + + void* lib; + + MWglXChooseVisual glXChooseVisual; + MWglXCreateContext glXCreateContext; + MWglXDestroyContext glXDestroyContext; + MWglXMakeCurrent glXMakeCurrent; + MWglXSwapBuffers glXSwapBuffers; + MWglXGetProcAddress glXGetProcAddress; +} x11opengl_t; +#endif + +#ifdef USE_WAYLAND +#include +#include + +typedef struct waylandopengl { + struct wl_egl_window* egl_window_native; + EGLDisplay egl_display; + EGLContext egl_context; + EGLSurface egl_surface; + EGLConfig egl_config; +} waylandopengl_t; + +#endif + +static int create(MwWidget handle) { + printf("Milsko compiled without OpenGL support! OpenGL widgets will not work properly.\n"); + return 1; +} + +static void destroy(MwWidget handle) { +} + +static void mwOpenGLMakeCurrentImpl(MwWidget handle) { +} + +static void mwOpenGLSwapBufferImpl(MwWidget handle) { +} + +static void* mwOpenGLGetProcAddressImpl(MwWidget handle, const char* name) { + return NULL; +} +#endif static void func_handler(MwWidget handle, const char* name, void* out, va_list va) { if(strcmp(name, "mwOpenGLMakeCurrent") == 0) {