|
commit 844d3d6d5c7a297db33408bf18488ec0e961b601
Author: ManoloFLTK <41016272+ManoloFLTK@users.noreply.github.com>
AuthorDate: Mon Jul 4 11:44:03 2022 +0200
Commit: ManoloFLTK <41016272+ManoloFLTK@users.noreply.github.com>
CommitDate: Mon Jul 4 11:44:03 2022 +0200
Wayland platform.: complete support of gl_start/gl_finish.
documentation/src/opengl.dox | 5 +-
src/drivers/Wayland/Fl_Wayland_Gl_Window_Driver.H | 2 +-
.../Wayland/Fl_Wayland_Gl_Window_Driver.cxx | 62 +++++++++++++++++-----
src/drivers/Wayland/Fl_Wayland_Window_Driver.H | 3 ++
src/drivers/Wayland/Fl_Wayland_Window_Driver.cxx | 11 ++++
5 files changed, 66 insertions(+), 17 deletions(-)
diff --git documentation/src/opengl.dox documentation/src/opengl.dox
index 566ce4d..c80d4fd 100644
--- documentation/src/opengl.dox
+++ documentation/src/opengl.dox
@@ -200,9 +200,8 @@ and OpenGL under macOS (see \ref osissues_retina)
\section opengl_normal Using OpenGL in Normal FLTK Windows
\note Drawing both with OpenGL and Quartz in a normal FLTK window is not possible
-with the macOS platform. Similarly, the Wayland platform doesn't allow to draw with
-both Cairo and OpenGL to the same window. This technique is therefore not useful under
-macOS or Wayland because it permits nothing more than what is possible with class Fl_Gl_Window.
+with the macOS platform. This technique is therefore not useful under macOS because
+it permits nothing more than what is possible with class Fl_Gl_Window.
You can put OpenGL code into the \p draw() method, as described in
\ref subclassing_drawing
diff --git src/drivers/Wayland/Fl_Wayland_Gl_Window_Driver.H src/drivers/Wayland/Fl_Wayland_Gl_Window_Driver.H
index 80f9197..2241c5e 100644
--- src/drivers/Wayland/Fl_Wayland_Gl_Window_Driver.H
+++ src/drivers/Wayland/Fl_Wayland_Gl_Window_Driver.H
@@ -50,8 +50,8 @@ class Fl_Wayland_Gl_Window_Driver : public Fl_Gl_Window_Driver {
virtual void delete_gl_context(GLContext);
virtual void make_overlay_current();
virtual void redraw_overlay();
- virtual void waitGL();
virtual void gl_start();
+ virtual void gl_visual(Fl_Gl_Choice *c);
virtual Fl_RGB_Image* capture_gl_rectangle(int x, int y, int w, int h);
char *alpha_mask_for_string(const char *str, int n, int w, int h, Fl_Fontsize fs);
static EGLDisplay egl_display;
diff --git src/drivers/Wayland/Fl_Wayland_Gl_Window_Driver.cxx src/drivers/Wayland/Fl_Wayland_Gl_Window_Driver.cxx
index 5bf04fc..686d0c1 100644
--- src/drivers/Wayland/Fl_Wayland_Gl_Window_Driver.cxx
+++ src/drivers/Wayland/Fl_Wayland_Gl_Window_Driver.cxx
@@ -46,6 +46,15 @@ public:
}
};
+struct gl_start_support { // to support use of gl_start / gl_finish
+ struct wl_surface *surface;
+ struct wl_subsurface *subsurface;
+ struct wl_egl_window *egl_window;
+ EGLSurface egl_surface;
+};
+
+static EGLConfig wld_egl_conf = NULL;
+
EGLDisplay Fl_Wayland_Gl_Window_Driver::egl_display = EGL_NO_DISPLAY;
EGLint Fl_Wayland_Gl_Window_Driver::configs_count = 0;
struct wl_event_queue *Fl_Wayland_Gl_Window_Driver::gl_event_queue = NULL;
@@ -172,23 +181,36 @@ GLContext Fl_Wayland_Gl_Window_Driver::create_gl_context(Fl_Window* window, cons
//fprintf(stderr, "eglCreateContext=%p shared_ctx=%p\n", ctx, shared_ctx);
if (ctx)
add_context(ctx);
- if (!egl_surface) { // useful for gl_start()
- struct wld_window *xid = fl_xid(window);
- float s = Fl::screen_scale(window->screen_num());
- egl_window = wl_egl_window_create(xid->wl_surface, window->w() * s, window->h() * s);
- egl_surface = eglCreateWindowSurface(egl_display, ((Fl_Wayland_Gl_Choice*)g)->egl_conf, egl_window, NULL);
- }
return ctx;
}
void Fl_Wayland_Gl_Window_Driver::set_gl_context(Fl_Window* w, GLContext context) {
struct wld_window *win = fl_xid(w);
- if (!win || !egl_surface) return;
+ if (!win) return;
+ Fl_Wayland_Window_Driver *dr = (Fl_Wayland_Window_Driver*)Fl_Window_Driver::driver(w);
+ EGLSurface target_egl_surface = NULL;
+ if (egl_surface) target_egl_surface = egl_surface;
+ else if (dr->gl_start_support_) target_egl_surface = dr->gl_start_support_->egl_surface;
+ if (!target_egl_surface) { // useful for gl_start()
+ dr->gl_start_support_ = new struct gl_start_support;
+ float s = Fl::screen_scale(w->screen_num());
+ Fl_Wayland_Screen_Driver *scr_driver = (Fl_Wayland_Screen_Driver*)Fl::screen_driver();
+ // the GL scene will be a transparent subsurface above the cairo-drawn surface
+ dr->gl_start_support_->surface = wl_compositor_create_surface(scr_driver->wl_compositor);
+ dr->gl_start_support_->subsurface = wl_subcompositor_get_subsurface(
+ scr_driver->wl_subcompositor, dr->gl_start_support_->surface, win->wl_surface);
+ wl_subsurface_set_position(dr->gl_start_support_->subsurface, w->x() * s, w->y() * s);
+ wl_subsurface_place_above(dr->gl_start_support_->subsurface, win->wl_surface);
+ dr->gl_start_support_->egl_window = wl_egl_window_create(
+ dr->gl_start_support_->surface, w->w() * s, w->h() * s);
+ target_egl_surface = dr->gl_start_support_->egl_surface = eglCreateWindowSurface(
+ egl_display, wld_egl_conf, dr->gl_start_support_->egl_window, NULL);
+ }
if (context != cached_context || w != cached_window) {
cached_context = context;
cached_window = w;
- if (eglMakeCurrent(egl_display, egl_surface, egl_surface, (EGLContext)context)) {
+ if (eglMakeCurrent(egl_display, target_egl_surface, target_egl_surface, (EGLContext)context)) {
//fprintf(stderr, "EGLContext %p made current\n", context);
} else {
Fl::error("eglMakeCurrent() failed\n");
@@ -333,6 +355,13 @@ public:
eglTerminate(Fl_Wayland_Gl_Window_Driver::egl_display);
}
}
+ virtual void destroy(struct gl_start_support *gl_start_support_) {
+ eglDestroySurface(Fl_Wayland_Gl_Window_Driver::egl_display, gl_start_support_->egl_surface);
+ wl_egl_window_destroy(gl_start_support_->egl_window);
+ wl_subsurface_destroy(gl_start_support_->subsurface);
+ wl_surface_destroy(gl_start_support_->surface);
+ delete gl_start_support_;
+ }
};
static Fl_Wayland_Gl_Plugin Gl_Overlay_Plugin;
@@ -358,11 +387,14 @@ char Fl_Wayland_Gl_Window_Driver::swap_type() {
}
-void Fl_Wayland_Gl_Window_Driver::waitGL() {
- struct wld_window *window = fl_xid(Fl_Window::current());
- window->buffer->draw_buffer_needs_commit = false;
+void Fl_Wayland_Gl_Window_Driver::gl_visual(Fl_Gl_Choice *c) {
+ Fl_Gl_Window_Driver::gl_visual(c);
+ wld_egl_conf = ((Fl_Wayland_Gl_Choice*)c)->egl_conf;
}
+static void delayed_redraw(Fl_Window *win) {
+ win->redraw();
+}
void Fl_Wayland_Gl_Window_Driver::gl_start() {
struct wld_window *win = fl_xid(Fl_Window::current());
@@ -370,8 +402,12 @@ void Fl_Wayland_Gl_Window_Driver::gl_start() {
int W = Fl_Window::current()->w() * f;
int H = Fl_Window::current()->h() * f;
int W2, H2;
- wl_egl_window_get_attached_size(egl_window, &W2, &H2);
- if (W2 != W || H2 != H) wl_egl_window_resize(egl_window, W, H, 0, 0);
+ Fl_Wayland_Window_Driver *dr = (Fl_Wayland_Window_Driver*)Fl_Window_Driver::driver(Fl_Window::current());
+ wl_egl_window_get_attached_size(dr->gl_start_support_->egl_window, &W2, &H2);
+ if (W2 != W || H2 != H) {
+ wl_egl_window_resize(dr->gl_start_support_->egl_window, W, H, 0, 0);
+ Fl::add_timeout(0.01, (Fl_Timeout_Handler)delayed_redraw, Fl_Window::current());
+ }
glClearColor(0., 0., 0., 0.);
glClear(GL_COLOR_BUFFER_BIT);
}
diff --git src/drivers/Wayland/Fl_Wayland_Window_Driver.H src/drivers/Wayland/Fl_Wayland_Window_Driver.H
index faa45b6..ad3c3ad 100644
--- src/drivers/Wayland/Fl_Wayland_Window_Driver.H
+++ src/drivers/Wayland/Fl_Wayland_Window_Driver.H
@@ -46,6 +46,7 @@ typedef struct _cairo_pattern cairo_pattern_t;
class FL_EXPORT Fl_Wayland_Window_Driver : public Fl_Window_Driver
{
friend class Fl_X;
+ friend class Fl_Wayland_Gl_Window_Driver;
private:
struct shape_data_type {
int lw_; ///< width of shape image
@@ -56,6 +57,7 @@ private:
static bool in_flush; // useful for progressive window drawing
struct wl_cursor *cursor_;
void delete_cursor_();
+ struct gl_start_support *gl_start_support_; // for support of gl_start/gl_finish
public:
struct wl_cursor *cursor() { return cursor_; };
bool in_handle_configure; // distinguish OS and user window resize
@@ -156,6 +158,7 @@ public:
virtual void do_swap(Fl_Window*) = 0;
virtual void invalidate(Fl_Window*) = 0;
virtual void terminate() = 0;
+ virtual void destroy(struct gl_start_support *) = 0;
};
#endif // FL_WAYLAND_WINDOW_DRIVER_H
diff --git src/drivers/Wayland/Fl_Wayland_Window_Driver.cxx src/drivers/Wayland/Fl_Wayland_Window_Driver.cxx
index dae93b1..2c94020 100644
--- src/drivers/Wayland/Fl_Wayland_Window_Driver.cxx
+++ src/drivers/Wayland/Fl_Wayland_Window_Driver.cxx
@@ -67,6 +67,7 @@ Fl_Wayland_Window_Driver::Fl_Wayland_Window_Driver(Fl_Window *win) : Fl_Window_D
cursor_ = NULL;
in_handle_configure = false;
screen_num_ = -1;
+ gl_start_support_ = NULL;
}
void Fl_Wayland_Window_Driver::delete_cursor_() {
@@ -98,6 +99,16 @@ Fl_Wayland_Window_Driver::~Fl_Wayland_Window_Driver()
delete shape_data_;
}
delete_cursor_();
+ if (gl_start_support_) { // occurs only if gl_start/gl_finish was used
+ static Fl_Wayland_Plugin *plugin = NULL;
+ if (!plugin) {
+ Fl_Plugin_Manager pm("wayland.fltk.org");
+ plugin = (Fl_Wayland_Plugin*)pm.plugin("gl.wayland.fltk.org");
+ }
+ if (plugin) {
+ plugin->destroy(gl_start_support_);
+ }
+ }
}
[ Direct Link to Message ] | |