Skip to content

Commit 4075afe

Browse files
authored
[Wayland] Add support for single-pixel-buffer-v1 protocol (#804)
* [Wayland] Add support for single-pixel-buffer-v1 protocol The "single pixel buffer" Wayland protocol extension provides a way for clients to create 1x1 buffers with a single color, specified by providing the color channels (red, green and blue) as well as the alpha channel as a 32 bit unsigned integer. This protocol is useful for e.g. MPV for creating black borders around content * wayland/single-pixel-buffer: Fix reusing buffer
1 parent ea90b59 commit 4075afe

8 files changed

Lines changed: 257 additions & 2 deletions

src/meson.build

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -556,6 +556,8 @@ if have_wayland
556556
'wayland/meta-wayland-seat.h',
557557
'wayland/meta-wayland-shell-surface.c',
558558
'wayland/meta-wayland-shell-surface.h',
559+
'wayland/meta-wayland-single-pixel-buffer.c',
560+
'wayland/meta-wayland-single-pixel-buffer.h',
559561
'wayland/meta-wayland-subsurface.c',
560562
'wayland/meta-wayland-subsurface.h',
561563
'wayland/meta-wayland-surface.c',
@@ -821,6 +823,7 @@ if have_wayland
821823
['pointer-warp-v1', 'private',],
822824
['primary-selection', 'unstable', 'v1', ],
823825
['relative-pointer', 'unstable', 'v1', ],
826+
['single-pixel-buffer', 'staging', 'v1', ],
824827
['xdg-system-bell', 'staging', 'v1', ],
825828
['tablet', 'unstable', 'v2', ],
826829
['text-input', 'unstable', 'v3', ],

src/wayland/meta-wayland-buffer.c

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -142,6 +142,7 @@ meta_wayland_buffer_realize (MetaWaylandBuffer *buffer)
142142
MetaWaylandEglStream *stream;
143143
#endif
144144
MetaWaylandDmaBufBuffer *dma_buf;
145+
MetaWaylandSinglePixelBuffer *single_pixel_buffer;
145146

146147
if (wl_shm_buffer_get (buffer->resource) != NULL)
147148
{
@@ -184,6 +185,14 @@ meta_wayland_buffer_realize (MetaWaylandBuffer *buffer)
184185
return TRUE;
185186
}
186187

188+
single_pixel_buffer = meta_wayland_single_pixel_buffer_from_buffer (buffer);
189+
if (single_pixel_buffer)
190+
{
191+
buffer->single_pixel.single_pixel_buffer = single_pixel_buffer;
192+
buffer->type = META_WAYLAND_BUFFER_TYPE_SINGLE_PIXEL;
193+
return TRUE;
194+
}
195+
187196
return FALSE;
188197
}
189198

