labwc/src/buffer.c
tokyo4j 16dbdc64e5 ssd: rework titlebar button rendering
- fix that icons for normal/hovered/rounded buttons are not placed
  exactly the same position
- fix blurry window button icons in scaled outputs

This commit introduces lab_img and scaled_img_buffer and uses them for
rendering icons in the window titlebar. Now the process of rendering
button icons are split into 2 phases: loading with lab_img_load() and
creating scene-nodes for them with scaled_img_buffer_create(). This
might incur some additional overhead since we no longer preload icon
textures, but the rendering of icon only happens for the first window
as backing buffers are shared and the overhead won't be noticeable.
This commit also simplifies the process of centering icon buffer in the
button, by creating icon buffers in a fixed geometry via
lab_img_render().
2024-12-23 18:11:32 +09:00

147 lines
4.7 KiB
C

// SPDX-License-Identifier: GPL-2.0-only
/*
* Based on wlroots/types/wlr_buffer.c
*
* Copyright (c) 2017, 2018 Drew DeVault
* Copyright (c) 2018-2021 Simon Ser, Simon Zeni
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
#include <assert.h>
#include <stdlib.h>
#include <drm_fourcc.h>
#include <wlr/interfaces/wlr_buffer.h>
#include "buffer.h"
#include "common/mem.h"
static const struct wlr_buffer_impl data_buffer_impl;
static struct lab_data_buffer *
data_buffer_from_buffer(struct wlr_buffer *buffer)
{
assert(buffer->impl == &data_buffer_impl);
return (struct lab_data_buffer *)buffer;
}
static void
data_buffer_destroy(struct wlr_buffer *wlr_buffer)
{
struct lab_data_buffer *buffer = data_buffer_from_buffer(wlr_buffer);
/* this also frees buffer->data if surface_owns_data == true */
cairo_surface_destroy(buffer->surface);
if (!buffer->surface_owns_data) {
free(buffer->data);
}
free(buffer);
}
static bool
data_buffer_begin_data_ptr_access(struct wlr_buffer *wlr_buffer, uint32_t flags,
void **data, uint32_t *format, size_t *stride)
{
struct lab_data_buffer *buffer =
wl_container_of(wlr_buffer, buffer, base);
assert(buffer->data);
*data = (void *)buffer->data;
*format = buffer->format;
*stride = buffer->stride;
return true;
}
static void
data_buffer_end_data_ptr_access(struct wlr_buffer *wlr_buffer)
{
/* noop */
}
static const struct wlr_buffer_impl data_buffer_impl = {
.destroy = data_buffer_destroy,
.begin_data_ptr_access = data_buffer_begin_data_ptr_access,
.end_data_ptr_access = data_buffer_end_data_ptr_access,
};
struct lab_data_buffer *
buffer_adopt_cairo_surface(cairo_surface_t *surface)
{
assert(cairo_surface_get_type(surface) == CAIRO_SURFACE_TYPE_IMAGE);
assert(cairo_image_surface_get_format(surface) == CAIRO_FORMAT_ARGB32);
int width = cairo_image_surface_get_width(surface);
int height = cairo_image_surface_get_height(surface);
struct lab_data_buffer *buffer = znew(*buffer);
wlr_buffer_init(&buffer->base, &data_buffer_impl, width, height);
buffer->surface = surface;
buffer->data = cairo_image_surface_get_data(buffer->surface);
buffer->format = DRM_FORMAT_ARGB8888;
buffer->stride = cairo_image_surface_get_stride(buffer->surface);
buffer->logical_width = width;
buffer->logical_height = height;
buffer->surface_owns_data = true;
return buffer;
}
struct lab_data_buffer *
buffer_create_cairo(uint32_t logical_width, uint32_t logical_height, float scale)
{
/* Create an image surface with the scaled size */
cairo_surface_t *surface =
cairo_image_surface_create(CAIRO_FORMAT_ARGB32,
lroundf(logical_width * scale),
lroundf(logical_height * scale));
/**
* Tell cairo about the device scale so we can keep drawing in unscaled
* coordinate space. Pango will automatically use the cairo scale attribute
* as well when creating text on this surface.
*
* For a more complete explanation see PR #389
*/
cairo_surface_set_device_scale(surface, scale, scale);
/*
* Adopt the image surface into a buffer, set the correct
* logical size, and create a cairo context for drawing
*/
struct lab_data_buffer *buffer = buffer_adopt_cairo_surface(surface);
buffer->logical_width = logical_width;
buffer->logical_height = logical_height;
return buffer;
}
struct lab_data_buffer *
buffer_create_from_data(void *pixel_data, uint32_t width, uint32_t height,
uint32_t stride)
{
struct lab_data_buffer *buffer = znew(*buffer);
wlr_buffer_init(&buffer->base, &data_buffer_impl, width, height);
buffer->logical_width = width;
buffer->logical_height = height;
buffer->data = pixel_data;
buffer->format = DRM_FORMAT_ARGB8888;
buffer->stride = stride;
buffer->surface = cairo_image_surface_create_for_data(
pixel_data, CAIRO_FORMAT_ARGB32, width, height, stride);
buffer->surface_owns_data = false;
return buffer;
}