mirror of https://github.com/fltk/fltk
Wayland platform.: complete support of gl_start/gl_finish.
This commit is contained in:
parent
8a2559e1af
commit
844d3d6d5c
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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_);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
|
Loading…
Reference in New Issue