Replace libuv with aml

aml
Andri Yngvason 2020-03-16 20:09:22 +00:00
parent 3b7839e53b
commit fefaf8060c
9 changed files with 106 additions and 90 deletions

View File

@ -19,7 +19,7 @@
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
#include <uv.h> #include <aml.h>
#include <assert.h> #include <assert.h>
#include <pixman.h> #include <pixman.h>
#include <libdrm/drm_fourcc.h> #include <libdrm/drm_fourcc.h>
@ -66,6 +66,9 @@ int main(int argc, char* argv[])
memset(addr, 0xff, width * height * 4); memset(addr, 0xff, width * height * 4);
struct aml* aml = aml_new(NULL, 0);
aml_set_default(aml);
struct nvnc* server = nvnc_open("127.0.0.1", 5900); struct nvnc* server = nvnc_open("127.0.0.1", 5900);
nvnc_set_dimensions(server, width, height, format); nvnc_set_dimensions(server, width, height, format);
@ -73,7 +76,7 @@ int main(int argc, char* argv[])
nvnc_set_pointer_fn(server, on_pointer_event); nvnc_set_pointer_fn(server, on_pointer_event);
nvnc_set_userdata(server, &draw); nvnc_set_userdata(server, &draw);
uv_run(uv_default_loop(), UV_RUN_DEFAULT); aml_run(aml);
nvnc_close(server); nvnc_close(server);
} }

View File

@ -8,7 +8,7 @@ executable(
dependencies: [ dependencies: [
neatvnc_dep, neatvnc_dep,
pixman, pixman,
libuv, aml,
] ]
) )
@ -22,7 +22,7 @@ if libpng.found()
dependencies: [ dependencies: [
neatvnc_dep, neatvnc_dep,
pixman, pixman,
libuv, aml,
libpng, libpng,
] ]
) )

View File

@ -17,7 +17,7 @@
#include <neatvnc.h> #include <neatvnc.h>
#include <stdio.h> #include <stdio.h>
#include <uv.h> #include <aml.h>
#include <assert.h> #include <assert.h>
#include <pixman.h> #include <pixman.h>
@ -38,6 +38,9 @@ int main(int argc, char* argv[])
return 1; return 1;
} }
struct aml* aml = aml_new(NULL, 0);
aml_set_default(aml);
struct nvnc* server = nvnc_open("127.0.0.1", 5900); struct nvnc* server = nvnc_open("127.0.0.1", 5900);
int width = nvnc_fb_get_width(fb); int width = nvnc_fb_get_width(fb);
@ -53,7 +56,7 @@ int main(int argc, char* argv[])
nvnc_feed_frame(server, fb, &region); nvnc_feed_frame(server, fb, &region);
pixman_region_fini(&region); pixman_region_fini(&region);
uv_run(uv_default_loop(), UV_RUN_DEFAULT); aml_run(aml);
nvnc_close(server); nvnc_close(server);
nvnc_fb_unref(fb); nvnc_fb_unref(fb);

View File

