mirror of https://github.com/fltk/fltk
Improve handling of type Fl_Offscreen under Wayland
Type Fl_Offscreen is now to be cast to cairo_t*. Also, make sure the dimensions of GL windows are multiples of the screen scale factor.
This commit is contained in:
parent
64f64835dd
commit
3384776f8e
|
@ -39,7 +39,7 @@ typedef opaque fl_uintptr_t;
|
|||
Platform-specific value representing an offscreen drawing buffer.
|
||||
\note This value can be safely cast to these types on each platform:
|
||||
\li X11: Pixmap
|
||||
\li Wayland: struct fl_wld_draw_buffer *
|
||||
\li Wayland: cairo_t *
|
||||
\li Windows: HBITMAP
|
||||
\li macOS: CGContextRef
|
||||
*/
|
||||
|
|
|
@ -528,11 +528,12 @@ give \c size, the common size of both byte arrays.
|
|||
|
||||
Section \ref wayland-buffer-factory below details how FLTK creates \c wl_buffer objects.
|
||||
|
||||
FLTK associates to each surface a <tt>struct fl_wld_buffer</tt> (see \ref fl_wld_buffer) containing
|
||||
a pointer to the byte array of the Cairo image surface (member \c draw_buffer), information about the
|
||||
FLTK associates to each surface a
|
||||
<tt>struct Fl_Wayland_Graphics_Driver::wld_buffer</tt> (see \ref wld_buffer) containing
|
||||
a pointer to the byte array of the Cairo image surface (member \c buffer), information about the
|
||||
Wayland buffer (members \c wl_buffer and \c data), the common size of the Cairo surface's and
|
||||
Wayland buffer's byte arrays (member \c data_size), and other information. A pointer to this
|
||||
<tt>struct fl_wld_buffer</tt> is memorized as member \c buffer of the Fl_Window's \ref wld_window.
|
||||
<tt>struct Fl_Wayland_Graphics_Driver::wld_buffer</tt> is memorized as member \c buffer of the Fl_Window's \ref wld_window.
|
||||
All drawing operations to the Fl_Window then modify the content of the Cairo image surface.
|
||||
|
||||
Function \c Fl_Wayland_Window_Driver::flush() is in charge of sending FLTK
|
||||
|
@ -550,7 +551,7 @@ mechanism to make sure the surface's \c wl_buffer is not changed until the surfa
|
|||
mapped on the display. This 3-step mechanism works as follows:
|
||||
- Fl_Wayland_Graphics_Driver::buffer_commit() first calls function \c wl_surface_frame() to
|
||||
obtain a <tt>struct wl_callback</tt> object and stores it as member \c cb of the surface's
|
||||
\ref fl_wld_buffer.
|
||||
\ref wld_buffer.
|
||||
- Then it calls \c wl_callback_add_listener() to associate this object to the FLTK-defined,
|
||||
callback function \c surface_frame_done() that Wayland calls when it's ready for another
|
||||
mapping operation.
|
||||
|
@ -609,23 +610,23 @@ the \c wl_shm_pool.
|
|||
- A variable named \c chunk_offset represents the offset within the pool's shared
|
||||
memory available for the buffer being constructed. It equals 0 when the pool has just been
|
||||
created and is updated as detailed below when one or more buffers have been previously created
|
||||
from the pool. A record of type <tt>struct fl_wld_buffer</tt> is created. This record will
|
||||
from the pool. A record of type <tt>struct Fl_Wayland_Graphics_Driver::wld_buffer</tt> is created. This record will
|
||||
contain (member \c wl_buffer) the address of a \c wl_buffer object that's created by function
|
||||
\c wl_shm_pool_create_buffer(). This \c wl_buffer object encapsulates a section of a given
|
||||
size of the pool's shared memory beginning at offset \c chunk_offset in it.
|
||||
Quantity <tt>pool_memory + chunk_offset</tt> is therefore the address of the
|
||||
beginning of the mmap'ed memory section encapsulated by this \c wl_buffer.
|
||||
Member \c shm_pool of the newly constructed \c fl_wld_buffer object is set to the address of
|
||||
Member \c shm_pool of the newly constructed \c Fl_Wayland_Graphics_Driver::wld_buffer object is set to the address of
|
||||
the current \c wl_shm_pool object. This record is added to the head of the linked list of
|
||||
current pool's buffers by a call to \c wl_list_insert().
|
||||
At that point, a <tt>struct fl_wld_buffer</tt> record is part of the linked list of all
|
||||
At that point, a <tt>struct Fl_Wayland_Graphics_Driver::wld_buffer</tt> record is part of the linked list of all
|
||||
such records corresponding to \c wl_buffer objects created from the same \c wl_shm_pool
|
||||
object, and member \c shm_pool of this record gives the address of this \c wl_shm_pool.
|
||||
When a new <tt>struct fl_wld_buffer</tt> record is to be created,
|
||||
When a new <tt>struct Fl_Wayland_Graphics_Driver::wld_buffer</tt> record is to be created,
|
||||
\code
|
||||
struct wld_shm_pool_data *pool_data =
|
||||
(struct wld_shm_pool_data *)wl_shm_pool_get_user_data(pool);
|
||||
struct fl_wld_buffer *record = wl_container_of(pool_data->buffers.next, record, link);
|
||||
struct Fl_Wayland_Graphics_Driver::wld_buffer *record = wl_container_of(pool_data->buffers.next, record, link);
|
||||
int chunk_offset = ((char*)record->data - pool_data->pool_memory) + record->data_size;
|
||||
\endcode
|
||||
gives the offset within the current pool's mmap'ed memory available for a new \c wl_buffer.
|
||||
|
@ -636,8 +637,8 @@ A window's \c wl_buffer is re-used each time the window gets redrawn, and is des
|
|||
function \c Fl_Wayland_Graphics_Driver::buffer_release() when \c Fl_Window::hide() runs or
|
||||
the window is resized. Function \c Fl_Wayland_Graphics_Driver::buffer_release() destroys the
|
||||
\c wl_buffer with \c wl_buffer_destroy() and removes the corresponding
|
||||
\c fl_wld_buffer record from the linked list of buffers from the same \c wl_shm_pool.
|
||||
Since new \c fl_wld_buffer records are added at the head of the linked list, and since
|
||||
\c Fl_Wayland_Graphics_Driver::wld_buffer record from the linked list of buffers from the same \c wl_shm_pool.
|
||||
Since new \c Fl_Wayland_Graphics_Driver::wld_buffer records are added at the head of the linked list, and since
|
||||
the record at the head of this list is used to compute the offset within the pool's mmap'ed
|
||||
memory available for a new \c wl_buffer, destruction of the last created \c wl_buffer
|
||||
allows to re-use the destroyed buffer's pool's memory for a new \c wl_buffer.
|
||||
|
@ -1110,7 +1111,7 @@ struct wld_window {
|
|||
Fl_Window *fl_win;
|
||||
struct wl_list outputs; // linked list of displays where part or whole of window maps
|
||||
struct wl_surface *wl_surface; // the window's surface
|
||||
struct fl_wld_buffer *buffer; // see \ref fl_wld_buffer
|
||||
struct Fl_Wayland_Graphics_Driver::wld_buffer *buffer; // see \ref wld_buffer
|
||||
struct xdg_surface *xdg_surface;
|
||||
enum Fl_Wayland_Window_Driver::kind kind; // DECORATED or POPUP or SUBWINDOW or UNFRAMED
|
||||
union {
|
||||
|
@ -1132,29 +1133,39 @@ struct wld_window {
|
|||
}
|
||||
</pre>
|
||||
|
||||
\anchor fl_wld_buffer
|
||||
<h3>struct fl_wld_buffer and struct fl_wld_draw_buffer</h3>
|
||||
Defined in \c Fl_Wayland_Graphics_Driver.H.
|
||||
One <tt>struct fl_wld_buffer</tt> record is created
|
||||
\anchor wld_buffer
|
||||
<h3>struct wld_buffer and struct draw_buffer</h3>
|
||||
They are defined as types of class \c Fl_Wayland_Graphics_Driver in file
|
||||
\c Fl_Wayland_Graphics_Driver.H.
|
||||
One <tt>struct Fl_Wayland_Graphics_Driver::wld_buffer</tt> record is created
|
||||
by \c Fl_Wayland_Graphics_Driver::create_shm_buffer() when
|
||||
an Fl_Window is show()'n or resized,
|
||||
when a custom cursor shape is created, or when text is dragged.
|
||||
|
||||
A <tt>struct fl_wld_draw_buffer</tt> record is created when an Fl_Image_Surface object
|
||||
is created by the \c Fl_Wayland_Image_Surface_Driver c'tor.
|
||||
One such record is also embedded inside each <tt>struct fl_wld_buffer</tt> record.
|
||||
A <tt>struct Fl_Wayland_Graphics_Driver::draw_buffer</tt> record
|
||||
is created when an Fl_Image_Surface object is created.
|
||||
One such record is also embedded inside each
|
||||
<tt>struct Fl_Wayland_Graphics_Driver::wld_buffer</tt> record.
|
||||
|
||||
<pre>
|
||||
struct fl_wld_draw_buffer { // Under Wayland, Fl_Offscreen points to this structure
|
||||
size_t data_size; // of wl_buffer and draw_buffer
|
||||
struct Fl_Wayland_Graphics_Driver::draw_buffer {
|
||||
size_t data_size; // of wl_buffer and buffer
|
||||
int stride; // bytes per line
|
||||
int width;
|
||||
unsigned char *buffer; // address of the beginning of the Cairo image surface's byte array
|
||||
cairo_t *cairo_; // used when drawing to the Cairo image surface
|
||||
};
|
||||
</pre>
|
||||
FLTK gives offscreen buffers the platform-dependent type \c Fl_Offscreen which is
|
||||
in fact member \c cairo_ of <tt>struct Fl_Wayland_Graphics_Driver::draw_buffer</tt>.
|
||||
Thus, a variable with type \c Fl_Offscreen needs be casted to type \c cairo_t*.
|
||||
Member function <tt>struct Fl_Wayland_Graphics_Driver::draw_buffer *
|
||||
Fl_Wayland_Graphics_Driver::offscreen_buffer(Fl_Offscreen);</tt>
|
||||
returns the \c draw_buffer record corresponding to an \c Fl_Offscreen value.
|
||||
|
||||
struct fl_wld_buffer {
|
||||
struct fl_wld_draw_buffer draw_buffer;
|
||||
<pre>
|
||||
struct Fl_Wayland_Graphics_Driver::wld_buffer {
|
||||
struct draw_buffer draw_buffer;
|
||||
struct wl_buffer *wl_buffer; // the Wayland buffer
|
||||
void *data; // address of the beginning of the Wayland buffer's byte array
|
||||
struct wl_callback *cb; // non-NULL while Wayland buffer is being committed
|
||||
|
|
|
@ -46,7 +46,7 @@ Fl_Wayland_Copy_Surface_Driver::~Fl_Wayland_Copy_Surface_Driver() {
|
|||
|
||||
void Fl_Wayland_Copy_Surface_Driver::set_current() {
|
||||
Fl_Surface_Device::set_current();
|
||||
((Fl_Wayland_Graphics_Driver*)driver())->set_cairo(((struct fl_wld_draw_buffer *)img_surf->offscreen())->cairo_);
|
||||
((Fl_Wayland_Graphics_Driver*)driver())->set_cairo((cairo_t*)img_surf->offscreen());
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -114,7 +114,8 @@ char *Fl_Wayland_Gl_Window_Driver::alpha_mask_for_string(const char *str, int n,
|
|||
fl_draw(str, n, 0, fl_height() - fl_descent());
|
||||
// get the R channel only of the bitmap
|
||||
char *alpha_buf = new char[w*h], *r = alpha_buf;
|
||||
struct fl_wld_draw_buffer *off = (struct fl_wld_draw_buffer *)surf->offscreen();
|
||||
struct Fl_Wayland_Graphics_Driver::draw_buffer *off =
|
||||
Fl_Wayland_Graphics_Driver::offscreen_buffer(surf->offscreen());
|
||||
for (int i = 0; i < h; i++) {
|
||||
uchar *q = off->buffer + i * off->stride;
|
||||
for (int j = 0; j < w; j++) {
|
||||
|
@ -274,7 +275,10 @@ void Fl_Wayland_Gl_Window_Driver::make_current_before() {
|
|||
if (!egl_window) {
|
||||
struct wld_window *win = fl_wl_xid(pWindow);
|
||||
struct wl_surface *surface = win->wl_surface;
|
||||
egl_window = wl_egl_window_create(surface, pWindow->pixel_w(), pWindow->pixel_h());
|
||||
int W = pWindow->pixel_w();
|
||||
int H = pWindow->pixel_h();
|
||||
int scale = Fl_Wayland_Window_Driver::driver(pWindow)->wld_scale();
|
||||
egl_window = wl_egl_window_create(surface, (W/scale)*scale, (H/scale)*scale);
|
||||
if (egl_window == EGL_NO_SURFACE) {
|
||||
Fl::fatal("Can't create egl window with wl_egl_window_create()\n");
|
||||
} else {
|
||||
|
@ -283,8 +287,7 @@ void Fl_Wayland_Gl_Window_Driver::make_current_before() {
|
|||
Fl_Wayland_Gl_Choice *g = (Fl_Wayland_Gl_Choice*)this->g();
|
||||
egl_surface = eglCreateWindowSurface(egl_display, g->egl_conf, egl_window, NULL);
|
||||
//fprintf(stderr, "Created egl surface=%p at scale=%d\n", egl_surface, win->scale);
|
||||
wl_surface_set_buffer_scale(surface,
|
||||
Fl_Wayland_Window_Driver::driver(pWindow)->wld_scale());
|
||||
wl_surface_set_buffer_scale(surface, scale);
|
||||
// Tested apps: shape, glpuzzle, cube, fractals, gl_overlay, fullscreen, unittests,
|
||||
// OpenGL3-glut-test, OpenGL3test.
|
||||
// Tested wayland compositors: mutter, kde-plasma, weston, sway on FreeBSD.
|
||||
|
@ -383,8 +386,8 @@ void Fl_Wayland_Gl_Window_Driver::resize(int is_a_resize, int W, int H) {
|
|||
if (!egl_window) return;
|
||||
float f = Fl::screen_scale(pWindow->screen_num());
|
||||
int s = Fl_Wayland_Window_Driver::driver(pWindow)->wld_scale();
|
||||
W = (W * s) * f;
|
||||
H = (H * s) * f;
|
||||
W = int(W * f) * s; // W, H must be multiples of int s
|
||||
H = int(H * f) * s;
|
||||
int W2, H2;
|
||||
wl_egl_window_get_attached_size(egl_window, &W2, &H2);
|
||||
if (W2 != W || H2 != H) {
|
||||
|
|
|
@ -27,28 +27,24 @@
|
|||
#include <wayland-client.h> // for wl_list
|
||||
|
||||
|
||||
struct fl_wld_draw_buffer { // Under Wayland, Fl_Offscreen points to this structure
|
||||
size_t data_size; // of wl_buffer and draw_buffer
|
||||
int stride;
|
||||
int width;
|
||||
unsigned char *buffer;
|
||||
cairo_t *cairo_;
|
||||
};
|
||||
|
||||
|
||||
struct fl_wld_buffer {
|
||||
struct fl_wld_draw_buffer draw_buffer;
|
||||
struct wl_buffer *wl_buffer;
|
||||
void *data;
|
||||
struct wl_callback *cb;
|
||||
bool draw_buffer_needs_commit;
|
||||
struct wl_shm_pool *shm_pool;
|
||||
struct wl_list link; // links all buffers from the same wl_shm_pool
|
||||
};
|
||||
|
||||
|
||||
class Fl_Wayland_Graphics_Driver : public Fl_Cairo_Graphics_Driver {
|
||||
public:
|
||||
struct draw_buffer {
|
||||
size_t data_size; // of wl_buffer and buffer
|
||||
int stride;
|
||||
int width;
|
||||
unsigned char *buffer;
|
||||
cairo_t *cairo_;
|
||||
};
|
||||
struct wld_buffer {
|
||||
struct draw_buffer draw_buffer;
|
||||
struct wl_buffer *wl_buffer;
|
||||
void *data;
|
||||
struct wl_callback *cb;
|
||||
bool draw_buffer_needs_commit;
|
||||
struct wl_shm_pool *shm_pool;
|
||||
struct wl_list link; // links all buffers from the same wl_shm_pool
|
||||
};
|
||||
struct wld_shm_pool_data { // one record attached to each wl_shm_pool object
|
||||
char *pool_memory; // start of mmap'ed memory encapsulated by the wl_shm_pool
|
||||
int pool_size; // size of encapsulated memory
|
||||
|
@ -56,10 +52,11 @@ public:
|
|||
};
|
||||
static const uint32_t wld_format;
|
||||
void copy_offscreen(int x, int y, int w, int h, Fl_Offscreen osrc, int srcx, int srcy) FL_OVERRIDE;
|
||||
static struct fl_wld_buffer *create_shm_buffer(int width, int height);
|
||||
static struct wld_buffer *create_shm_buffer(int width, int height);
|
||||
static void buffer_release(struct wld_window *window);
|
||||
static void buffer_commit(struct wld_window *window, struct flCairoRegion *r = NULL);
|
||||
static void cairo_init(struct fl_wld_draw_buffer *buffer, int width, int height, int stride, cairo_format_t format);
|
||||
static void cairo_init(struct draw_buffer *buffer, int width, int height, int stride, cairo_format_t format);
|
||||
static struct draw_buffer *offscreen_buffer(Fl_Offscreen);
|
||||
};
|
||||
|
||||
#endif // FL_WAYLAND_GRAPHICS_DRIVER_H
|
||||
|
|
|
@ -31,9 +31,10 @@ extern "C" {
|
|||
static struct wl_shm_pool *pool = NULL; // the current pool
|
||||
|
||||
|
||||
struct fl_wld_buffer *Fl_Wayland_Graphics_Driver::create_shm_buffer(int width, int height)
|
||||
struct Fl_Wayland_Graphics_Driver::wld_buffer *
|
||||
Fl_Wayland_Graphics_Driver::create_shm_buffer(int width, int height)
|
||||
{
|
||||
struct fl_wld_buffer *buffer;
|
||||
struct wld_buffer *buffer;
|
||||
int stride = cairo_format_stride_for_width(Fl_Cairo_Graphics_Driver::cairo_format, width);
|
||||
int size = stride * height;
|
||||
const int default_pool_size = 10000000; // larger pools are possible if needed
|
||||
|
@ -42,8 +43,8 @@ struct fl_wld_buffer *Fl_Wayland_Graphics_Driver::create_shm_buffer(int width, i
|
|||
(struct wld_shm_pool_data *)wl_shm_pool_get_user_data(pool) : NULL;
|
||||
int pool_size = pool ? pool_data->pool_size : default_pool_size; // current pool size
|
||||
if (pool) {
|
||||
// last fl_wld_buffer created from current pool
|
||||
struct fl_wld_buffer *record = wl_container_of(pool_data->buffers.next, record, link);
|
||||
// last wld_buffer created from current pool
|
||||
struct wld_buffer *record = wl_container_of(pool_data->buffers.next, record, link);
|
||||
chunk_offset = ((char*)record->data - pool_data->pool_memory) + record->draw_buffer.data_size;
|
||||
}
|
||||
if (!pool || chunk_offset + size > pool_size) { // if true, a new pool is needed
|
||||
|
@ -69,7 +70,7 @@ struct fl_wld_buffer *Fl_Wayland_Graphics_Driver::create_shm_buffer(int width, i
|
|||
wl_list_init(&pool_data->buffers);
|
||||
wl_shm_pool_set_user_data(pool, pool_data);
|
||||
}
|
||||
buffer = (struct fl_wld_buffer*)calloc(1, sizeof(struct fl_wld_buffer));
|
||||
buffer = (struct wld_buffer*)calloc(1, sizeof(struct wld_buffer));
|
||||
buffer->wl_buffer = wl_shm_pool_create_buffer(pool, chunk_offset, width, height, stride, Fl_Wayland_Graphics_Driver::wld_format);
|
||||
// add this buffer to head of list of current pool's buffers
|
||||
wl_list_insert(&pool_data->buffers, &buffer->link);
|
||||
|
@ -106,7 +107,7 @@ static void surface_frame_done(void *data, struct wl_callback *cb, uint32_t time
|
|||
|
||||
// copy pixels in region r from the Cairo surface to the Wayland buffer
|
||||
static void copy_region(struct wld_window *window, struct flCairoRegion *r) {
|
||||
struct fl_wld_buffer *buffer = window->buffer;
|
||||
struct Fl_Wayland_Graphics_Driver::wld_buffer *buffer = window->buffer;
|
||||
float f = Fl::screen_scale(window->fl_win->screen_num()) *
|
||||
Fl_Wayland_Window_Driver::driver(window->fl_win)->wld_scale();
|
||||
for (int i = 0; i < r->count; i++) {
|
||||
|
@ -149,7 +150,7 @@ void Fl_Wayland_Graphics_Driver::buffer_commit(struct wld_window *window,
|
|||
}
|
||||
|
||||
|
||||
void Fl_Wayland_Graphics_Driver::cairo_init(struct fl_wld_draw_buffer *buffer, int width, int height, int stride, cairo_format_t format) {
|
||||
void Fl_Wayland_Graphics_Driver::cairo_init(struct Fl_Wayland_Graphics_Driver::draw_buffer *buffer, int width, int height, int stride, cairo_format_t format) {
|
||||
buffer->data_size = stride * height;
|
||||
buffer->stride = stride;
|
||||
buffer->buffer = new uchar[buffer->data_size];
|
||||
|
@ -182,7 +183,7 @@ void Fl_Wayland_Graphics_Driver::buffer_release(struct wld_window *window)
|
|||
(struct wld_shm_pool_data*)wl_shm_pool_get_user_data(my_pool);
|
||||
wl_buffer_destroy(window->buffer->wl_buffer);
|
||||
//printf("wl_buffer_destroy(%p)\n",window->buffer->wl_buffer);
|
||||
// remove fl_wld_buffer from list of pool's buffers
|
||||
// remove wld_buffer from list of pool's buffers
|
||||
wl_list_remove(&window->buffer->link);
|
||||
//printf("last=%p\n", wl_list_empty(&pool_data->buffers) ? NULL : pool_data->buffers.next);
|
||||
if (wl_list_empty(&pool_data->buffers)) { // all buffers from pool are gone
|
||||
|
@ -206,14 +207,13 @@ const uint32_t Fl_Wayland_Graphics_Driver::wld_format = WL_SHM_FORMAT_ARGB8888;
|
|||
|
||||
void Fl_Wayland_Graphics_Driver::copy_offscreen(int x, int y, int w, int h, Fl_Offscreen src, int srcx, int srcy) {
|
||||
// draw portion srcx,srcy,w,h of osrc to position x,y (top-left) of the graphics driver's surface
|
||||
struct fl_wld_draw_buffer *osrc = (struct fl_wld_draw_buffer *)src;
|
||||
cairo_matrix_t matrix;
|
||||
cairo_get_matrix(cairo_, &matrix);
|
||||
double s = matrix.xx;
|
||||
cairo_save(cairo_);
|
||||
cairo_rectangle(cairo_, x, y, w, h);
|
||||
cairo_clip(cairo_);
|
||||
cairo_surface_t *surf = cairo_get_target(osrc->cairo_);
|
||||
cairo_surface_t *surf = cairo_get_target((cairo_t *)src);
|
||||
cairo_pattern_t *pat = cairo_pattern_create_for_surface(surf);
|
||||
cairo_set_source(cairo_, pat);
|
||||
cairo_matrix_init_scale(&matrix, s, s);
|
||||
|
@ -223,3 +223,9 @@ void Fl_Wayland_Graphics_Driver::copy_offscreen(int x, int y, int w, int h, Fl_O
|
|||
cairo_pattern_destroy(pat);
|
||||
cairo_restore(cairo_);
|
||||
}
|
||||
|
||||
|
||||
struct Fl_Wayland_Graphics_Driver::draw_buffer *Fl_Wayland_Graphics_Driver::offscreen_buffer(
|
||||
Fl_Offscreen offscreen) {
|
||||
return (struct draw_buffer*)cairo_get_user_data((cairo_t*)offscreen, NULL);
|
||||
}
|
||||
|
|
|
@ -32,11 +32,14 @@ Fl_Wayland_Image_Surface_Driver::Fl_Wayland_Image_Surface_Driver(int w, int h, i
|
|||
w = int(w * d);
|
||||
h = int(h * d);
|
||||
}
|
||||
struct fl_wld_draw_buffer *off_ = (struct fl_wld_draw_buffer*)calloc(1, sizeof(struct fl_wld_draw_buffer));
|
||||
offscreen = (Fl_Offscreen)off_;
|
||||
struct Fl_Wayland_Graphics_Driver::draw_buffer *off_ =
|
||||
(struct Fl_Wayland_Graphics_Driver::draw_buffer*)calloc(1,
|
||||
sizeof(struct Fl_Wayland_Graphics_Driver::draw_buffer));
|
||||
Fl_Wayland_Graphics_Driver::cairo_init(off_, w, h,
|
||||
cairo_format_stride_for_width(CAIRO_FORMAT_RGB24, w), CAIRO_FORMAT_RGB24);
|
||||
}
|
||||
offscreen = (Fl_Offscreen)off_->cairo_;
|
||||
cairo_set_user_data(off_->cairo_, NULL, off_, NULL);
|
||||
} else offscreen = off;
|
||||
driver(new Fl_Wayland_Graphics_Driver());
|
||||
if (d != 1 && high_res) driver()->scale(d);
|
||||
}
|
||||
|
@ -44,23 +47,25 @@ Fl_Wayland_Image_Surface_Driver::Fl_Wayland_Image_Surface_Driver(int w, int h, i
|
|||
|
||||
Fl_Wayland_Image_Surface_Driver::~Fl_Wayland_Image_Surface_Driver() {
|
||||
if (offscreen && !external_offscreen) {
|
||||
cairo_destroy(((struct fl_wld_draw_buffer *)offscreen)->cairo_);
|
||||
delete[] ((struct fl_wld_draw_buffer *)offscreen)->buffer;
|
||||
free((struct fl_wld_draw_buffer *)offscreen);
|
||||
struct Fl_Wayland_Graphics_Driver::draw_buffer *buffer =
|
||||
Fl_Wayland_Graphics_Driver::offscreen_buffer(offscreen);
|
||||
cairo_destroy((cairo_t *)offscreen);
|
||||
delete[] buffer->buffer;
|
||||
free(buffer);
|
||||
}
|
||||
delete driver();
|
||||
}
|
||||
|
||||
void Fl_Wayland_Image_Surface_Driver::set_current() {
|
||||
Fl_Surface_Device::set_current();
|
||||
((Fl_Wayland_Graphics_Driver*)fl_graphics_driver)->set_cairo(((struct fl_wld_draw_buffer*)offscreen)->cairo_);
|
||||
((Fl_Wayland_Graphics_Driver*)fl_graphics_driver)->set_cairo((cairo_t*)offscreen);
|
||||
pre_window = Fl_Wayland_Window_Driver::wld_window;
|
||||
Fl_Wayland_Window_Driver::wld_window = NULL;
|
||||
fl_window = 0;
|
||||
}
|
||||
|
||||
void Fl_Wayland_Image_Surface_Driver::end_current() {
|
||||
cairo_surface_t *surf = cairo_get_target(((struct fl_wld_draw_buffer *)offscreen)->cairo_);
|
||||
cairo_surface_t *surf = cairo_get_target((cairo_t*)offscreen);
|
||||
cairo_surface_flush(surf);
|
||||
Fl_Wayland_Window_Driver::wld_window = pre_window;
|
||||
fl_window = (Window)pre_window;
|
||||
|
@ -77,20 +82,21 @@ void Fl_Wayland_Image_Surface_Driver::untranslate() {
|
|||
|
||||
Fl_RGB_Image* Fl_Wayland_Image_Surface_Driver::image() {
|
||||
// Convert depth-4 image in draw_buffer to a depth-3 image while exchanging R and B colors
|
||||
int height = ((struct fl_wld_draw_buffer *)offscreen)->data_size / ((struct fl_wld_draw_buffer *)offscreen)->stride;
|
||||
uchar *rgb = new uchar[((struct fl_wld_draw_buffer *)offscreen)->width * height * 3];
|
||||
struct Fl_Wayland_Graphics_Driver::draw_buffer *off_buf = Fl_Wayland_Graphics_Driver::offscreen_buffer(offscreen);
|
||||
int height = off_buf->data_size / off_buf->stride;
|
||||
uchar *rgb = new uchar[off_buf->width * height * 3];
|
||||
uchar *p = rgb;
|
||||
uchar *q;
|
||||
for (int j = 0; j < height; j++) {
|
||||
q = ((struct fl_wld_draw_buffer *)offscreen)->buffer + j*((struct fl_wld_draw_buffer *)offscreen)->stride;
|
||||
for (int i = 0; i < ((struct fl_wld_draw_buffer *)offscreen)->width; i++) { // exchange R and B colors, transmit G
|
||||
q = off_buf->buffer + j*off_buf->stride;
|
||||
for (int i = 0; i < off_buf->width; i++) { // exchange R and B colors, transmit G
|
||||
*p = *(q+2);
|
||||
*(p+1) = *(q+1);
|
||||
*(p+2) = *q;
|
||||
p += 3; q += 4;
|
||||
}
|
||||
}
|
||||
Fl_RGB_Image *image = new Fl_RGB_Image(rgb, ((struct fl_wld_draw_buffer *)offscreen)->width, height, 3);
|
||||
Fl_RGB_Image *image = new Fl_RGB_Image(rgb, off_buf->width, height, 3);
|
||||
image->alloc_array = 1;
|
||||
return image;
|
||||
}
|
||||
|
|
|
@ -1507,11 +1507,12 @@ Fl_RGB_Image *Fl_Wayland_Screen_Driver::read_win_rectangle(int X, int Y, int w,
|
|||
bool ignore, bool *p_ignore) {
|
||||
struct wld_window* xid = win ? fl_wl_xid(win) : NULL;
|
||||
if (win && (!xid || !xid->buffer)) return NULL;
|
||||
struct fl_wld_draw_buffer *buffer;
|
||||
struct Fl_Wayland_Graphics_Driver::draw_buffer *buffer;
|
||||
if (win) buffer = &xid->buffer->draw_buffer;
|
||||
else {
|
||||
Fl_Image_Surface_Driver *dr = (Fl_Image_Surface_Driver*)Fl_Surface_Device::surface();
|
||||
buffer = (struct fl_wld_draw_buffer *)dr->image_surface()->offscreen();
|
||||
buffer = Fl_Wayland_Graphics_Driver::offscreen_buffer(
|
||||
dr->image_surface()->offscreen());
|
||||
}
|
||||
float s = win ?
|
||||
Fl_Wayland_Window_Driver::driver(win)->wld_scale() * scale(win->screen_num()) :
|
||||
|
@ -1545,7 +1546,7 @@ Fl_RGB_Image *Fl_Wayland_Screen_Driver::read_win_rectangle(int X, int Y, int w,
|
|||
|
||||
void Fl_Wayland_Screen_Driver::offscreen_size(Fl_Offscreen off_, int &width, int &height)
|
||||
{
|
||||
struct fl_wld_draw_buffer *off = (struct fl_wld_draw_buffer *)off_;
|
||||
struct Fl_Wayland_Graphics_Driver::draw_buffer *off = Fl_Wayland_Graphics_Driver::offscreen_buffer(off_);
|
||||
width = off->width;
|
||||
height = off->data_size / off->stride;
|
||||
}
|
||||
|
|
|
@ -25,6 +25,7 @@
|
|||
#include "../../Fl_Window_Driver.H"
|
||||
#include <FL/Fl_Plugin.H>
|
||||
#include "Fl_Wayland_Screen_Driver.H"
|
||||
#include "Fl_Wayland_Graphics_Driver.H"
|
||||
|
||||
|
||||
/*
|
||||
|
@ -137,7 +138,7 @@ struct wld_window {
|
|||
Fl_Window *fl_win;
|
||||
struct wl_list outputs; // linked list of displays where part or whole of window maps
|
||||
struct wl_surface *wl_surface;
|
||||
struct fl_wld_buffer *buffer;
|
||||
struct Fl_Wayland_Graphics_Driver::wld_buffer *buffer;
|
||||
struct xdg_surface *xdg_surface;
|
||||
enum Fl_Wayland_Window_Driver::kind kind;
|
||||
union { // for each value of kind
|
||||
|
|
|
@ -76,7 +76,9 @@ void Fl_Wayland_Window_Driver::delete_cursor_(struct wld_window *xid, bool delet
|
|||
if (custom) {
|
||||
struct wl_cursor *wl_cursor = custom->wl_cursor;
|
||||
struct cursor_image *new_image = (struct cursor_image*)wl_cursor->images[0];
|
||||
struct fl_wld_buffer *offscreen = (struct fl_wld_buffer *)wl_buffer_get_user_data(new_image->buffer);
|
||||
struct Fl_Wayland_Graphics_Driver::wld_buffer *offscreen =
|
||||
(struct Fl_Wayland_Graphics_Driver::wld_buffer *)
|
||||
wl_buffer_get_user_data(new_image->buffer);
|
||||
struct wld_window fake_xid;
|
||||
fake_xid.buffer = offscreen;
|
||||
Fl_Wayland_Graphics_Driver::buffer_release(&fake_xid);
|
||||
|
@ -575,7 +577,7 @@ int Fl_Wayland_Window_Driver::scroll(int src_x, int src_y, int src_w, int src_h,
|
|||
void (*draw_area)(void*, int,int,int,int), void* data)
|
||||
{
|
||||
struct wld_window * xid = fl_wl_xid(pWindow);
|
||||
struct fl_wld_buffer *buffer = xid->buffer;
|
||||
struct Fl_Wayland_Graphics_Driver::wld_buffer *buffer = xid->buffer;
|
||||
float s = wld_scale() * fl_graphics_driver->scale();
|
||||
if (s != 1) {
|
||||
src_x = src_x * s;
|
||||
|
@ -1620,7 +1622,7 @@ int Fl_Wayland_Window_Driver::set_cursor_4args(const Fl_RGB_Image *rgb, int hotx
|
|||
new_image->image.delay = 0;
|
||||
new_image->offset = 0;
|
||||
//create a Wayland buffer and have it used as an image of the new cursor
|
||||
struct fl_wld_buffer *offscreen = Fl_Wayland_Graphics_Driver::create_shm_buffer(new_image->image.width, new_image->image.height);
|
||||
struct Fl_Wayland_Graphics_Driver::wld_buffer *offscreen = Fl_Wayland_Graphics_Driver::create_shm_buffer(new_image->image.width, new_image->image.height);
|
||||
new_image->buffer = offscreen->wl_buffer;
|
||||
wl_buffer_set_user_data(new_image->buffer, offscreen);
|
||||
new_cursor->image_count = 1;
|
||||
|
@ -1628,7 +1630,11 @@ int Fl_Wayland_Window_Driver::set_cursor_4args(const Fl_RGB_Image *rgb, int hotx
|
|||
new_cursor->images[0] = (struct wl_cursor_image*)new_image;
|
||||
new_cursor->name = strdup("custom cursor");
|
||||
// draw the rgb image to the cursor's drawing buffer
|
||||
Fl_Image_Surface *img_surf = new Fl_Image_Surface(new_image->image.width, new_image->image.height, 0, (Fl_Offscreen)&offscreen->draw_buffer);
|
||||
cairo_set_user_data(offscreen->draw_buffer.cairo_,
|
||||
NULL,
|
||||
&offscreen->draw_buffer,
|
||||
NULL);
|
||||
Fl_Image_Surface *img_surf = new Fl_Image_Surface(new_image->image.width, new_image->image.height, 0, (Fl_Offscreen)offscreen->draw_buffer.cairo_);
|
||||
Fl_Surface_Device::push_current(img_surf);
|
||||
Fl_Wayland_Graphics_Driver *driver = (Fl_Wayland_Graphics_Driver*)img_surf->driver();
|
||||
cairo_scale(driver->cr(), scale, scale);
|
||||
|
|
|
@ -101,7 +101,9 @@ static void data_source_handle_cancelled(void *data, struct wl_data_source *sour
|
|||
wl_data_source_destroy(source);
|
||||
doing_dnd = false;
|
||||
if (dnd_icon) {
|
||||
struct fl_wld_buffer * off = (struct fl_wld_buffer *)wl_surface_get_user_data(dnd_icon);
|
||||
struct Fl_Wayland_Graphics_Driver::wld_buffer *off =
|
||||
(struct Fl_Wayland_Graphics_Driver::wld_buffer *)
|
||||
wl_surface_get_user_data(dnd_icon);
|
||||
struct wld_window fake_window;
|
||||
fake_window.buffer = off;
|
||||
Fl_Wayland_Graphics_Driver::buffer_release(&fake_window);
|
||||
|
@ -176,7 +178,7 @@ static const struct wl_data_source_listener data_source_listener = {
|
|||
};
|
||||
|
||||
|
||||
static struct fl_wld_buffer *offscreen_from_text(const char *text, int scale) {
|
||||
static struct Fl_Wayland_Graphics_Driver::wld_buffer *offscreen_from_text(const char *text, int scale) {
|
||||
const char *p, *q;
|
||||
int width = 0, height, w2, ltext = strlen(text);
|
||||
fl_font(FL_HELVETICA, 10 * scale);
|
||||
|
@ -196,9 +198,14 @@ static struct fl_wld_buffer *offscreen_from_text(const char *text, int scale) {
|
|||
if (width > 300*scale) width = 300*scale;
|
||||
height = nl * fl_height() + 3;
|
||||
width += 6;
|
||||
struct fl_wld_buffer *off = Fl_Wayland_Graphics_Driver::create_shm_buffer(width, height);
|
||||
width = ceil(width/float(scale)) * scale; // these must be multiples of scale
|
||||
height = ceil(height/float(scale)) * scale;
|
||||
struct Fl_Wayland_Graphics_Driver::wld_buffer *off = Fl_Wayland_Graphics_Driver::create_shm_buffer(width, height);
|
||||
memset(off->draw_buffer.buffer, 0, off->draw_buffer.data_size);
|
||||
Fl_Image_Surface *surf = new Fl_Image_Surface(width, height, 0, (Fl_Offscreen)&off->draw_buffer);
|
||||
cairo_set_user_data(off->draw_buffer.cairo_,
|
||||
NULL,
|
||||
&off->draw_buffer, NULL);
|
||||
Fl_Image_Surface *surf = new Fl_Image_Surface(width, height, 0, (Fl_Offscreen)off->draw_buffer.cairo_);
|
||||
Fl_Surface_Device::push_current(surf);
|
||||
p = text;
|
||||
fl_font(FL_HELVETICA, 10 * scale);
|
||||
|
@ -232,13 +239,13 @@ int Fl_Wayland_Screen_Driver::dnd(int use_selection) {
|
|||
wl_data_source_add_listener(source, &data_source_listener, (void*)0);
|
||||
wl_data_source_offer(source, wld_plain_text_clipboard);
|
||||
wl_data_source_set_actions(source, WL_DATA_DEVICE_MANAGER_DND_ACTION_COPY);
|
||||
struct fl_wld_buffer * off = NULL;
|
||||
struct Fl_Wayland_Graphics_Driver::wld_buffer *off = NULL;
|
||||
int s = 1;
|
||||
if (use_selection) {
|
||||
// use the text as dragging icon
|
||||
Fl_Widget *current = Fl::pushed() ? Fl::pushed() : Fl::first_window();
|
||||
s = Fl_Wayland_Window_Driver::driver(current->top_window())->wld_scale();
|
||||
off = (struct fl_wld_buffer *)offscreen_from_text(fl_selection_buffer[0], s);
|
||||
off = (struct Fl_Wayland_Graphics_Driver::wld_buffer *)offscreen_from_text(fl_selection_buffer[0], s);
|
||||
dnd_icon = wl_compositor_create_surface(scr_driver->wl_compositor);
|
||||
} else dnd_icon = NULL;
|
||||
doing_dnd = true;
|
||||
|
|
Loading…
Reference in New Issue