neatvnc/src/display.c

135 lines
3.3 KiB
C
Raw Normal View History

/*
2021-09-19 20:12:30 +00:00
* Copyright (c) 2020 - 2021 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"
2021-08-29 14:41:57 +00:00
#include "fb.h"
#include "resampler.h"
2021-09-20 21:15:32 +00:00
#include "transform-util.h"
2021-12-24 16:29:37 +00:00
#include "encoder.h"
#include <assert.h>
#include <stdlib.h>
#define EXPORT __attribute__((visibility("default")))
static void nvnc_display__on_resampler_done(struct nvnc_fb* fb,
struct pixman_region16* damage, void* userdata)
2021-09-19 20:12:30 +00:00
{
struct nvnc_display* self = userdata;
2021-09-19 20:12:30 +00:00
if (self->buffer) {
nvnc_fb_release(self->buffer);
nvnc_fb_unref(self->buffer);
}
self->buffer = fb;
nvnc_fb_ref(fb);
nvnc_fb_hold(fb);
assert(self->server);
2021-12-24 16:29:37 +00:00
struct nvnc_client* client;
LIST_FOREACH(client, &self->server->clients, link)
if (client->encoder)
encoder_push(client->encoder, fb, damage);
// TODO: Shift according to display position
2021-09-19 20:12:30 +00:00
nvnc__damage_region(self->server, damage);
}
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->resampler = resampler_create();
2021-09-20 21:15:32 +00:00
if (!self->resampler)
goto resampler_failure;
if (damage_refinery_init(&self->damage_refinery, 0, 0) < 0)
goto refinery_failure;
2021-09-19 20:12:30 +00:00
self->ref = 1;
self->x_pos = x_pos;
self->y_pos = y_pos;
return self;
2021-09-20 21:15:32 +00:00
refinery_failure:
resampler_destroy(self->resampler);
resampler_failure:
free(self);
return NULL;
}
static void nvnc__display_free(struct nvnc_display* self)
{
if (self->buffer) {
nvnc_fb_release(self->buffer);
nvnc_fb_unref(self->buffer);
}
2021-09-20 21:15:32 +00:00
damage_refinery_destroy(&self->damage_refinery);
resampler_destroy(self->resampler);
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
2021-09-19 20:12:30 +00:00
void nvnc_display_feed_buffer(struct nvnc_display* self, struct nvnc_fb* fb,
struct pixman_region16* damage)
{
2021-09-20 21:15:32 +00:00
damage_refinery_resize(&self->damage_refinery, fb->width, fb->height);
// TODO: Run the refinery in a worker thread?
struct pixman_region16 refined_damage;
pixman_region_init(&refined_damage);
damage_refine(&self->damage_refinery, &refined_damage, damage, fb);
struct pixman_region16 transformed_damage;
pixman_region_init(&transformed_damage);
nvnc_transform_region(&transformed_damage, &refined_damage,
fb->transform, fb->width, fb->height);
resampler_feed(self->resampler, fb, &transformed_damage,
nvnc_display__on_resampler_done, self);
2021-09-20 21:15:32 +00:00
pixman_region_fini(&transformed_damage);
2021-09-20 21:15:32 +00:00
pixman_region_fini(&refined_damage);
}