Prepare API for multi-display support
These changes are made now to make it possible to add multi-display support in the future while keeping the public interface stable.pull/30/head
parent
737dd311a0
commit
f3e09fd622
|
@ -35,6 +35,7 @@ struct coord {
|
|||
};
|
||||
|
||||
struct draw {
|
||||
struct nvnc_display* display;
|
||||
struct nvnc_fb* fb;
|
||||
struct coord coord[MAX_COORD];
|
||||
int index;
|
||||
|
@ -47,8 +48,8 @@ int coord_distance_between(struct coord a, struct coord b)
|
|||
return round(sqrt(x * x + y * y));
|
||||
}
|
||||
|
||||
void draw_dot(struct nvnc* nvnc, struct nvnc_fb* fb, struct coord coord,
|
||||
int radius, uint32_t colour)
|
||||
void draw_dot(struct nvnc_display* display, struct nvnc_fb* fb,
|
||||
struct coord coord, int radius, uint32_t colour)
|
||||
{
|
||||
uint32_t* image = nvnc_fb_get_addr(fb);
|
||||
int width = nvnc_fb_get_width(fb);
|
||||
|
@ -64,7 +65,7 @@ void draw_dot(struct nvnc* nvnc, struct nvnc_fb* fb, struct coord coord,
|
|||
struct pixman_region16 region;
|
||||
pixman_region_init_rect(®ion, start.x, start.y,
|
||||
stop.x - start.x, stop.y - start.y);
|
||||
nvnc_damage_region(nvnc, ®ion);
|
||||
nvnc_display_damage_region(display, ®ion);
|
||||
pixman_region_fini(®ion);
|
||||
|
||||
/* The brute force method. ;) */
|
||||
|
@ -82,7 +83,7 @@ void on_pointer_event(struct nvnc_client* client, uint16_t x, uint16_t y,
|
|||
if (!(buttons & NVNC_BUTTON_LEFT))
|
||||
return;
|
||||
|
||||
struct nvnc* server = nvnc_get_server(client);
|
||||
struct nvnc* server = nvnc_client_get_server(client);
|
||||
assert(server);
|
||||
|
||||
struct draw* draw = nvnc_get_userdata(server);
|
||||
|
@ -101,17 +102,20 @@ void on_pointer_event(struct nvnc_client* client, uint16_t x, uint16_t y,
|
|||
struct pixman_region16 region;
|
||||
pixman_region_init_rect(®ion, 0, 0, width, height);
|
||||
pixman_region_intersect_rect(®ion, ®ion, x, y, 1, 1);
|
||||
nvnc_damage_region(server, ®ion);
|
||||
nvnc_display_damage_region(draw->display, ®ion);
|
||||
pixman_region_fini(®ion);
|
||||
}
|
||||
|
||||
void on_render(struct nvnc* server, struct nvnc_fb* fb)
|
||||
void on_render(struct nvnc_display* display, struct nvnc_fb* fb)
|
||||
{
|
||||
struct nvnc* server = nvnc_display_get_server(display);
|
||||
assert(server);
|
||||
|
||||
struct draw* draw = nvnc_get_userdata(server);
|
||||
assert(draw);
|
||||
|
||||
for (int i = 0; i < draw->index; ++i)
|
||||
draw_dot(server, fb, draw->coord[i], 16, 0);
|
||||
draw_dot(draw->display, fb, draw->coord[i], 16, 0);
|
||||
|
||||
draw->index = 0;
|
||||
}
|
||||
|
@ -138,12 +142,18 @@ int main(int argc, char* argv[])
|
|||
aml_set_default(aml);
|
||||
|
||||
struct nvnc* server = nvnc_open("127.0.0.1", 5900);
|
||||
assert(server);
|
||||
|
||||
draw.display = nvnc_display_new(0, 0);
|
||||
assert(draw.display);
|
||||
nvnc_display_set_buffer(draw.display, draw.fb);
|
||||
nvnc_display_set_render_fn(draw.display, on_render);
|
||||
|
||||
nvnc_add_display(server, draw.display);
|
||||
|
||||
nvnc_set_name(server, "Draw");
|
||||
nvnc_set_pointer_fn(server, on_pointer_event);
|
||||
nvnc_set_userdata(server, &draw);
|
||||
nvnc_set_buffer(server, draw.fb);
|
||||
nvnc_set_render_fn(server, on_render);
|
||||
|
||||
struct aml_signal* sig = aml_signal_new(SIGINT, on_sigint, NULL, NULL);
|
||||
aml_start(aml_get_default(), sig);
|
||||
|
@ -152,6 +162,7 @@ int main(int argc, char* argv[])
|
|||
aml_run(aml);
|
||||
|
||||
nvnc_close(server);
|
||||
nvnc_display_unref(draw.display);
|
||||
nvnc_fb_unref(draw.fb);
|
||||
aml_unref(aml);
|
||||
}
|
||||
|
|
|
@ -48,11 +48,17 @@ int main(int argc, char* argv[])
|
|||
aml_set_default(aml);
|
||||
|
||||
struct nvnc* server = nvnc_open("127.0.0.1", 5900);
|
||||
assert(server);
|
||||
|
||||
nvnc_set_buffer(server, fb);
|
||||
struct nvnc_display* display = nvnc_display_new(0, 0);
|
||||
assert(display);
|
||||
|
||||
nvnc_display_set_buffer(display, fb);
|
||||
|
||||
nvnc_add_display(server, display);
|
||||
nvnc_set_name(server, file);
|
||||
|
||||
nvnc_damage_whole(server);
|
||||
nvnc_display_damage_whole(display);
|
||||
|
||||
struct aml_signal* sig = aml_signal_new(SIGINT, on_sigint, NULL, NULL);
|
||||
aml_start(aml_get_default(), sig);
|
||||
|
@ -61,6 +67,7 @@ int main(int argc, char* argv[])
|
|||
aml_run(aml);
|
||||
|
||||
nvnc_close(server);
|
||||
nvnc_display_unref(display);
|
||||
nvnc_fb_unref(fb);
|
||||
aml_unref(aml);
|
||||
}
|
||||
|
|
|
@ -52,6 +52,7 @@ struct nvnc;
|
|||
struct stream;
|
||||
struct aml_handler;
|
||||
struct aml_idle;
|
||||
struct nvnc_display;
|
||||
|
||||
struct nvnc_common {
|
||||
void* userdata;
|
||||
|
@ -93,8 +94,7 @@ struct nvnc {
|
|||
nvnc_pointer_fn pointer_fn;
|
||||
nvnc_fb_req_fn fb_req_fn;
|
||||
nvnc_client_fn new_client_fn;
|
||||
nvnc_render_fn render_fn;
|
||||
struct nvnc_fb* buffer;
|
||||
struct nvnc_display* display;
|
||||
|
||||
#ifdef ENABLE_TLS
|
||||
gnutls_certificate_credentials_t tls_creds;
|
||||
|
@ -102,3 +102,6 @@ struct nvnc {
|
|||
void* auth_ud;
|
||||
#endif
|
||||
};
|
||||
|
||||
void nvnc__damage_region(struct nvnc* self,
|
||||
const struct pixman_region16* damage);
|
||||
|
|
|
@ -0,0 +1,33 @@
|
|||
/*
|
||||
* Copyright (c) 2020 Andri Yngvason
|
||||
*
|
||||
* Permission to use, copy, modify, and/or distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
* copyright notice and this permission notice appear in all copies.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
|
||||
* REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
|
||||
* AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
|
||||
* INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
|
||||
* LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
|
||||
* OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
||||
* PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "neatvnc.h"
|
||||
|
||||
#include <stdint.h>
|
||||
#include <pixels.h>
|
||||
|
||||
struct nvnc;
|
||||
struct nvnc_fb;
|
||||
|
||||
struct nvnc_display {
|
||||
int ref;
|
||||
struct nvnc* server;
|
||||
uint16_t x_pos, y_pos;
|
||||
struct nvnc_fb* buffer;
|
||||
nvnc_render_fn render_fn;
|
||||
};
|
|
@ -21,6 +21,7 @@
|
|||
|
||||
struct nvnc;
|
||||
struct nvnc_client;
|
||||
struct nvnc_display;
|
||||
struct nvnc_fb;
|
||||
struct pixman_region16;
|
||||
|
||||
|
@ -47,17 +48,18 @@ typedef void (*nvnc_client_fn)(struct nvnc_client*);
|
|||
typedef void (*nvnc_damage_fn)(struct pixman_region16* damage, void* userdata);
|
||||
typedef bool (*nvnc_auth_fn)(const char* username, const char* password,
|
||||
void* userdata);
|
||||
typedef void (*nvnc_render_fn)(struct nvnc*, struct nvnc_fb*);
|
||||
typedef void (*nvnc_render_fn)(struct nvnc_display*, struct nvnc_fb*);
|
||||
|
||||
struct nvnc* nvnc_open(const char* addr, uint16_t port);
|
||||
void nvnc_close(struct nvnc* self);
|
||||
|
||||
void nvnc_add_display(struct nvnc*, struct nvnc_display*);
|
||||
void nvnc_remove_display(struct nvnc*, struct nvnc_display*);
|
||||
|
||||
void nvnc_set_userdata(void* self, void* userdata);
|
||||
void* nvnc_get_userdata(const void* self);
|
||||
|
||||
struct nvnc* nvnc_get_server(const struct nvnc_client* client);
|
||||
|
||||
void nvnc_set_buffer(struct nvnc*, struct nvnc_fb*);
|
||||
struct nvnc* nvnc_client_get_server(const struct nvnc_client* client);
|
||||
|
||||
void nvnc_set_name(struct nvnc* self, const char* name);
|
||||
|
||||
|
@ -65,7 +67,6 @@ void nvnc_set_key_fn(struct nvnc* self, nvnc_key_fn);
|
|||
void nvnc_set_pointer_fn(struct nvnc* self, nvnc_pointer_fn);
|
||||
void nvnc_set_fb_req_fn(struct nvnc* self, nvnc_fb_req_fn);
|
||||
void nvnc_set_new_client_fn(struct nvnc* self, nvnc_client_fn);
|
||||
void nvnc_set_render_fn(struct nvnc* self, nvnc_render_fn fn);
|
||||
void nvnc_set_client_cleanup_fn(struct nvnc_client* self, nvnc_client_fn fn);
|
||||
|
||||
bool nvnc_has_auth(void);
|
||||
|
@ -86,8 +87,18 @@ uint16_t nvnc_fb_get_width(const struct nvnc_fb* fb);
|
|||
uint16_t nvnc_fb_get_height(const struct nvnc_fb* fb);
|
||||
uint32_t nvnc_fb_get_fourcc_format(const struct nvnc_fb* fb);
|
||||
|
||||
void nvnc_damage_region(struct nvnc*, const struct pixman_region16* damage);
|
||||
void nvnc_damage_whole(struct nvnc*);
|
||||
struct nvnc_display* nvnc_display_new(uint16_t x_pos, uint16_t y_pos);
|
||||
void nvnc_display_ref(struct nvnc_display*);
|
||||
void nvnc_display_unref(struct nvnc_display*);
|
||||
|
||||
struct nvnc* nvnc_display_get_server(const struct nvnc_display*);
|
||||
|
||||
void nvnc_display_set_render_fn(struct nvnc_display* self, nvnc_render_fn fn);
|
||||
void nvnc_display_set_buffer(struct nvnc_display*, struct nvnc_fb*);
|
||||
|
||||
void nvnc_display_damage_region(struct nvnc_display*,
|
||||
const struct pixman_region16*);
|
||||
void nvnc_display_damage_whole(struct nvnc_display*);
|
||||
|
||||
/*
|
||||
* Find the regions that differ between fb0 and fb1. Regions outside the hinted
|
||||
|
|
|
@ -58,6 +58,7 @@ sources = [
|
|||
'src/fb.c',
|
||||
'src/rcbuf.c',
|
||||
'src/stream.c',
|
||||
'src/display.c',
|
||||
]
|
||||
|
||||
dependencies = [
|
||||
|
|
|
@ -0,0 +1,103 @@
|
|||
/*
|
||||
* Copyright (c) 2020 Andri Yngvason
|
||||
*
|
||||
* Permission to use, copy, modify, and/or distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
* copyright notice and this permission notice appear in all copies.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
|
||||
* REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
|
||||
* AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
|
||||
* INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
|
||||
* LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
|
||||
* OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
||||
* PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "display.h"
|
||||
#include "neatvnc.h"
|
||||
#include "common.h"
|
||||
|
||||
#include <assert.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#define EXPORT __attribute__((visibility("default")))
|
||||
|
||||
EXPORT
|
||||
struct nvnc_display* nvnc_display_new(uint16_t x_pos, uint16_t y_pos)
|
||||
{
|
||||
struct nvnc_display* self = calloc(1, sizeof(*self));
|
||||
if (!self)
|
||||
return NULL;
|
||||
|
||||
self->ref = 1;
|
||||
self->x_pos = x_pos;
|
||||
self->y_pos = y_pos;
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
void nvnc__display_free(struct nvnc_display* self)
|
||||
{
|
||||
if (self->buffer)
|
||||
nvnc_fb_unref(self->buffer);
|
||||
free(self);
|
||||
}
|
||||
|
||||
EXPORT
|
||||
void nvnc_display_ref(struct nvnc_display* self)
|
||||
{
|
||||
self->ref++;
|
||||
}
|
||||
|
||||
EXPORT
|
||||
void nvnc_display_unref(struct nvnc_display* self)
|
||||
{
|
||||
if (--self->ref == 0)
|
||||
nvnc__display_free(self);
|
||||
}
|
||||
|
||||
EXPORT
|
||||
struct nvnc* nvnc_display_get_server(const struct nvnc_display* self)
|
||||
{
|
||||
return self->server;
|
||||
}
|
||||
|
||||
EXPORT
|
||||
void nvnc_display_set_buffer(struct nvnc_display* self, struct nvnc_fb* fb)
|
||||
{
|
||||
if (self->buffer)
|
||||
nvnc_fb_unref(self->buffer);
|
||||
|
||||
self->buffer = fb;
|
||||
nvnc_fb_ref(fb);
|
||||
}
|
||||
|
||||
EXPORT
|
||||
void nvnc_display_set_render_fn(struct nvnc_display* self, nvnc_render_fn fn)
|
||||
{
|
||||
self->render_fn = fn;
|
||||
}
|
||||
|
||||
EXPORT
|
||||
void nvnc_display_damage_region(struct nvnc_display* self,
|
||||
const struct pixman_region16* region)
|
||||
{
|
||||
// TODO: Shift according to display position
|
||||
assert(self->server);
|
||||
nvnc__damage_region(self->server, region);
|
||||
}
|
||||
|
||||
EXPORT
|
||||
void nvnc_display_damage_whole(struct nvnc_display* self)
|
||||
{
|
||||
assert(self->server);
|
||||
|
||||
uint16_t width = nvnc_fb_get_width(self->buffer);
|
||||
uint16_t height = nvnc_fb_get_height(self->buffer);
|
||||
|
||||
struct pixman_region16 damage;
|
||||
pixman_region_init_rect(&damage, 0, 0, width, height);
|
||||
nvnc_display_damage_region(self, &damage);
|
||||
pixman_region_fini(&damage);
|
||||
}
|
78
src/server.c
78
src/server.c
|
@ -21,6 +21,7 @@
|
|||
#include "vec.h"
|
||||
#include "type-macros.h"
|
||||
#include "fb.h"
|
||||
#include "display.h"
|
||||
#include "neatvnc.h"
|
||||
#include "common.h"
|
||||
#include "pixels.h"
|
||||
|
@ -348,18 +349,24 @@ static void disconnect_all_other_clients(struct nvnc_client* client)
|
|||
static void send_server_init_message(struct nvnc_client* client)
|
||||
{
|
||||
struct nvnc* server = client->server;
|
||||
struct nvnc_display* display = server->display;
|
||||
|
||||
size_t name_len = strlen(server->name);
|
||||
size_t size = sizeof(struct rfb_server_init_msg) + name_len;
|
||||
|
||||
if (!server->buffer) {
|
||||
log_debug("Tried to send init message, but not buffer has been set\n");
|
||||
if (!display) {
|
||||
log_debug("Tried to send init message, but no display has been added\n");
|
||||
goto close;
|
||||
}
|
||||
|
||||
uint16_t width = nvnc_fb_get_width(server->buffer);
|
||||
uint16_t height = nvnc_fb_get_height(server->buffer);
|
||||
uint32_t fourcc = nvnc_fb_get_fourcc_format(server->buffer);
|
||||
if (!display->buffer) {
|
||||
log_debug("Tried to send init message, but no framebuffers have been set\n");
|
||||
goto close;
|
||||
}
|
||||
|
||||
uint16_t width = nvnc_fb_get_width(display->buffer);
|
||||
uint16_t height = nvnc_fb_get_height(display->buffer);
|
||||
uint32_t fourcc = nvnc_fb_get_fourcc_format(display->buffer);
|
||||
|
||||
struct rfb_server_init_msg* msg = calloc(1, size);
|
||||
if (!msg)
|
||||
|
@ -476,7 +483,7 @@ static int on_client_set_encodings(struct nvnc_client* client)
|
|||
|
||||
static void process_fb_update_requests(struct nvnc_client* client)
|
||||
{
|
||||
if (!client->server->buffer)
|
||||
if (!client->server->display || !client->server->display->buffer)
|
||||
return;
|
||||
|
||||
if (client->net_stream->state == STREAM_STATE_CLOSED)
|
||||
|
@ -829,8 +836,9 @@ void on_main_dispatch(void* aml_obj)
|
|||
return;
|
||||
}
|
||||
|
||||
if (self->render_fn)
|
||||
self->render_fn(self, self->buffer);
|
||||
struct nvnc_display* display = self->display;
|
||||
if (display && display->render_fn)
|
||||
display->render_fn(display, display->buffer);
|
||||
|
||||
LIST_FOREACH(client, &self->clients, link)
|
||||
process_fb_update_requests(client);
|
||||
|
@ -888,8 +896,8 @@ void nvnc_close(struct nvnc* self)
|
|||
{
|
||||
struct nvnc_client* client;
|
||||
|
||||
if (self->buffer)
|
||||
nvnc_fb_unref(self->buffer);
|
||||
if (self->display)
|
||||
nvnc_display_unref(self->display);
|
||||
|
||||
struct nvnc_client* tmp;
|
||||
LIST_FOREACH_SAFE (client, &self->clients, link, tmp)
|
||||
|
@ -1006,7 +1014,7 @@ void on_client_update_fb_done(void* work)
|
|||
|
||||
int schedule_client_update_fb(struct nvnc_client* client)
|
||||
{
|
||||
struct nvnc_fb* fb = client->server->buffer;
|
||||
struct nvnc_fb* fb = client->server->display->buffer;
|
||||
assert(fb);
|
||||
|
||||
DTRACE_PROBE1(neatvnc, update_fb_start, client);
|
||||
|
@ -1060,8 +1068,7 @@ pixfmt_failure:
|
|||
return -1;
|
||||
}
|
||||
|
||||
EXPORT
|
||||
void nvnc_damage_region(struct nvnc* self, const struct pixman_region16* damage)
|
||||
void nvnc__damage_region(struct nvnc* self, const struct pixman_region16* damage)
|
||||
{
|
||||
struct nvnc_client* client;
|
||||
|
||||
|
@ -1071,20 +1078,6 @@ void nvnc_damage_region(struct nvnc* self, const struct pixman_region16* damage)
|
|||
(struct pixman_region16*)damage);
|
||||
}
|
||||
|
||||
EXPORT
|
||||
void nvnc_damage_whole(struct nvnc* self)
|
||||
{
|
||||
assert(self->buffer);
|
||||
|
||||
uint16_t width = nvnc_fb_get_width(self->buffer);
|
||||
uint16_t height = nvnc_fb_get_height(self->buffer);
|
||||
|
||||
struct pixman_region16 damage;
|
||||
pixman_region_init_rect(&damage, 0, 0, width, height);
|
||||
nvnc_damage_region(self, &damage);
|
||||
pixman_region_fini(&damage);
|
||||
}
|
||||
|
||||
EXPORT
|
||||
void nvnc_set_userdata(void* self, void* userdata)
|
||||
{
|
||||
|
@ -1123,12 +1116,6 @@ void nvnc_set_new_client_fn(struct nvnc* self, nvnc_client_fn fn)
|
|||
self->new_client_fn = fn;
|
||||
}
|
||||
|
||||
EXPORT
|
||||
void nvnc_set_render_fn(struct nvnc* self, nvnc_render_fn fn)
|
||||
{
|
||||
self->render_fn = fn;
|
||||
}
|
||||
|
||||
EXPORT
|
||||
void nvnc_set_client_cleanup_fn(struct nvnc_client* self, nvnc_client_fn fn)
|
||||
{
|
||||
|
@ -1136,17 +1123,30 @@ void nvnc_set_client_cleanup_fn(struct nvnc_client* self, nvnc_client_fn fn)
|
|||
}
|
||||
|
||||
EXPORT
|
||||
void nvnc_set_buffer(struct nvnc* self, struct nvnc_fb* fb)
|
||||
void nvnc_add_display(struct nvnc* self, struct nvnc_display* display)
|
||||
{
|
||||
if (self->buffer)
|
||||
nvnc_fb_unref(self->buffer);
|
||||
if (self->display) {
|
||||
log_error("Multiple displays are not implemented. Aborting!\n");
|
||||
abort();
|
||||
}
|
||||
|
||||
self->buffer = fb;
|
||||
nvnc_fb_ref(fb);
|
||||
display->server = self;
|
||||
self->display = display;
|
||||
nvnc_display_ref(display);
|
||||
}
|
||||
|
||||
EXPORT
|
||||
struct nvnc* nvnc_get_server(const struct nvnc_client* client)
|
||||
void nvnc_remove_display(struct nvnc* self, struct nvnc_display* display)
|
||||
{
|
||||
if (self->display != display)
|
||||
return;
|
||||
|
||||
nvnc_display_unref(display);
|
||||
self->display = NULL;
|
||||
}
|
||||
|
||||
EXPORT
|
||||
struct nvnc* nvnc_client_get_server(const struct nvnc_client* client)
|
||||
{
|
||||
return client->server;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue