some work on x11 ext

This commit is contained in:
veclavtlica
2026-10-13 04:30:06 +03:00
parent 964e623644
commit 5789cafd4e
13 changed files with 262 additions and 144 deletions
+147 -72
View File
@@ -10,7 +10,6 @@
#include "../../Common/cfg.h"
#include "../../Common/def.h"
#include "../../Common/lzw.h"
#include "../../Common/mat.h"
#include "../../Common/std.h"
#include "../../Common/str.h"
#include "../../Common/test.h"
@@ -53,13 +52,13 @@ static struct {
uint32_t resource_id_mask;
} plr_x11_connection;
bool quited = false;
bool fileread(void *ctx, char *into, uint32_t bytes) {
static bool fileread(void *ctx, char *into, uint32_t bytes) {
return com_std_read(ctx, into, bytes) == bytes;
}
bool fileskip(void *ctx, uint32_t bytes) { return com_std_sfwd(ctx, bytes); }
static bool fileskip(void *ctx, uint32_t bytes) {
return com_std_sfwd(ctx, bytes);
}
#define AUTH_ENTRY_MAGIC_COOKIE "MIT-MAGIC-COOKIE-1"
@@ -145,6 +144,8 @@ static bool plr_x11_handshake(com_std_fd xfd,
if (response.success != 1)
return false;
/* https://xorg.freedesktop.org/archive/X11R7.7-RC1/doc/xproto/x11protocol.html#server_response
*/
struct {
uint32_t release_number;
uint32_t resource_id_base;
@@ -175,8 +176,13 @@ static bool plr_x11_handshake(com_std_fd xfd,
return false;
if (!com_std_read(xfd, scratch, 8 * dyn_response.formats_count))
return false;
/* Read first and hope it is what we need. */
if (!com_std_read(xfd, &plr_x11_root_screen, sizeof plr_x11_root_screen))
return false;
/* Then drop all the things that proceed, such as other screens and their
* visual profiles. */
while (com_std_has_data(xfd))
com_std_read(xfd, scratch, sizeof scratch);
plr_x11_connection.resource_id_base = dyn_response.resource_id_base;
plr_x11_connection.resource_id_mask = dyn_response.resource_id_mask;
@@ -184,50 +190,65 @@ static bool plr_x11_handshake(com_std_fd xfd,
return true;
}
/* TODO: Instead have a poll_events function instead. */
static inline bool plr_x11_poll_errors(com_std_fd xfd) {
union {
struct {
uint8_t type;
uint8_t errcode;
uint16_t sequenceid;
uint32_t badval;
uint16_t minorop;
uint32_t majorop;
char pad[18];
} __attribute__((packed)) error;
struct {
uint8_t type;
uint8_t data;
uint16_t sequenceid;
uint32_t length;
char pad[24];
} __attribute__((packed)) reply;
} response;
union plr_x11_response {
struct {
uint8_t type;
uint8_t errcode;
uint16_t sequenceid;
uint32_t badval;
uint16_t minorop;
uint32_t majorop;
char pad[18];
} __attribute__((packed)) error;
struct {
uint8_t type;
uint8_t data;
uint16_t sequenceid;
uint32_t length;
char pad[24];
} __attribute__((packed)) reply;
};
while (com_std_has_data(xfd)) {
if (!com_std_read(xfd, &response, sizeof response))
static bool plr_x11_poll(com_std_fd xfd, bool wait,
union plr_x11_response *response) {
if (!wait && !com_std_has_data(xfd))
return false;
com_std_read(xfd, response, sizeof(union plr_x11_response));
return true;
}
static bool plr_x11_poll_reply(com_std_fd xfd, uint16_t seqid,
union plr_x11_response *response) {
while (plr_x11_poll(xfd, true, response)) {
/* Wait for match. */
if (response->reply.type == 1 && response->reply.sequenceid == seqid)
break;
/* Errors could be encountered here, report along the way. */
if (response->reply.type == 0) {
com_std_print('c', "X11 error code=", 'u', response->error.errcode, 'c',
" for seqid=", 'u', response->error.sequenceid);
}
}
return true;
}
/* TODO: Instead we should poll for events, errors are only byproduct. */
static bool plr_x11_poll_errors(com_std_fd xfd) {
union plr_x11_response response;
while (plr_x11_poll(xfd, false, &response)) {
/* There should be no replies unhandled. */
/* TODO: Write down encountered events. */
if (response.reply.type == 1)
return false;
/* Exhaust variable length data of reply. */
if (response.reply.type == 1) {
char buf[1024];
com_std_assert(response.reply.length * 4 <= sizeof buf);
if (!com_std_read(xfd, &buf, response.reply.length * 4))
return false;
}
if (response.reply.type == 0 && response.error.errcode != 0) {
if (response.reply.type == 0)
com_std_print('c', "X11 error code=", 'u', response.error.errcode, 'c',
" for seqid=", 'u', response.error.sequenceid);
/* This means X11 closed the connection. */
// if (response.error.errcode == 0)
// return false;
}
/* TODO: Save polled events, as they might be used later. */
};
}
return true;
}
@@ -322,6 +343,7 @@ static uint32_t plr_x11_create_window(com_std_fd xfd) {
}
static bool plr_x11_show_window(com_std_fd xfd, uint32_t window_id) {
uint32_t const seq = plr_x11_next_seqid();
struct {
uint8_t opcode;
uint8_t pad1;
@@ -361,16 +383,82 @@ static uint32_t plr_x11_create_pixmap(com_std_fd xfd, uint32_t window_id) {
return pixmap_id;
}
/* Returns opcode for given extension. */
static uint8_t plr_x11_query_extension(com_std_fd xfd, com_str const *ext) {
uint32_t const seq = plr_x11_next_seqid();
uint16_t const pad = com_bits_nalign(ext->len, 4);
struct {
uint8_t opcode;
uint8_t pad1;
uint16_t request_length;
uint16_t name_length;
uint16_t pad2;
} __attribute__((packed)) request = {
.opcode = 98,
.request_length = sizeof request / 4 + pad / 4,
.name_length = ext->len,
};
if (!com_std_write(xfd, &request, sizeof request))
return 0;
if (!com_std_write(xfd, ext->data, ext->len))
return 0;
if ((pad - ext->len) && !com_std_write(xfd, ext->data, pad - ext->len))
return 0;
union plr_x11_response response;
plr_x11_poll_reply(xfd, seq, &response);
return response.reply.pad[1];
}
/*
This is needed as base X11 doesn't allow passing more than 16bit x 4bytes.
https://xorg.freedesktop.org/archive/current/doc/bigreqsproto/bigreq.html
*/
static bool plr_x11_enable_big_requests(com_std_fd xfd) {
static com_str bigreqext = com_str_lit("BIG-REQUESTS");
uint8_t const opcode = plr_x11_query_extension(xfd, &bigreqext);
/* Request the thing. */
struct {
uint8_t opcode;
uint8_t micode;
uint16_t request_length;
} __attribute__((packed)) request = {
.opcode = opcode,
.request_length = sizeof request / 4,
};
uint32_t const seq = plr_x11_next_seqid();
if (!com_std_write(xfd, &request, sizeof request))
return 0;
/* Read the response. */
union plr_x11_response response;
plr_x11_poll_reply(xfd, seq, &response);
uint32_t const limit = *(uint32_t *)response.reply.pad;
com_std_print('c', "Request limit: ", 'u', limit);
if (limit < COM_CFG_FBSIZE) {
com_std_print('c', "Big request can't accommodate for framebuffer.");
return false;
}
return true;
}
static bool plr_x11_put_framebuffer(com_std_fd xfd, uint32_t gc_id,
uint32_t pixmap_id,
uint8_t pixels[COM_CFG_FBSIZE]) {
uint32_t const seq = plr_x11_next_seqid();
uint32_t const padded = com_bits_nalign(COM_CFG_FBSIZE, 4);
uint32_t const seq = plr_x11_next_seqid();
struct {
uint8_t opcode;
uint8_t format;
uint16_t request_length;
uint16_t bigreq; /* Marked zero so that 32bit could be used. */
uint32_t request_length;
uint32_t drawable_id;
uint32_t gc_id;
uint16_t width;
@@ -398,8 +486,8 @@ static bool plr_x11_put_framebuffer(com_std_fd xfd, uint32_t gc_id,
if (!com_std_write(xfd, pixels, COM_CFG_FBSIZE))
return false;
/* Use request memory for pad, it doesn't matter what we write. */
uint32_t const padfinal = padded - COM_CFG_FBSIZE;
if (padfinal && !com_std_write(xfd, &pixels, padfinal))
if ((padded - COM_CFG_FBSIZE) &&
!com_std_write(xfd, &pixels, padded - COM_CFG_FBSIZE))
return false;
return true;
}
@@ -418,7 +506,7 @@ static bool plr_x11_establish_connection(com_std_fd xfd, int argc,
char const *xauthpath = NULL;
for (char const *const *envp = &argv[argc + 1]; *envp != NULL; ++envp) {
static const struct com_str xauthlit = com_str_lit("XAUTHORITY=");
if (com_str_ext_prefixed(*envp, xauthlit)) {
if (com_str_ext_prefixed(*envp, &xauthlit)) {
xauthpath = &((*envp)[xauthlit.len]);
break;
}
@@ -473,29 +561,11 @@ extern int plr_display_x11_main(int argc, char const *const *argv) {
com_lzw_free_table(&table);
com_std_assert(test);
com_mat_t m0 = com_mat_identity();
com_mat_t m1 = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16};
for (int i = 0; i < 16; ++i)
m1.a[i] *= COM_FIX_FRACUNIT;
com_mat_t t0 = com_mat_mul(m1, m0);
com_mat_t t1 = com_mat_mul_reodered(com_mat_reoder(m1), m0);
com_std_print('f', t0.a[4]);
com_std_print('f', t1.a[4]);
// com_vec_t v0 = com_mat_vec_project(com_mat_reoder(m0), com_vec_identity());
// com_fix_print(v0.a[0]);
/* TODO: Move to separate executable maybe? */
#ifndef NDEBUG
// com_test_run();
com_test_run();
#endif
// com_fix_run_tests();
// com_fix_run_bench();
// com_mat_run_bench();
/* TODO: Move init to separate func. */
/* Open X11 socket for communication. */
com_std_fd const xfd = com_std_socket(false);
if (!xfd) {
@@ -513,6 +583,11 @@ extern int plr_display_x11_main(int argc, char const *const *argv) {
return -1;
}
if (!plr_x11_enable_big_requests(xfd)) {
com_std_print('c', "Big requests unsupported for your X11");
return -1;
}
uint32_t const gc = plr_x11_create_graphical_context(xfd);
if (!gc) {
com_std_print('c', "Failure to initialize X11");
@@ -629,10 +704,10 @@ extern int plr_display_x11_main(int argc, char const *const *argv) {
uint8_t *fbm = plr_draw_get_pixel_buffer();
plr_draw_screen(fbm);
// if (!plr_x11_put_framebuffer(xfd, gc, fb, fbm)) {
// com_std_print('c', "Failure to drive X11");
// return -1;
// }
if (!plr_x11_put_framebuffer(xfd, gc, fb, fbm)) {
com_std_print('c', "Failure to drive X11");
return -1;
}
if (!plr_x11_show_window(xfd, win)) {
com_std_print('c', "Failure to drive X11");
+23 -10
View File
@@ -1,27 +1,37 @@
CC = clang
CC ?= clang
RELEASE ?= 0 # Optimize.
DEBUG ?= 1 # Emit debug info.
SQUEEZE ?= 0 # Nuclear option to save space.
BITS ?= 64
RUN ?= 0
ISCLANG = 1
CFLAGS = -Wall -std=gnu99 -ffast-math -fno-ident -fvisibility=hidden
# Set cosmopolitan toolchain.
ifeq ($(MAKECMDGOALS),cosmo)
ISCLANG = 0
CC = ./Cosmo/bin/cosmocc -mclang
ifeq ($(DEBUG), 1)
CFLAGS += -mdbg
else
CFLAGS += -mtiny
endif
endif
CFLAGS = -Wall -std=gnu99 -ffast-math -fno-ident -fvisibility=hidden
ifeq ($(ISCLANG), 1)
CFLAGS = -flto=thin -fuse-ld=lld
# Provide LTO where it's applicable.
ifeq ($(CC),clang)
ISCLANG = 1
CFLAGS += -flto=thin -fuse-ld=lld
else
ifneq ($(MAKECMDGOALS),cosmo)
CFLAGS += -flto
endif
endif
# Linux specific options.
ifeq ($(MAKECMDGOALS),linux)
CFLAGS += -fno-pic -fno-pie
ifeq ($(RELEASE), 1)
CFLAGS += -Wl,--ignore-data-address-equality -Wl,--ignore-function-address-equality \
# CFLAGS += -Wl,--ignore-data-address-equality -Wl,--ignore-function-address-equality \
-Wl,--optimize-bb-jumps
endif
ifeq ($(SQUEEZE), 1)
@@ -37,11 +47,15 @@ ifeq ($(MAKECMDGOALS),linux)
CFLAGS += -m32 -msse2
endif
endif
# WASM specific options.
ifeq ($(MAKECMDGOALS),wasm)
ifeq ($(RELEASE), 1)
CFLAGS += -Wl,--compress-relocations
endif
endif
# Separate debug and release switches.
ifeq ($(DEBUG), 1)
CFLAGS += -g3
else
@@ -50,7 +64,7 @@ endif
ifeq ($(RELEASE), 1)
CFLAGS += -O3 -fmerge-all-constants -Wl,-O3 \
-ffunction-sections -fdata-sections -Wl,--gc-sections
ifeq ($(ISCLANG), 1)
ifeq ($(CC),clang)
CFLAGS += -Wl,-mllvm,--vectorize-slp=true \
-Wl,-mllvm,--enable-gvn-hoist=true
endif
@@ -66,8 +80,7 @@ wasm:
$(CC) -o player.wasm ./amalgam.c $(CFLAGS)
# todo: Add -mtiny for release without debug
cosmo: CC = ./Cosmo/bin/cosmocc
cosmo: CFLAGS += -I /usr/include/X11 -mclang
cosmo: CFLAGS += -I /usr/include/X11
cosmo: ./amalgam.c
$(CC) $(CFLAGS) -o ./Out/Cosmo/player $^
ifeq ($(RUN), 1)
+27 -26
View File
@@ -29,36 +29,37 @@ com_def_export_sym("plr_draw_screen") void plr_draw_screen(
}
}
com_mat_t proj = com_mat_perspective(COM_CFG_WIDTH, COM_CFG_HEIGHT, 1,
100 * COM_FIX_FRACUNIT, COM_FIX_PIHALF);
com_mat_t view = com_mat_look_at(com_vec_from(0, 0, 0),
com_vec_from(0, COM_FIX_FRACUNIT, 0),
com_vec_from(-COM_FIX_FRACUNIT, 0, 0));
com_mat_t mvp = com_mat_reoder(com_mat_mul(proj, view));
// com_mat_t proj = com_mat_perspective(COM_CFG_WIDTH, COM_CFG_HEIGHT, 1,
// 100 * COM_FIX_FRACUNIT,
// COM_FIX_PIHALF);
// com_mat_t view = com_mat_look_at(com_vec_from(0, 0, 0),
// com_vec_from(0, COM_FIX_FRACUNIT, 0),
// com_vec_from(-COM_FIX_FRACUNIT, 0, 0));
// com_mat_t mvp = com_mat_reoder(com_mat_mul(proj, view));
com_vec_t v0 = com_vec_from(0 * COM_FIX_FRACUNIT, 0, 1 * COM_FIX_FRACUNIT);
com_vec_t v1 = com_vec_from(1 * COM_FIX_FRACUNIT, 1 * COM_FIX_FRACUNIT,
1 * COM_FIX_FRACUNIT);
com_vec_t v2 = com_vec_from(1 * COM_FIX_FRACUNIT, 1 * COM_FIX_FRACUNIT,
1 * COM_FIX_FRACUNIT);
com_vec_t v3 = com_vec_from(1 * COM_FIX_FRACUNIT, 1 * COM_FIX_FRACUNIT,
-1 * COM_FIX_FRACUNIT);
// com_vec_t v0 = com_vec_from(0 * COM_FIX_FRACUNIT, 0, 1 * COM_FIX_FRACUNIT);
// com_vec_t v1 = com_vec_from(1 * COM_FIX_FRACUNIT, 1 * COM_FIX_FRACUNIT,
// 1 * COM_FIX_FRACUNIT);
// com_vec_t v2 = com_vec_from(1 * COM_FIX_FRACUNIT, 1 * COM_FIX_FRACUNIT,
// 1 * COM_FIX_FRACUNIT);
// com_vec_t v3 = com_vec_from(1 * COM_FIX_FRACUNIT, 1 * COM_FIX_FRACUNIT,
// -1 * COM_FIX_FRACUNIT);
com_pnt_t uv0 = com_pnt_from(0 * COM_FIX_FRACUNIT, 0 * COM_FIX_FRACUNIT);
com_pnt_t uv1 = com_pnt_from(1 * COM_FIX_FRACUNIT, 0 * COM_FIX_FRACUNIT);
com_pnt_t uv2 = com_pnt_from(1 * COM_FIX_FRACUNIT, 1 * COM_FIX_FRACUNIT);
com_pnt_t uv3 = com_pnt_from(0 * COM_FIX_FRACUNIT, 1 * COM_FIX_FRACUNIT);
// com_pnt_t uv0 = com_pnt_from(0 * COM_FIX_FRACUNIT, 0 * COM_FIX_FRACUNIT);
// com_pnt_t uv1 = com_pnt_from(1 * COM_FIX_FRACUNIT, 0 * COM_FIX_FRACUNIT);
// com_pnt_t uv2 = com_pnt_from(1 * COM_FIX_FRACUNIT, 1 * COM_FIX_FRACUNIT);
// com_pnt_t uv3 = com_pnt_from(0 * COM_FIX_FRACUNIT, 1 * COM_FIX_FRACUNIT);
com_vec_t c0 = com_gem_vec_project_clip(mvp, v0);
com_vec_t c1 = com_gem_vec_project_clip(mvp, v1);
com_vec_t c2 = com_gem_vec_project_clip(mvp, v2);
com_vec_t c3 = com_gem_vec_project_clip(mvp, v3);
// com_vec_t c0 = com_gem_vec_project_clip(mvp, v0);
// com_vec_t c1 = com_gem_vec_project_clip(mvp, v1);
// com_vec_t c2 = com_gem_vec_project_clip(mvp, v2);
// com_vec_t c3 = com_gem_vec_project_clip(mvp, v3);
com_pnt_t p0, p1, p2, p3;
uint8_t cc0 = com_gem_clip_vis_project(c0, &p0);
uint8_t cc1 = com_gem_clip_vis_project(c1, &p1);
uint8_t cc2 = com_gem_clip_vis_project(c2, &p2);
uint8_t cc3 = com_gem_clip_vis_project(c3, &p3);
// com_pnt_t p0, p1, p2, p3;
// uint8_t cc0 = com_gem_clip_vis_project(c0, &p0);
// uint8_t cc1 = com_gem_clip_vis_project(c1, &p1);
// uint8_t cc2 = com_gem_clip_vis_project(c2, &p2);
// uint8_t cc3 = com_gem_clip_vis_project(c3, &p3);
// com_std_printf("%i, %i\n", p0.a[0], p0.a[1]);
// com_std_printf("%i, %i\n", p1.a[0], p1.a[1]);