@ -16,7 +16,6 @@
#pragma once #pragma once
#include <uv.h>
#include <stdbool.h> #include <stdbool.h>
#include <pixman.h> #include <pixman.h>
@ -50,6 +49,7 @@ enum nvnc_client_state {
struct nvnc; struct nvnc;
struct stream; struct stream;
struct aml_handler;
struct nvnc_common { struct nvnc_common {
void* userdata; void* userdata;
@ -88,7 +88,7 @@ struct vnc_display {
struct nvnc { struct nvnc {
struct nvnc_common common; struct nvnc_common common;
int fd; int fd;
uv_poll_t poll_handle; struct aml_handler* poll_handle;
struct nvnc_client_list clients; struct nvnc_client_list clients;
struct vnc_display display; struct vnc_display display;
void* userdata; void* userdata;

View File

@ -14,8 +14,6 @@
* PERFORMANCE OF THIS SOFTWARE. * PERFORMANCE OF THIS SOFTWARE.
*/ */
#include <uv.h>
#include "config.h" #include "config.h"
#include "sys/queue.h" #include "sys/queue.h"
#include "rcbuf.h" #include "rcbuf.h"
@ -66,7 +64,7 @@ struct stream {
enum stream_state state; enum stream_state state;
int fd; int fd;
uv_poll_t uv_poll; struct aml_handler* handler;
stream_event_fn on_event; stream_event_fn on_event;
void* userdata; void* userdata;

View File

@ -34,10 +34,16 @@ cc = meson.get_compiler('c')
libm = cc.find_library('m', required: false) libm = cc.find_library('m', required: false)
pixman = dependency('pixman-1') pixman = dependency('pixman-1')
libuv = dependency('libuv')
libturbojpeg = dependency('libturbojpeg', required: get_option('tight-encoding')) libturbojpeg = dependency('libturbojpeg', required: get_option('tight-encoding'))
gnutls = dependency('gnutls', required: get_option('tls')) gnutls = dependency('gnutls', required: get_option('tls'))
aml_project = subproject('aml', required: false)
if aml_project.found()
aml = aml_project.get_variable('aml_dep')
else
aml = dependency('aml')
endif
inc = include_directories('include', 'contrib/miniz') inc = include_directories('include', 'contrib/miniz')
sources = [ sources = [
@ -56,7 +62,7 @@ sources = [
dependencies = [ dependencies = [
libm, libm,
pixman, pixman,
libuv, aml,
] ]
config = configuration_data() config = configuration_data()

View File

@ -8,14 +8,14 @@
#include <string.h> #include <string.h>
#include <sys/param.h> #include <sys/param.h>
#include <libdrm/drm_fourcc.h> #include <libdrm/drm_fourcc.h>
#include <uv.h> #include <aml.h>
#include <assert.h> #include <assert.h>
#define EXPORT __attribute__((visibility("default"))) #define EXPORT __attribute__((visibility("default")))
#define ALIGN_DOWN(a, b) (((a) / (b)) * (b)) #define ALIGN_DOWN(a, b) (((a) / (b)) * (b))
struct damage_check { struct damage_check {
uv_work_t work; struct aml_work* work;
struct nvnc_fb* fb0; struct nvnc_fb* fb0;
struct nvnc_fb* fb1; struct nvnc_fb* fb1;
int x_hint; int x_hint;
@ -86,20 +86,18 @@ int check_damage_linear(struct pixman_region16* damage,
} }
#undef TILE_SIDE_LENGTH #undef TILE_SIDE_LENGTH
void do_damage_check_linear(uv_work_t* work) void do_damage_check_linear(void* work)
{ {
struct damage_check* check = (void*)work; struct damage_check* check = aml_get_userdata(work);
check_damage_linear(&check->damage, check->fb0, check->fb1, check_damage_linear(&check->damage, check->fb0, check->fb1,
check->x_hint, check->y_hint, check->width_hint, check->x_hint, check->y_hint, check->width_hint,
check->height_hint); check->height_hint);
} }
void on_damage_check_done_linear(uv_work_t* work, int status) void on_damage_check_done_linear(void* work)
{ {
(void)status; struct damage_check* check = aml_get_userdata(work);
struct damage_check* check = (void*)work;
check->on_done(&check->damage, check->userdata); check->on_done(&check->damage, check->userdata);
@ -130,17 +128,25 @@ int check_damage_linear_threaded(struct nvnc_fb* fb0, struct nvnc_fb* fb1,
pixman_region_init(&work->damage); pixman_region_init(&work->damage);
/* TODO: Spread the work into more tasks */ /* TODO: Spread the work into more tasks */
int rc = uv_queue_work(uv_default_loop(), &work->work, struct aml_work* obj =
do_damage_check_linear, aml_work_new(do_damage_check_linear, on_damage_check_done_linear,
on_damage_check_done_linear); work, free);
if (rc >= 0) { if (!obj) {
nvnc_fb_ref(fb0);
nvnc_fb_ref(fb1);
} else {
free(work); free(work);
return -1;
} }
return rc; int rc = aml_start(aml_get_default(), obj);
aml_unref(obj);
if (rc < 0)
return -1;
work->work = obj;
nvnc_fb_ref(fb0);
nvnc_fb_ref(fb1);
return 0;
} }
EXPORT EXPORT

View File

@ -33,10 +33,11 @@
#include <sys/queue.h> #include <sys/queue.h>
#include <sys/param.h> #include <sys/param.h>
#include <assert.h> #include <assert.h>
#include <uv.h> #include <aml.h>
#include <libdrm/drm_fourcc.h> #include <libdrm/drm_fourcc.h>
#include <pixman.h> #include <pixman.h>
#include <pthread.h> #include <pthread.h>
#include <errno.h>
#ifdef ENABLE_TLS #ifdef ENABLE_TLS
#include <gnutls/gnutls.h> #include <gnutls/gnutls.h>
@ -55,7 +56,7 @@
#define EXPORT __attribute__((visibility("default"))) #define EXPORT __attribute__((visibility("default")))
struct fb_update_work { struct fb_update_work {
uv_work_t work; struct aml_work* work;
struct nvnc_client* client; struct nvnc_client* client;
struct pixman_region16 region; struct pixman_region16 region;
struct rfb_pixel_format server_fmt; struct rfb_pixel_format server_fmt;
@ -65,19 +66,6 @@ struct fb_update_work {
int schedule_client_update_fb(struct nvnc_client* client); int schedule_client_update_fb(struct nvnc_client* client);
static const char* fourcc_to_string(uint32_t fourcc)
{
static char buffer[5];
buffer[0] = (fourcc >> 0) & 0xff;
buffer[1] = (fourcc >> 8) & 0xff;
buffer[2] = (fourcc >> 16) & 0xff;
buffer[3] = (fourcc >> 24) & 0xff;
buffer[4] = '\0';
return buffer;
}
static void client_close(struct nvnc_client* client) static void client_close(struct nvnc_client* client)
{ {
log_debug("client_close(%p): ref %d\n", client, client->ref); log_debug("client_close(%p): ref %d\n", client, client->ref);
@ -688,10 +676,9 @@ static void on_client_event(struct stream* stream, enum stream_event event)
client->buffer_index = 0; client->buffer_index = 0;
} }
static void on_connection(uv_poll_t* poll_handle, int status, int events) static void on_connection(void* obj)
{ {
struct nvnc* server = struct nvnc* server = aml_get_userdata(obj);
container_of(poll_handle, struct nvnc, poll_handle);
struct nvnc_client* client = calloc(1, sizeof(*client)); struct nvnc_client* client = calloc(1, sizeof(*client));
if (!client) if (!client)
@ -749,6 +736,8 @@ accept_failure:
EXPORT EXPORT
struct nvnc* nvnc_open(const char* address, uint16_t port) struct nvnc* nvnc_open(const char* address, uint16_t port)
{ {
aml_require_workers(aml_get_default(), 4);
struct nvnc* self = calloc(1, sizeof(*self)); struct nvnc* self = calloc(1, sizeof(*self));
if (!self) if (!self)
return NULL; return NULL;
@ -776,11 +765,17 @@ struct nvnc* nvnc_open(const char* address, uint16_t port)
if (listen(self->fd, 16) < 0) if (listen(self->fd, 16) < 0)
goto failure; goto failure;
uv_poll_init(uv_default_loop(), &self->poll_handle, self->fd); self->poll_handle = aml_handler_new(self->fd, on_connection, self, NULL);
uv_poll_start(&self->poll_handle, UV_READABLE, on_connection); if (!self->poll_handle)
goto failure;
if (aml_start(aml_get_default(), self->poll_handle) < 0)
goto start_failure;
return self; return self;
start_failure:
aml_unref(self->poll_handle);
failure: failure:
close(self->fd); close(self->fd);
return NULL; return NULL;
@ -798,7 +793,7 @@ void nvnc_close(struct nvnc* self)
LIST_FOREACH_SAFE (client, &self->clients, link, tmp) LIST_FOREACH_SAFE (client, &self->clients, link, tmp)
client_unref(client); client_unref(client);
uv_poll_stop(&self->poll_handle); aml_stop(aml_get_default(), self->poll_handle);
close(self->fd); close(self->fd);
#ifdef ENABLE_TLS #ifdef ENABLE_TLS
@ -808,6 +803,7 @@ void nvnc_close(struct nvnc* self)
} }
#endif #endif
aml_unref(self->poll_handle);
free(self); free(self);
} }
@ -835,9 +831,9 @@ enum rfb_encodings choose_frame_encoding(struct nvnc_client* client)
return -1; return -1;
} }
void do_client_update_fb(uv_work_t* work) void do_client_update_fb(void* work)
{ {
struct fb_update_work* update = (void*)work; struct fb_update_work* update = aml_get_userdata(work);
struct nvnc_client* client = update->client; struct nvnc_client* client = update->client;
const struct nvnc_fb* fb = update->fb; const struct nvnc_fb* fb = update->fb;
@ -873,11 +869,9 @@ void do_client_update_fb(uv_work_t* work)
} }
} }
void on_client_update_fb_done(uv_work_t* work, int status) void on_client_update_fb_done(void* work)
{ {
(void)status; struct fb_update_work* update = aml_get_userdata(work);
struct fb_update_work* update = (void*)work;
struct nvnc_client* client = update->client; struct nvnc_client* client = update->client;
struct vec* frame = &update->frame; struct vec* frame = &update->frame;
@ -901,7 +895,6 @@ void on_client_update_fb_done(uv_work_t* work, int status)
pixman_region_fini(&update->region); pixman_region_fini(&update->region);
client_unref(client); client_unref(client);
free(update);
} }
int schedule_client_update_fb(struct nvnc_client* client) int schedule_client_update_fb(struct nvnc_client* client)
@ -930,14 +923,25 @@ int schedule_client_update_fb(struct nvnc_client* client)
client_ref(client); client_ref(client);
nvnc_fb_ref(fb); nvnc_fb_ref(fb);
rc = uv_queue_work(uv_default_loop(), &work->work, do_client_update_fb, struct aml_work* obj =
on_client_update_fb_done); aml_work_new(do_client_update_fb, on_client_update_fb_done,
work, free);
if (!obj) {
goto oom_failure;
}
rc = aml_start(aml_get_default(), obj);
aml_unref(obj);
if (rc < 0) if (rc < 0)
goto queue_failure; goto start_failure;
work->work = obj;
return 0; return 0;
queue_failure: start_failure:
work = NULL; /* handled in unref */
oom_failure:
nvnc_fb_unref(fb); nvnc_fb_unref(fb);
client_unref(client); client_unref(client);
vec_destroy(&work->frame); vec_destroy(&work->frame);

View File

@ -21,38 +21,37 @@
#include <assert.h> #include <assert.h>
#include <errno.h> #include <errno.h>
#include <sys/uio.h> #include <sys/uio.h>
#include <uv.h> #include <limits.h>
#include <aml.h>
#include <fcntl.h>
#include <poll.h>
#ifdef ENABLE_TLS #ifdef ENABLE_TLS
#include <gnutls/gnutls.h> #include <gnutls/gnutls.h>
#endif #endif
#include "type-macros.h"
#include "rcbuf.h" #include "rcbuf.h"
#include "stream.h" #include "stream.h"
#include "sys/queue.h" #include "sys/queue.h"
static void stream__on_event(uv_poll_t* uv_poll, int status, int events); static void stream__on_event(void* obj);
#ifdef ENABLE_TLS #ifdef ENABLE_TLS
static int stream__try_tls_accept(struct stream* self); static int stream__try_tls_accept(struct stream* self);
#endif #endif
static inline void stream__poll_r(struct stream* self) static inline void stream__poll_r(struct stream* self)
{ {
uv_poll_start(&self->uv_poll, UV_READABLE | UV_DISCONNECT, aml_set_event_mask(self->handler, POLLIN);
stream__on_event);
} }
static inline void stream__poll_w(struct stream* self) static inline void stream__poll_w(struct stream* self)
{ {
uv_poll_start(&self->uv_poll, UV_WRITABLE | UV_DISCONNECT, aml_set_event_mask(self->handler, POLLOUT);
stream__on_event);
} }
static inline void stream__poll_rw(struct stream* self) static inline void stream__poll_rw(struct stream* self)
{ {
uv_poll_start(&self->uv_poll, UV_READABLE | UV_DISCONNECT | UV_WRITABLE, aml_set_event_mask(self->handler, POLLIN | POLLOUT);
stream__on_event);
} }
static void stream_req__finish(struct stream_req* req, enum stream_req_status status) static void stream_req__finish(struct stream_req* req, enum stream_req_status status)
@ -83,24 +82,18 @@ int stream_close(struct stream* self)
self->tls_session = NULL; self->tls_session = NULL;
#endif #endif
uv_poll_stop(&self->uv_poll); // TODO: Maybe use explicit loop object instead of the default one?
aml_stop(aml_get_default(), self->handler);
close(self->fd); close(self->fd);
self->fd = -1; self->fd = -1;
return 0; return 0;
} }
void stream__free_poll_handle(uv_handle_t* handle)
{
uv_poll_t* uv_poll = (uv_poll_t*)handle;
struct stream* self = container_of(uv_poll, struct stream, uv_poll);
free(self);
}
void stream_destroy(struct stream* self) void stream_destroy(struct stream* self)
{ {
stream_close(self); stream_close(self);
uv_close((uv_handle_t*)&self->uv_poll, stream__free_poll_handle); aml_unref(self->handler);
} }
static void stream__remote_closed(struct stream* self) static void stream__remote_closed(struct stream* self)
@ -268,19 +261,15 @@ static void stream__on_writable(struct stream* self)
} }
} }
static void stream__on_event(uv_poll_t* uv_poll, int status, int events) static void stream__on_event(void* obj)
{ {
struct stream* self = container_of(uv_poll, struct stream, uv_poll); struct stream* self = aml_get_userdata(obj);
uint32_t events = aml_get_revents(obj);
if (events & UV_DISCONNECT) { if (events & POLLIN)
stream__remote_closed(self);
return;
}
if (events & UV_READABLE)
stream__on_readable(self); stream__on_readable(self);
if (events & UV_WRITABLE) if (events & POLLOUT)
stream__on_writable(self); stream__on_writable(self);
} }
@ -298,13 +287,20 @@ struct stream* stream_new(int fd, stream_event_fn on_event, void* userdata)
fcntl(fd, F_SETFL, fcntl(fd, F_GETFL, 0) | O_NONBLOCK); fcntl(fd, F_SETFL, fcntl(fd, F_GETFL, 0) | O_NONBLOCK);
if (uv_poll_init(uv_default_loop(), &self->uv_poll, fd) < 0) self->handler = aml_handler_new(fd, stream__on_event, self, free);
if (!self->handler)
goto failure; goto failure;
if (aml_start(aml_get_default(), self->handler) < 0)
goto start_failure;
stream__poll_r(self); stream__poll_r(self);
return self; return self;
start_failure:
aml_unref(self->handler);
self = NULL; /* Handled in unref */
failure: failure:
free(self); free(self);
return NULL; return NULL;
@ -393,7 +389,7 @@ static int stream__try_tls_accept(struct stream* self)
} }
if (gnutls_error_is_fatal(rc)) { if (gnutls_error_is_fatal(rc)) {
uv_poll_stop(&self->uv_poll); aml_stop(aml_get_default(), &self->handler);
return -1; return -1;
} }