mirror of
https://codeberg.org/vyivel/dulcepan/
synced 2025-12-17 15:45:12 +02:00
Support transforms and more formats
This commit is contained in:
206
main.c
206
main.c
@@ -2,6 +2,7 @@
|
|||||||
#include <cairo.h>
|
#include <cairo.h>
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
#include <linux/input-event-codes.h>
|
#include <linux/input-event-codes.h>
|
||||||
|
#include <pixman.h>
|
||||||
#include <stdarg.h>
|
#include <stdarg.h>
|
||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
@@ -41,7 +42,9 @@ struct dp_output {
|
|||||||
struct wp_viewport *ui_viewport;
|
struct wp_viewport *ui_viewport;
|
||||||
|
|
||||||
int width, height;
|
int width, height;
|
||||||
int width_px, height_px;
|
int px_width, px_height;
|
||||||
|
int frame_width, frame_height;
|
||||||
|
int32_t transform;
|
||||||
|
|
||||||
struct zwlr_screencopy_frame_v1 *frame;
|
struct zwlr_screencopy_frame_v1 *frame;
|
||||||
bool frame_ready;
|
bool frame_ready;
|
||||||
@@ -99,7 +102,7 @@ static struct dp_output *pointer_output = NULL;
|
|||||||
static int pointer_x = 0;
|
static int pointer_x = 0;
|
||||||
static int pointer_y = 0;
|
static int pointer_y = 0;
|
||||||
|
|
||||||
static bool save_on_select = false;
|
static bool quick = false;
|
||||||
|
|
||||||
static void die(const char *fmt, ...) {
|
static void die(const char *fmt, ...) {
|
||||||
va_list args;
|
va_list args;
|
||||||
@@ -201,6 +204,12 @@ static void layer_surface_handle_configure(void *data, struct zwlr_layer_surface
|
|||||||
output->height = (int)height;
|
output->height = (int)height;
|
||||||
|
|
||||||
output->configured = true;
|
output->configured = true;
|
||||||
|
|
||||||
|
wp_viewport_set_destination(output->viewport, output->width, output->height);
|
||||||
|
wp_viewport_set_destination(output->ui_viewport, output->width, output->height);
|
||||||
|
|
||||||
|
wl_surface_attach(output->surface, output->frame_buffer, 0, 0);
|
||||||
|
wl_surface_commit(output->surface);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void redraw(struct dp_output *output) {
|
static void redraw(struct dp_output *output) {
|
||||||
@@ -234,15 +243,15 @@ static void redraw(struct dp_output *output) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
wl_surface_attach(output->ui_surface, sc_buffer->buffer, 0, 0);
|
wl_surface_attach(output->ui_surface, sc_buffer->buffer, 0, 0);
|
||||||
wl_surface_damage(output->ui_surface, 0, 0, output->width_px, output->height_px);
|
wl_surface_damage(output->ui_surface, 0, 0, 200000000, 200000000);
|
||||||
wl_surface_commit(output->ui_surface);
|
wl_surface_commit(output->ui_surface);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void select_whole(void) {
|
static void select_whole(void) {
|
||||||
selected_x = 0;
|
selected_x = 0;
|
||||||
selected_y = 0;
|
selected_y = 0;
|
||||||
selected_width = selected_output->width_px;
|
selected_width = selected_output->px_width;
|
||||||
selected_height = selected_output->height_px;
|
selected_height = selected_output->px_height;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void set_selected_output(struct dp_output *output) {
|
static void set_selected_output(struct dp_output *output) {
|
||||||
@@ -266,14 +275,15 @@ static const struct zwlr_layer_surface_v1_listener layer_surface_listener = {
|
|||||||
static void output_handle_geometry(void *data, struct wl_output *wl_output, int32_t x, int32_t y,
|
static void output_handle_geometry(void *data, struct wl_output *wl_output, int32_t x, int32_t y,
|
||||||
int32_t phys_width, int32_t phys_height, int32_t subpixel, const char *make,
|
int32_t phys_width, int32_t phys_height, int32_t subpixel, const char *make,
|
||||||
const char *model, int32_t transform) {
|
const char *model, int32_t transform) {
|
||||||
// TODO: handle transform?
|
struct dp_output *output = data;
|
||||||
|
output->transform = transform;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void output_handle_mode(void *data, struct wl_output *wl_output, uint32_t flags,
|
static void output_handle_mode(void *data, struct wl_output *wl_output, uint32_t flags,
|
||||||
int32_t width, int32_t height, int32_t refresh) {
|
int32_t width, int32_t height, int32_t refresh) {
|
||||||
struct dp_output *output = data;
|
struct dp_output *output = data;
|
||||||
output->width_px = width;
|
output->frame_width = width;
|
||||||
output->height_px = height;
|
output->frame_height = height;
|
||||||
}
|
}
|
||||||
|
|
||||||
static const struct wl_output_listener output_listener = {
|
static const struct wl_output_listener output_listener = {
|
||||||
@@ -382,8 +392,8 @@ static const struct wl_keyboard_listener keyboard_listener = {
|
|||||||
|
|
||||||
static void convert_pos(wl_fixed_t x, wl_fixed_t y, int *out_x, int *out_y) {
|
static void convert_pos(wl_fixed_t x, wl_fixed_t y, int *out_x, int *out_y) {
|
||||||
assert(pointer_output != NULL);
|
assert(pointer_output != NULL);
|
||||||
*out_x = (int)wl_fixed_to_double(x) * pointer_output->width_px / pointer_output->width;
|
*out_x = (int)wl_fixed_to_double(x) * pointer_output->px_width / pointer_output->width;
|
||||||
*out_y = (int)wl_fixed_to_double(y) * pointer_output->height_px / pointer_output->height;
|
*out_y = (int)wl_fixed_to_double(y) * pointer_output->px_height / pointer_output->height;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void pointer_handle_enter(void *data, struct wl_pointer *pointer_, uint32_t serial,
|
static void pointer_handle_enter(void *data, struct wl_pointer *pointer_, uint32_t serial,
|
||||||
@@ -433,7 +443,7 @@ static void pointer_handle_button(void *data, struct wl_pointer *pointer_, uint3
|
|||||||
}
|
}
|
||||||
if (state != WL_POINTER_BUTTON_STATE_PRESSED) {
|
if (state != WL_POINTER_BUTTON_STATE_PRESSED) {
|
||||||
selecting_rect = false;
|
selecting_rect = false;
|
||||||
if (save_on_select) {
|
if (quick) {
|
||||||
status = DP_SAVE;
|
status = DP_SAVE;
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
@@ -454,6 +464,10 @@ static void pointer_handle_button(void *data, struct wl_pointer *pointer_, uint3
|
|||||||
case BTN_RIGHT:
|
case BTN_RIGHT:
|
||||||
set_selected_output(pointer_output);
|
set_selected_output(pointer_output);
|
||||||
select_whole();
|
select_whole();
|
||||||
|
if (quick) {
|
||||||
|
status = DP_SAVE;
|
||||||
|
return;
|
||||||
|
}
|
||||||
redraw(selected_output);
|
redraw(selected_output);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -473,11 +487,18 @@ static const struct wl_pointer_listener pointer_listener = {
|
|||||||
|
|
||||||
static void frame_handle_buffer(void *data, struct zwlr_screencopy_frame_v1 *frame, uint32_t format,
|
static void frame_handle_buffer(void *data, struct zwlr_screencopy_frame_v1 *frame, uint32_t format,
|
||||||
uint32_t width, uint32_t height, uint32_t stride) {
|
uint32_t width, uint32_t height, uint32_t stride) {
|
||||||
// TODO
|
struct dp_output *output = data;
|
||||||
|
assert(output->frame_buffer == NULL);
|
||||||
|
output->frame_format = format;
|
||||||
|
output->frame_stride = (int)stride;
|
||||||
|
output->frame_buffer = create_buffer(output->frame_width, output->frame_height,
|
||||||
|
output->frame_stride, output->frame_format, &output->frame_data);
|
||||||
|
zwlr_screencopy_frame_v1_copy(output->frame, output->frame_buffer);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void frame_handle_flags(void *data, struct zwlr_screencopy_frame_v1 *frame, uint32_t flags) {
|
static void frame_handle_flags(void *data, struct zwlr_screencopy_frame_v1 *frame, uint32_t flags) {
|
||||||
if (flags != 0) {
|
if (flags != 0) {
|
||||||
|
// TODO
|
||||||
die("who the fuck uses Y_INVERT");
|
die("who the fuck uses Y_INVERT");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -502,7 +523,9 @@ static const struct zwlr_screencopy_frame_v1_listener frame_listener = {
|
|||||||
static void registry_handle_global(void *data, struct wl_registry *registry, uint32_t name,
|
static void registry_handle_global(void *data, struct wl_registry *registry, uint32_t name,
|
||||||
const char *interface, uint32_t version) {
|
const char *interface, uint32_t version) {
|
||||||
if (strcmp(interface, wl_compositor_interface.name) == 0) {
|
if (strcmp(interface, wl_compositor_interface.name) == 0) {
|
||||||
compositor = wl_registry_bind(registry, name, &wl_compositor_interface, 1);
|
if (version >= 2) {
|
||||||
|
compositor = wl_registry_bind(registry, name, &wl_compositor_interface, 2);
|
||||||
|
}
|
||||||
} else if (strcmp(interface, wl_subcompositor_interface.name) == 0) {
|
} else if (strcmp(interface, wl_subcompositor_interface.name) == 0) {
|
||||||
subcompositor = wl_registry_bind(registry, name, &wl_subcompositor_interface, 1);
|
subcompositor = wl_registry_bind(registry, name, &wl_subcompositor_interface, 1);
|
||||||
} else if (strcmp(interface, wp_viewporter_interface.name) == 0) {
|
} else if (strcmp(interface, wp_viewporter_interface.name) == 0) {
|
||||||
@@ -544,6 +567,57 @@ static const struct wl_registry_listener registry_listener = {
|
|||||||
.global_remove = registry_handle_global_remove,
|
.global_remove = registry_handle_global_remove,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static pixman_format_code_t shm_to_pixman(enum wl_shm_format shm_format) {
|
||||||
|
struct {
|
||||||
|
enum wl_shm_format shm;
|
||||||
|
pixman_format_code_t pixman;
|
||||||
|
} formats[] = {
|
||||||
|
#if DP_BIG_ENDIAN
|
||||||
|
{WL_SHM_FORMAT_ARGB8888, PIXMAN_b8g8r8a8},
|
||||||
|
{WL_SHM_FORMAT_XRGB8888, PIXMAN_b8g8r8x8},
|
||||||
|
{WL_SHM_FORMAT_ABGR8888, PIXMAN_r8g8b8a8},
|
||||||
|
{WL_SHM_FORMAT_XBGR8888, PIXMAN_r8g8b8x8},
|
||||||
|
{WL_SHM_FORMAT_BGRA8888, PIXMAN_a8r8g8b8},
|
||||||
|
{WL_SHM_FORMAT_BGRX8888, PIXMAN_x8r8g8b8},
|
||||||
|
{WL_SHM_FORMAT_RGBA8888, PIXMAN_a8b8g8r8},
|
||||||
|
{WL_SHM_FORMAT_RGBX8888, PIXMAN_x8b8g8r8},
|
||||||
|
#else
|
||||||
|
{WL_SHM_FORMAT_RGB332, PIXMAN_r3g3b2},
|
||||||
|
{WL_SHM_FORMAT_BGR233, PIXMAN_b2g3r3},
|
||||||
|
{WL_SHM_FORMAT_ARGB4444, PIXMAN_a4r4g4b4},
|
||||||
|
{WL_SHM_FORMAT_XRGB4444, PIXMAN_x4r4g4b4},
|
||||||
|
{WL_SHM_FORMAT_ABGR4444, PIXMAN_a4b4g4r4},
|
||||||
|
{WL_SHM_FORMAT_XBGR4444, PIXMAN_x4b4g4r4},
|
||||||
|
{WL_SHM_FORMAT_ARGB1555, PIXMAN_a1r5g5b5},
|
||||||
|
{WL_SHM_FORMAT_XRGB1555, PIXMAN_x1r5g5b5},
|
||||||
|
{WL_SHM_FORMAT_ABGR1555, PIXMAN_a1b5g5r5},
|
||||||
|
{WL_SHM_FORMAT_XBGR1555, PIXMAN_x1b5g5r5},
|
||||||
|
{WL_SHM_FORMAT_RGB565, PIXMAN_r5g6b5},
|
||||||
|
{WL_SHM_FORMAT_BGR565, PIXMAN_b5g6r5},
|
||||||
|
{WL_SHM_FORMAT_RGB888, PIXMAN_r8g8b8},
|
||||||
|
{WL_SHM_FORMAT_BGR888, PIXMAN_b8g8r8},
|
||||||
|
{WL_SHM_FORMAT_ARGB8888, PIXMAN_a8r8g8b8},
|
||||||
|
{WL_SHM_FORMAT_XRGB8888, PIXMAN_x8r8g8b8},
|
||||||
|
{WL_SHM_FORMAT_ABGR8888, PIXMAN_a8b8g8r8},
|
||||||
|
{WL_SHM_FORMAT_XBGR8888, PIXMAN_x8b8g8r8},
|
||||||
|
{WL_SHM_FORMAT_BGRA8888, PIXMAN_b8g8r8a8},
|
||||||
|
{WL_SHM_FORMAT_BGRX8888, PIXMAN_b8g8r8x8},
|
||||||
|
{WL_SHM_FORMAT_RGBA8888, PIXMAN_r8g8b8a8},
|
||||||
|
{WL_SHM_FORMAT_RGBX8888, PIXMAN_r8g8b8x8},
|
||||||
|
{WL_SHM_FORMAT_ARGB2101010, PIXMAN_a2r10g10b10},
|
||||||
|
{WL_SHM_FORMAT_ABGR2101010, PIXMAN_a2b10g10r10},
|
||||||
|
{WL_SHM_FORMAT_XRGB2101010, PIXMAN_x2r10g10b10},
|
||||||
|
{WL_SHM_FORMAT_XBGR2101010, PIXMAN_x2b10g10r10},
|
||||||
|
#endif
|
||||||
|
};
|
||||||
|
for (size_t i = 0; i < sizeof(formats) / sizeof(*formats); i++) {
|
||||||
|
if (formats[i].shm == shm_format) {
|
||||||
|
return formats[i].pixman;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
int main(void) {
|
int main(void) {
|
||||||
struct wl_display *display = wl_display_connect(NULL);
|
struct wl_display *display = wl_display_connect(NULL);
|
||||||
if (display == NULL) {
|
if (display == NULL) {
|
||||||
@@ -599,27 +673,26 @@ int main(void) {
|
|||||||
wl_pointer_add_listener(pointer, &pointer_listener, NULL);
|
wl_pointer_add_listener(pointer, &pointer_listener, NULL);
|
||||||
|
|
||||||
wl_list_for_each (output, &outputs, link) {
|
wl_list_for_each (output, &outputs, link) {
|
||||||
|
if ((output->transform & WL_OUTPUT_TRANSFORM_90) != 0) {
|
||||||
|
output->px_width = output->frame_height;
|
||||||
|
output->px_height = output->frame_width;
|
||||||
|
} else {
|
||||||
|
output->px_width = output->frame_width;
|
||||||
|
output->px_height = output->frame_height;
|
||||||
|
}
|
||||||
|
|
||||||
output->frame = zwlr_screencopy_manager_v1_capture_output(
|
output->frame = zwlr_screencopy_manager_v1_capture_output(
|
||||||
screencopy_manager, false, output->global);
|
screencopy_manager, false, output->global);
|
||||||
zwlr_screencopy_frame_v1_add_listener(output->frame, &frame_listener, output);
|
zwlr_screencopy_frame_v1_add_listener(output->frame, &frame_listener, output);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get formats
|
// Get frames
|
||||||
wl_display_roundtrip(display);
|
wl_display_roundtrip(display);
|
||||||
|
|
||||||
// TODO: actually check formats
|
|
||||||
wl_list_for_each (output, &outputs, link) {
|
|
||||||
output->frame_format = WL_SHM_FORMAT_XBGR8888;
|
|
||||||
output->frame_stride = output->width_px * 4;
|
|
||||||
}
|
|
||||||
|
|
||||||
wl_list_for_each (output, &outputs, link) {
|
|
||||||
output->frame_buffer = create_buffer(output->width_px, output->height_px,
|
|
||||||
output->frame_stride, output->frame_format, &output->frame_data);
|
|
||||||
zwlr_screencopy_frame_v1_copy(output->frame, output->frame_buffer);
|
|
||||||
}
|
|
||||||
|
|
||||||
wl_list_for_each (output, &outputs, link) {
|
wl_list_for_each (output, &outputs, link) {
|
||||||
|
if (output->frame_buffer == NULL) {
|
||||||
|
die("failed to create a buffer for an output");
|
||||||
|
}
|
||||||
while (!output->frame_ready && wl_display_dispatch(display) != -1) {
|
while (!output->frame_ready && wl_display_dispatch(display) != -1) {
|
||||||
// Wait
|
// Wait
|
||||||
}
|
}
|
||||||
@@ -632,6 +705,11 @@ int main(void) {
|
|||||||
output->global, ZWLR_LAYER_SHELL_V1_LAYER_OVERLAY, "dulcepan");
|
output->global, ZWLR_LAYER_SHELL_V1_LAYER_OVERLAY, "dulcepan");
|
||||||
output->viewport = wp_viewporter_get_viewport(viewporter, output->surface);
|
output->viewport = wp_viewporter_get_viewport(viewporter, output->surface);
|
||||||
|
|
||||||
|
wl_surface_set_buffer_transform(output->surface, output->transform);
|
||||||
|
|
||||||
|
struct wl_region *empty_region = wl_compositor_create_region(compositor);
|
||||||
|
wl_surface_set_input_region(output->surface, empty_region);
|
||||||
|
|
||||||
zwlr_layer_surface_v1_add_listener(output->layer_surface, &layer_surface_listener, output);
|
zwlr_layer_surface_v1_add_listener(output->layer_surface, &layer_surface_listener, output);
|
||||||
|
|
||||||
zwlr_layer_surface_v1_set_anchor(output->layer_surface,
|
zwlr_layer_surface_v1_set_anchor(output->layer_surface,
|
||||||
@@ -652,11 +730,11 @@ int main(void) {
|
|||||||
|
|
||||||
for (size_t i = 0; i < SWAPCHAIN_LEN; i++) {
|
for (size_t i = 0; i < SWAPCHAIN_LEN; i++) {
|
||||||
struct dp_swapchain_buffer *sc_buffer = &output->swapchain[i];
|
struct dp_swapchain_buffer *sc_buffer = &output->swapchain[i];
|
||||||
int stride = output->width_px * 4;
|
int stride = output->frame_width * 4;
|
||||||
sc_buffer->buffer = create_buffer(output->width_px, output->height_px, stride,
|
sc_buffer->buffer = create_buffer(output->px_width, output->px_height, stride,
|
||||||
WL_SHM_FORMAT_ARGB8888, &sc_buffer->data);
|
WL_SHM_FORMAT_ARGB8888, &sc_buffer->data);
|
||||||
sc_buffer->cairo_surface = cairo_image_surface_create_for_data(sc_buffer->data,
|
sc_buffer->cairo_surface = cairo_image_surface_create_for_data(sc_buffer->data,
|
||||||
CAIRO_FORMAT_ARGB32, output->width_px, output->height_px, stride);
|
CAIRO_FORMAT_ARGB32, output->px_width, output->px_height, stride);
|
||||||
sc_buffer->cairo = cairo_create(sc_buffer->cairo_surface);
|
sc_buffer->cairo = cairo_create(sc_buffer->cairo_surface);
|
||||||
|
|
||||||
wl_buffer_add_listener(sc_buffer->buffer, &sc_buffer_listener, sc_buffer);
|
wl_buffer_add_listener(sc_buffer->buffer, &sc_buffer_listener, sc_buffer);
|
||||||
@@ -665,21 +743,17 @@ int main(void) {
|
|||||||
wl_surface_commit(output->surface);
|
wl_surface_commit(output->surface);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
wl_list_for_each (output, &outputs, link) {
|
||||||
|
while (!output->configured && wl_display_dispatch(display) != -1) {
|
||||||
|
// Wait
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Select the "first" output, whatever that is
|
// Select the "first" output, whatever that is
|
||||||
selected_output = wl_container_of(outputs.next, selected_output, link);
|
selected_output = wl_container_of(outputs.next, selected_output, link);
|
||||||
select_whole();
|
select_whole();
|
||||||
|
|
||||||
wl_list_for_each (output, &outputs, link) {
|
wl_list_for_each (output, &outputs, link) {
|
||||||
while (!output->configured && wl_display_dispatch(display) != -1) {
|
|
||||||
// Wait
|
|
||||||
}
|
|
||||||
|
|
||||||
wp_viewport_set_destination(output->viewport, output->width, output->height);
|
|
||||||
wp_viewport_set_destination(output->ui_viewport, output->width, output->height);
|
|
||||||
|
|
||||||
wl_surface_attach(output->surface, output->frame_buffer, 0, 0);
|
|
||||||
wl_surface_commit(output->surface);
|
|
||||||
|
|
||||||
redraw(output);
|
redraw(output);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -692,21 +766,59 @@ int main(void) {
|
|||||||
die("selected region is empty");
|
die("selected region is empty");
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: work with compositor-provided formats
|
pixman_format_code_t pixman_format = shm_to_pixman(selected_output->frame_format);
|
||||||
// TODO: actually figure out the byte ordering
|
if (pixman_format == 0) {
|
||||||
// TODO: a better file format
|
die("failed to get a matching Pixman format for wl_shm format");
|
||||||
|
}
|
||||||
|
|
||||||
|
pixman_image_t *frame = pixman_image_create_bits(pixman_format,
|
||||||
|
selected_output->frame_width, selected_output->frame_height,
|
||||||
|
selected_output->frame_data, selected_output->frame_stride);
|
||||||
|
|
||||||
|
static const int sines[] = {0, -1, 0, 1, 0, 1, 0, -1};
|
||||||
|
static const int cosines[] = {1, 0, -1, 0, 1, 0, -1, 0};
|
||||||
|
static const int flips[] = {1, 1, 1, 1, -1, -1, -1, -1};
|
||||||
|
|
||||||
|
struct pixman_transform frame_transform;
|
||||||
|
pixman_transform_init_identity(&frame_transform);
|
||||||
|
pixman_transform_translate(&frame_transform, NULL,
|
||||||
|
pixman_int_to_fixed(-selected_output->px_width / 2),
|
||||||
|
pixman_int_to_fixed(-selected_output->px_height / 2));
|
||||||
|
pixman_transform_rotate(&frame_transform, NULL,
|
||||||
|
pixman_int_to_fixed(cosines[selected_output->transform]),
|
||||||
|
pixman_int_to_fixed(sines[selected_output->transform]));
|
||||||
|
pixman_transform_scale(&frame_transform, NULL,
|
||||||
|
pixman_int_to_fixed(flips[selected_output->transform]), pixman_fixed_1);
|
||||||
|
pixman_transform_translate(&frame_transform, NULL,
|
||||||
|
pixman_int_to_fixed(selected_output->frame_width / 2),
|
||||||
|
pixman_int_to_fixed(selected_output->frame_height / 2));
|
||||||
|
|
||||||
|
pixman_image_set_transform(frame, &frame_transform);
|
||||||
|
|
||||||
|
pixman_image_t *result =
|
||||||
|
pixman_image_create_bits(PIXMAN_a8r8g8b8, selected_width, selected_height, NULL, 0);
|
||||||
|
pixman_image_composite32(PIXMAN_OP_SRC, frame, NULL, result, selected_x, selected_y, 0, 0,
|
||||||
|
0, 0, selected_width, selected_height);
|
||||||
|
pixman_image_unref(frame);
|
||||||
|
|
||||||
|
// TODO: a better format
|
||||||
|
|
||||||
|
uint32_t *data = pixman_image_get_data(result);
|
||||||
fprintf(stdout, "P6\n%d %d\n255\n", selected_width, selected_height);
|
fprintf(stdout, "P6\n%d %d\n255\n", selected_width, selected_height);
|
||||||
char *data = selected_output->frame_data;
|
|
||||||
int stride = selected_output->width_px * 4;
|
|
||||||
for (int y = 0; y < selected_height; y++) {
|
for (int y = 0; y < selected_height; y++) {
|
||||||
int base = (selected_y + y) * stride;
|
|
||||||
for (int x = 0; x < selected_width; x++) {
|
for (int x = 0; x < selected_width; x++) {
|
||||||
int i = base + (selected_x + x) * 4;
|
uint32_t pixel = *(data++);
|
||||||
fwrite(&data[i], 1, 3, stdout);
|
char bytes[3] = {
|
||||||
|
(char)((pixel >> 16) & 0xff),
|
||||||
|
(char)((pixel >> 8) & 0xff),
|
||||||
|
(char)((pixel >> 0) & 0xff),
|
||||||
|
};
|
||||||
|
fwrite(bytes, 1, sizeof(bytes), stdout);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
fflush(stdout);
|
fflush(stdout);
|
||||||
|
|
||||||
|
pixman_image_unref(result);
|
||||||
}
|
}
|
||||||
|
|
||||||
wl_registry_destroy(registry);
|
wl_registry_destroy(registry);
|
||||||
|
|||||||
@@ -18,6 +18,8 @@ add_project_arguments(
|
|||||||
|
|
||||||
cc = meson.get_compiler('c')
|
cc = meson.get_compiler('c')
|
||||||
|
|
||||||
|
big_endian = target_machine.endian() == 'big'
|
||||||
|
|
||||||
add_project_arguments(cc.get_supported_arguments([
|
add_project_arguments(cc.get_supported_arguments([
|
||||||
'-Wconversion',
|
'-Wconversion',
|
||||||
'-Wendif-labels',
|
'-Wendif-labels',
|
||||||
@@ -34,12 +36,15 @@ add_project_arguments(cc.get_supported_arguments([
|
|||||||
'-Wundef',
|
'-Wundef',
|
||||||
|
|
||||||
'-Wno-unused-parameter',
|
'-Wno-unused-parameter',
|
||||||
|
|
||||||
|
'-DDP_BIG_ENDIAN=@0@'.format(big_endian.to_int()),
|
||||||
]), language: 'c')
|
]), language: 'c')
|
||||||
|
|
||||||
wayland_client = dependency('wayland-client')
|
wayland_client = dependency('wayland-client')
|
||||||
wayland_protos = dependency('wayland-protocols')
|
wayland_protos = dependency('wayland-protocols')
|
||||||
|
|
||||||
cairo = dependency('cairo')
|
cairo = dependency('cairo')
|
||||||
|
pixman = dependency('pixman-1')
|
||||||
xkbcommon = dependency('xkbcommon')
|
xkbcommon = dependency('xkbcommon')
|
||||||
|
|
||||||
subdir('protocols')
|
subdir('protocols')
|
||||||
@@ -55,6 +60,7 @@ executable(
|
|||||||
client_protos,
|
client_protos,
|
||||||
wayland_client,
|
wayland_client,
|
||||||
cairo,
|
cairo,
|
||||||
|
pixman,
|
||||||
xkbcommon,
|
xkbcommon,
|
||||||
],
|
],
|
||||||
install: true,
|
install: true,
|
||||||
|
|||||||
Reference in New Issue
Block a user