mutter/src/wayland/meta-wayland-single-pixel-buffer.c
Robert Mader 50f8f1e8b3 wayland/single-pixel: Add API to check if buffer is opaque black
Which is the typical background color we also use for fullscreen
padding. This will allow us to apply optimizations.

Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/3177>
2024-02-10 17:41:12 +00:00

191 lines
6.3 KiB
C

/*
* Copyright (C) 2022 Red Hat Inc.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, see <http://www.gnu.org/licenses/>.
*
*/
#include "config.h"
#include "wayland/meta-wayland-single-pixel-buffer.h"
#include "backends/meta-backend-private.h"
#include "wayland/meta-wayland-buffer.h"
#include "wayland/meta-wayland-private.h"
#include "single-pixel-buffer-v1-server-protocol.h"
struct _MetaWaylandSinglePixelBuffer
{
uint32_t r;
uint32_t g;
uint32_t b;
uint32_t a;
};
static void
buffer_destroy (struct wl_client *client,
struct wl_resource *resource)
{
wl_resource_destroy (resource);
}
static const struct wl_buffer_interface single_pixel_buffer_implementation =
{
buffer_destroy,
};
static void
single_pixel_buffer_manager_destroy (struct wl_client *client,
struct wl_resource *resource)
{
wl_resource_destroy (resource);
}
static void
single_pixel_buffer_manager_create_1px_rgba32_buffer (struct wl_client *client,
struct wl_resource *resource,
uint32_t buffer_id,
uint32_t r,
uint32_t g,
uint32_t b,
uint32_t a)
{
MetaWaylandCompositor *compositor = wl_resource_get_user_data (resource);
MetaWaylandSinglePixelBuffer *single_pixel_buffer;
struct wl_resource *buffer_resource;
single_pixel_buffer = g_new0 (MetaWaylandSinglePixelBuffer, 1);
single_pixel_buffer->r = r;
single_pixel_buffer->g = g;
single_pixel_buffer->b = b;
single_pixel_buffer->a = a;
buffer_resource =
wl_resource_create (client, &wl_buffer_interface, 1, buffer_id);
wl_resource_set_implementation (buffer_resource,
&single_pixel_buffer_implementation,
single_pixel_buffer, NULL);
meta_wayland_buffer_from_resource (compositor, buffer_resource);
}
static const struct wp_single_pixel_buffer_manager_v1_interface
single_pixel_buffer_manager_implementation =
{
single_pixel_buffer_manager_destroy,
single_pixel_buffer_manager_create_1px_rgba32_buffer,
};
static void
single_pixel_buffer_manager_bind (struct wl_client *client,
void *user_data,
uint32_t version,
uint32_t id)
{
MetaWaylandCompositor *compositor = user_data;
struct wl_resource *resource;
resource = wl_resource_create (client,
&wp_single_pixel_buffer_manager_v1_interface,
version, id);
wl_resource_set_implementation (resource,
&single_pixel_buffer_manager_implementation,
compositor, NULL);
}
gboolean
meta_wayland_single_pixel_buffer_attach (MetaWaylandBuffer *buffer,
MetaMultiTexture **texture,
GError **error)
{
MetaContext *context =
meta_wayland_compositor_get_context (buffer->compositor);
MetaBackend *backend = meta_context_get_backend (context);
ClutterBackend *clutter_backend = meta_backend_get_clutter_backend (backend);
CoglContext *cogl_context =
clutter_backend_get_cogl_context (clutter_backend);
MetaWaylandSinglePixelBuffer *single_pixel_buffer =
wl_resource_get_user_data (buffer->resource);
uint8_t data[4];
CoglPixelFormat pixel_format;
CoglTexture *tex_2d;
if (buffer->single_pixel.texture)
return TRUE;
data[0] = single_pixel_buffer->b / (UINT32_MAX / 0xff);
data[1] = single_pixel_buffer->g / (UINT32_MAX / 0xff);
data[2] = single_pixel_buffer->r / (UINT32_MAX / 0xff);
data[3] = single_pixel_buffer->a / (UINT32_MAX / 0xff);
if (data[3] == UINT8_MAX)
pixel_format = COGL_PIXEL_FORMAT_BGR_888;
else
pixel_format = COGL_PIXEL_FORMAT_BGRA_8888_PRE;
tex_2d = cogl_texture_2d_new_from_data (cogl_context,
1, 1,
pixel_format,
4, data,
error);
if (!tex_2d)
return FALSE;
buffer->single_pixel.texture =
meta_multi_texture_new_simple (tex_2d);
g_clear_object (texture);
*texture = g_object_ref (buffer->single_pixel.texture);
return TRUE;
}
MetaWaylandSinglePixelBuffer *
meta_wayland_single_pixel_buffer_from_buffer (MetaWaylandBuffer *buffer)
{
if (!buffer->resource)
return NULL;
if (wl_resource_instance_of (buffer->resource, &wl_buffer_interface,
&single_pixel_buffer_implementation))
return wl_resource_get_user_data (buffer->resource);
return NULL;
}
void
meta_wayland_single_pixel_buffer_free (MetaWaylandSinglePixelBuffer *single_pixel_buffer)
{
g_free (single_pixel_buffer);
}
gboolean
meta_wayland_single_pixel_buffer_is_opaque_black (MetaWaylandSinglePixelBuffer *single_pixel_buffer)
{
return (single_pixel_buffer->a == UINT32_MAX &&
single_pixel_buffer->r == 0x0 &&
single_pixel_buffer->g == 0x0 &&
single_pixel_buffer->b == 0x0);
}
void
meta_wayland_init_single_pixel_buffer_manager (MetaWaylandCompositor *compositor)
{
if (!wl_global_create (compositor->wayland_display,
&wp_single_pixel_buffer_manager_v1_interface,
META_WP_SINGLE_PIXEL_BUFFER_V1_VERSION,
compositor,
single_pixel_buffer_manager_bind))
g_warning ("Failed to create wp_single_pixel_buffer_manager_v1 global");
}