FLTK logo

[master] 844d3d6 - Wayland platform.: complete support of gl_start/gl_finish.

FLTK matrix user chat room
(using Element browser app)   FLTK gitter user chat room   GitHub FLTK Project   FLTK News RSS Feed  
  FLTK Apps      FLTK Library      Forums      Links     Login 
 All Forums  |  Back to fltk.commit  ]
 
Previous Message ]Next Message ]

[master] 844d3d6 - Wayland platform.: complete support of gl_start/gl_finish. "ManoloFLTK" Jul 04, 2022  
 
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 ]
 
     
Previous Message ]Next Message ]
 
 

Comments are owned by the poster. All other content is copyright 1998-2024 by Bill Spitzak and others. This project is hosted by The FLTK Team. Please report site problems to 'erco@seriss.com'.