some work on x11 ext
This commit is contained in:
+147
-72
@@ -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");
|
||||
|
||||
Reference in New Issue
Block a user