@@ -522,6 +531,10 @@ meta_wayland_buffer_attach (MetaWaylandBuffer *buffer,
522531
return meta_wayland_dma_buf_buffer_attach (buffer,
523532
texture,
524533
error);
534+
case META_WAYLAND_BUFFER_TYPE_SINGLE_PIXEL:
535+
return meta_wayland_single_pixel_buffer_attach (buffer,
536+
texture,
537+
error);
525538
case META_WAYLAND_BUFFER_TYPE_UNKNOWN:
526539
g_assert_not_reached ();
527540
return FALSE;
@@ -628,6 +641,7 @@ meta_wayland_buffer_process_damage (MetaWaylandBuffer *buffer,
628641
case META_WAYLAND_BUFFER_TYPE_EGL_STREAM:
629642
#endif
630643
case META_WAYLAND_BUFFER_TYPE_DMA_BUF:
644+
case META_WAYLAND_BUFFER_TYPE_SINGLE_PIXEL:
631645
res = TRUE;
632646
break;
633647
case META_WAYLAND_BUFFER_TYPE_UNKNOWN:
@@ -706,6 +720,7 @@ meta_wayland_buffer_try_acquire_scanout (MetaWaylandBuffer *buffer,
706720
switch (buffer->type)
707721
{
708722
case META_WAYLAND_BUFFER_TYPE_SHM:
723+
case META_WAYLAND_BUFFER_TYPE_SINGLE_PIXEL:
709724
return NULL;
710725
case META_WAYLAND_BUFFER_TYPE_EGL_IMAGE:
711726
return try_acquire_egl_image_scanout (buffer, onscreen);
@@ -744,6 +759,9 @@ meta_wayland_buffer_finalize (GObject *object)
744759
#endif
745760
g_clear_pointer (&buffer->dma_buf.texture, cogl_object_unref);
746761
g_clear_object (&buffer->dma_buf.dma_buf);
762+
g_clear_pointer (&buffer->single_pixel.single_pixel_buffer,
763+
meta_wayland_single_pixel_buffer_free);
764+
cogl_clear_object (&buffer->single_pixel.texture);
747765

748766
G_OBJECT_CLASS (meta_wayland_buffer_parent_class)->finalize (object);
749767
}

src/wayland/meta-wayland-buffer.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@
3232
#include "wayland/meta-wayland-types.h"
3333
#include "wayland/meta-wayland-egl-stream.h"
3434
#include "wayland/meta-wayland-dma-buf.h"
35+
#include "wayland/meta-wayland-single-pixel-buffer.h"
3536

3637
typedef enum _MetaWaylandBufferType
3738
{
@@ -42,6 +43,7 @@ typedef enum _MetaWaylandBufferType
4243
META_WAYLAND_BUFFER_TYPE_EGL_STREAM,
4344
#endif
4445
META_WAYLAND_BUFFER_TYPE_DMA_BUF,
46+
META_WAYLAND_BUFFER_TYPE_SINGLE_PIXEL,
4547
} MetaWaylandBufferType;
4648

4749
struct _MetaWaylandBuffer
@@ -70,6 +72,11 @@ struct _MetaWaylandBuffer
7072
MetaWaylandDmaBufBuffer *dma_buf;
7173
CoglTexture *texture;
7274
} dma_buf;
75+
76+
struct {
77+
MetaWaylandSinglePixelBuffer *single_pixel_buffer;
78+
CoglTexture *texture;
79+
} single_pixel;
7380
};
7481

7582
#define META_TYPE_WAYLAND_BUFFER (meta_wayland_buffer_get_type ())
Lines changed: 182 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,182 @@
1+
/*
2+
* Copyright (C) 2022 Red Hat Inc.
3+
*
4+
* This program is free software; you can redistribute it and/or
5+
* modify it under the terms of the GNU General Public License as
6+
* published by the Free Software Foundation; either version 2 of the
7+
* License, or (at your option) any later version.
8+
*
9+
* This program is distributed in the hope that it will be useful, but
10+
* WITHOUT ANY WARRANTY; without even the implied warranty of
11+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12+
* General Public License for more details.
13+
*
14+
* You should have received a copy of the GNU General Public License
15+
* along with this program; if not, write to the Free Software
16+
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
17+
* 02111-1307, USA.
18+
*
19+
*/
20+
21+
#include "config.h"
22+
23+
#include "wayland/meta-wayland-single-pixel-buffer.h"
24+
25+
#include "backends/meta-backend-private.h"
26+
#include "wayland/meta-wayland-buffer.h"
27+
#include "wayland/meta-wayland-private.h"
28+
29+
#include "single-pixel-buffer-v1-server-protocol.h"
30+
31+
struct _MetaWaylandSinglePixelBuffer
32+
{
33+
uint32_t r;
34+
uint32_t g;
35+
uint32_t b;
36+
uint32_t a;
37+
};
38+
39+
static void
40+
buffer_destroy (struct wl_client *client,
41+
struct wl_resource *resource)
42+
{
43+
wl_resource_destroy (resource);
44+
}
45+
46+
static const struct wl_buffer_interface single_pixel_buffer_implementation =
47+
{
48+
buffer_destroy,
49+
};
50+
51+
static void
52+
single_pixel_buffer_manager_destroy (struct wl_client *client,
53+
struct wl_resource *resource)
54+
{
55+
wl_resource_destroy (resource);
56+
}
57+
58+
static void
59+
single_pixel_buffer_manager_create_1px_rgba32_buffer (struct wl_client *client,
60+
struct wl_resource *resource,
61+
uint32_t buffer_id,
62+
uint32_t r,
63+
uint32_t g,
64+
uint32_t b,
65+
uint32_t a)
66+
{
67+
MetaWaylandSinglePixelBuffer *single_pixel_buffer;
68+
struct wl_resource *buffer_resource;
69+
70+
single_pixel_buffer = g_new0 (MetaWaylandSinglePixelBuffer, 1);
71+
single_pixel_buffer->r = r;
72+
single_pixel_buffer->g = g;
73+
single_pixel_buffer->b = b;
74+
single_pixel_buffer->a = a;
75+
76+
buffer_resource =
77+
wl_resource_create (client, &wl_buffer_interface, 1, buffer_id);
78+
wl_resource_set_implementation (buffer_resource,
79+
&single_pixel_buffer_implementation,
80+
single_pixel_buffer, NULL);
81+
meta_wayland_buffer_from_resource (buffer_resource);
82+
}
83+
84+
static const struct wp_single_pixel_buffer_manager_v1_interface
85+
single_pixel_buffer_manager_implementation =
86+
{
87+
single_pixel_buffer_manager_destroy,
88+
single_pixel_buffer_manager_create_1px_rgba32_buffer,
89+
};
90+
91+
static void
92+
single_pixel_buffer_manager_bind (struct wl_client *client,
93+
void *user_data,
94+
uint32_t version,
95+
uint32_t id)
96+
{
97+
MetaWaylandCompositor *compositor = user_data;
98+
struct wl_resource *resource;
99+
100+
resource = wl_resource_create (client,
101+
&wp_single_pixel_buffer_manager_v1_interface,
102+
version, id);
103+
wl_resource_set_implementation (resource,
104+
&single_pixel_buffer_manager_implementation,
105+
compositor, NULL);
106+
}
107+
108+
gboolean
109+
meta_wayland_single_pixel_buffer_attach (MetaWaylandBuffer *buffer,
110+
CoglTexture **texture,
111+
GError **error)
112+
{
113+
MetaBackend *backend = meta_get_backend ();
114+
ClutterBackend *clutter_backend = meta_backend_get_clutter_backend (backend);
115+
CoglContext *cogl_context =
116+
clutter_backend_get_cogl_context (clutter_backend);
117+
MetaWaylandSinglePixelBuffer *single_pixel_buffer =
118+
wl_resource_get_user_data (buffer->resource);
119+
uint8_t data[4];
120+
CoglPixelFormat pixel_format;
121+
CoglTexture2D *tex_2d;
122+
123+
if (buffer->single_pixel.texture)
124+
{
125+
*texture = g_object_ref (buffer->single_pixel.texture);
126+
return TRUE;
127+
}
128+
129+
data[0] = single_pixel_buffer->b / (UINT32_MAX / 0xff);
130+
data[1] = single_pixel_buffer->g / (UINT32_MAX / 0xff);
131+
data[2] = single_pixel_buffer->r / (UINT32_MAX / 0xff);
132+
data[3] = single_pixel_buffer->a / (UINT32_MAX / 0xff);
133+
134+
if (data[3] == UINT8_MAX)
135+
pixel_format = COGL_PIXEL_FORMAT_BGR_888;
136+
else
137+
pixel_format = COGL_PIXEL_FORMAT_BGRA_8888_PRE;
138+
139+
tex_2d = cogl_texture_2d_new_from_data (cogl_context,
140+
1, 1,
141+
pixel_format,
142+
4, data,
143+
error);
144+
if (!tex_2d)
145+
return FALSE;
146+
147+
buffer->single_pixel.texture = COGL_TEXTURE (tex_2d);
148+
149+
cogl_clear_object (texture);
150+
*texture = cogl_object_ref (buffer->single_pixel.texture);
151+
return TRUE;
152+
}
153+
154+
MetaWaylandSinglePixelBuffer *
155+
meta_wayland_single_pixel_buffer_from_buffer (MetaWaylandBuffer *buffer)
156+
{
157+
if (!buffer->resource)
158+
return NULL;
159+
160+
if (wl_resource_instance_of (buffer->resource, &wl_buffer_interface,
161+
&single_pixel_buffer_implementation))
162+
return wl_resource_get_user_data (buffer->resource);
163+
164+
return NULL;
165+
}
166+
167+
void
168+
meta_wayland_single_pixel_buffer_free (MetaWaylandSinglePixelBuffer *single_pixel_buffer)
169+
{
170+
g_free (single_pixel_buffer);
171+
}
172+
173+
void
174+
meta_wayland_init_single_pixel_buffer_manager (MetaWaylandCompositor *compositor)
175+
{
176+
if (!wl_global_create (compositor->wayland_display,
177+
&wp_single_pixel_buffer_manager_v1_interface,
178+
META_WP_SINGLE_PIXEL_BUFFER_V1_VERSION,
179+
compositor,
180+
single_pixel_buffer_manager_bind))
181+
g_warning ("Failed to create wp_single_pixel_buffer_manager_v1 global");
182+
}
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
/*
2+
* Copyright (C) 2022 Red Hat Inc.
3+
*
4+
* This program is free software; you can redistribute it and/or
5+
* modify it under the terms of the GNU General Public License as
6+
* published by the Free Software Foundation; either version 2 of the
7+
* License, or (at your option) any later version.
8+
*
9+
* This program is distributed in the hope that it will be useful, but
10+
* WITHOUT ANY WARRANTY; without even the implied warranty of
11+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12+
* General Public License for more details.
13+
*
14+
* You should have received a copy of the GNU General Public License
15+
* along with this program; if not, write to the Free Software
16+
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
17+
* 02111-1307, USA.
18+
*
19+
*/
20+
21+
#ifndef META_WAYLAND_SINGLE_PIXEL_BUFFER_H
22+
#define META_WAYLAND_SINGLE_PIXEL_BUFFER_H
23+
24+
#include <glib.h>
25+
26+
#include "cogl/cogl.h"
27+
#include "wayland/meta-wayland-types.h"
28+
29+
typedef struct _MetaWaylandSinglePixelBuffer MetaWaylandSinglePixelBuffer;
30+
31+
gboolean meta_wayland_single_pixel_buffer_attach (MetaWaylandBuffer *buffer,
32+
CoglTexture **texture,
33+
GError **error);
34+
35+
MetaWaylandSinglePixelBuffer * meta_wayland_single_pixel_buffer_from_buffer (MetaWaylandBuffer *buffer);
36+
37+
void meta_wayland_init_single_pixel_buffer_manager (MetaWaylandCompositor *compositor);
38+
39+
void meta_wayland_single_pixel_buffer_free (MetaWaylandSinglePixelBuffer *single_pixel_buffer);
40+
41+
#endif /* META_WAYLAND_SINGLE_PIXEL_BUFFER_H */

src/wayland/meta-wayland-surface.c

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -724,8 +724,10 @@ meta_wayland_surface_apply_state (MetaWaylandSurface *surface,
724724
* it until is replaced by a subsequent wl_surface.commit or when the
725725
* wl_surface is destroyed.
726726
*/
727-
surface->buffer_held = (state->buffer &&
728-
!wl_shm_buffer_get (state->buffer->resource));
727+
surface->buffer_held =
728+
(state->buffer &&
729+
(state->buffer->type != META_WAYLAND_BUFFER_TYPE_SHM &&
730+
state->buffer->type != META_WAYLAND_BUFFER_TYPE_SINGLE_PIXEL));
729731
}
730732

731733
if (state->scale > 0)

src/wayland/meta-wayland-versions.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,7 @@
6060
#define META_ZWP_PRIMARY_SELECTION_V1_VERSION 1
6161
#define META_XDG_TOPLEVEL_TAG_V1_VERSION 1
6262
#define META_WP_CURSOR_SHAPE_VERSION 2
63+
#define META_WP_SINGLE_PIXEL_BUFFER_V1_VERSION 1
6364
#define META_WP_POINTER_WARP_VERSION 1
6465
#define META_WP_SYSTEM_BELL_V1_VERSION 1
6566
#define META_ZWLR_LAYER_SHELL_V1_VERSION 4

src/wayland/meta-wayland.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -442,6 +442,7 @@ meta_wayland_compositor_setup (MetaWaylandCompositor *wayland_compositor)
442442
meta_wayland_xdg_foreign_init (compositor);
443443
meta_wayland_legacy_xdg_foreign_init (compositor);
444444
meta_wayland_dma_buf_init (compositor);
445+
meta_wayland_init_single_pixel_buffer_manager (compositor);
445446
meta_wayland_keyboard_shortcuts_inhibit_init (compositor);
446447
meta_wayland_surface_inhibit_shortcuts_dialog_init ();
447448
meta_wayland_text_input_init (compositor);

0 commit comments

Comments
 (0)