Let neatvnc handle buffer transforms
parent
87c040c919
commit
61ebb57696
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2020 Andri Yngvason
|
* Copyright (c) 2020 - 2021 Andri Yngvason
|
||||||
*
|
*
|
||||||
* Permission to use, copy, modify, and/or distribute this software for any
|
* Permission to use, copy, modify, and/or distribute this software for any
|
||||||
* purpose with or without fee is hereby granted, provided that the above
|
* purpose with or without fee is hereby granted, provided that the above
|
||||||
|
@ -26,6 +26,7 @@
|
||||||
|
|
||||||
struct wl_buffer;
|
struct wl_buffer;
|
||||||
struct gbm_bo;
|
struct gbm_bo;
|
||||||
|
struct nvnc_fb;
|
||||||
|
|
||||||
enum wv_buffer_type {
|
enum wv_buffer_type {
|
||||||
WV_BUFFER_UNSPEC = 0,
|
WV_BUFFER_UNSPEC = 0,
|
||||||
|
@ -39,6 +40,7 @@ struct wv_buffer {
|
||||||
enum wv_buffer_type type;
|
enum wv_buffer_type type;
|
||||||
TAILQ_ENTRY(wv_buffer) link;
|
TAILQ_ENTRY(wv_buffer) link;
|
||||||
|
|
||||||
|
struct nvnc_fb* nvnc_fb;
|
||||||
struct wl_buffer* wl_buffer;
|
struct wl_buffer* wl_buffer;
|
||||||
|
|
||||||
void* pixels;
|
void* pixels;
|
||||||
|
@ -51,7 +53,6 @@ struct wv_buffer {
|
||||||
|
|
||||||
/* The following is only applicable to DMABUF */
|
/* The following is only applicable to DMABUF */
|
||||||
struct gbm_bo* bo;
|
struct gbm_bo* bo;
|
||||||
void* bo_map_handle;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
TAILQ_HEAD(wv_buffer_queue, wv_buffer);
|
TAILQ_HEAD(wv_buffer_queue, wv_buffer);
|
||||||
|
@ -69,9 +70,6 @@ struct wv_buffer* wv_buffer_create(enum wv_buffer_type, int width, int height,
|
||||||
int stride, uint32_t fourcc);
|
int stride, uint32_t fourcc);
|
||||||
void wv_buffer_destroy(struct wv_buffer* self);
|
void wv_buffer_destroy(struct wv_buffer* self);
|
||||||
|
|
||||||
int wv_buffer_map(struct wv_buffer* self);
|
|
||||||
void wv_buffer_unmap(struct wv_buffer* self);
|
|
||||||
|
|
||||||
void wv_buffer_damage_rect(struct wv_buffer* self, int x, int y, int width,
|
void wv_buffer_damage_rect(struct wv_buffer* self, int x, int y, int width,
|
||||||
int height);
|
int height);
|
||||||
void wv_buffer_damage_whole(struct wv_buffer* self);
|
void wv_buffer_damage_whole(struct wv_buffer* self);
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2020 Andri Yngvason
|
* Copyright (c) 2020 - 2021 Andri Yngvason
|
||||||
*
|
*
|
||||||
* Permission to use, copy, modify, and/or distribute this software for any
|
* Permission to use, copy, modify, and/or distribute this software for any
|
||||||
* purpose with or without fee is hereby granted, provided that the above
|
* purpose with or without fee is hereby granted, provided that the above
|
||||||
|
@ -29,6 +29,8 @@ struct damage_refinery {
|
||||||
|
|
||||||
int damage_refinery_init(struct damage_refinery* self, uint32_t width,
|
int damage_refinery_init(struct damage_refinery* self, uint32_t width,
|
||||||
uint32_t height);
|
uint32_t height);
|
||||||
|
int damage_refinery_resize(struct damage_refinery* self, uint32_t width,
|
||||||
|
uint32_t height);
|
||||||
void damage_refinery_destroy(struct damage_refinery* self);
|
void damage_refinery_destroy(struct damage_refinery* self);
|
||||||
|
|
||||||
void damage_refine(struct damage_refinery* self,
|
void damage_refine(struct damage_refinery* self,
|
||||||
|
|
|
@ -1,27 +0,0 @@
|
||||||
/*
|
|
||||||
* 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 <wayland-client.h>
|
|
||||||
|
|
||||||
struct nvnc_fb;
|
|
||||||
struct wv_buffer;
|
|
||||||
struct pixman_region16;
|
|
||||||
|
|
||||||
void wv_pixman_render(struct nvnc_fb* dst, const struct wv_buffer* src,
|
|
||||||
enum wl_output_transform transform,
|
|
||||||
struct pixman_region16* damage);
|
|
|
@ -87,7 +87,6 @@ sources = [
|
||||||
'src/intset.c',
|
'src/intset.c',
|
||||||
'src/buffer.c',
|
'src/buffer.c',
|
||||||
'src/pixels.c',
|
'src/pixels.c',
|
||||||
'src/pixman-renderer.c',
|
|
||||||
'src/transform-util.c',
|
'src/transform-util.c',
|
||||||
'src/damage-refinery.c',
|
'src/damage-refinery.c',
|
||||||
'src/murmurhash.c',
|
'src/murmurhash.c',
|
||||||
|
|
102
src/buffer.c
102
src/buffer.c
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2020 Andri Yngvason
|
* Copyright (c) 2020 - 2021 Andri Yngvason
|
||||||
*
|
*
|
||||||
* Permission to use, copy, modify, and/or distribute this software for any
|
* Permission to use, copy, modify, and/or distribute this software for any
|
||||||
* purpose with or without fee is hereby granted, provided that the above
|
* purpose with or without fee is hereby granted, provided that the above
|
||||||
|
@ -23,6 +23,7 @@
|
||||||
#include <libdrm/drm_fourcc.h>
|
#include <libdrm/drm_fourcc.h>
|
||||||
#include <wayland-client.h>
|
#include <wayland-client.h>
|
||||||
#include <pixman.h>
|
#include <pixman.h>
|
||||||
|
#include <neatvnc.h>
|
||||||
|
|
||||||
#include "linux-dmabuf-unstable-v1.h"
|
#include "linux-dmabuf-unstable-v1.h"
|
||||||
#include "shm.h"
|
#include "shm.h"
|
||||||
|
@ -90,14 +91,24 @@ struct wv_buffer* wv_buffer_create_shm(int width,
|
||||||
if (!self->wl_buffer)
|
if (!self->wl_buffer)
|
||||||
goto shm_failure;
|
goto shm_failure;
|
||||||
|
|
||||||
|
// TODO: Get the pixel size from the format instead of assuming it's 4.
|
||||||
|
self->nvnc_fb = nvnc_fb_from_buffer(self->pixels, width, height, fourcc,
|
||||||
|
stride / 4);
|
||||||
|
if (!self->nvnc_fb) {
|
||||||
|
goto nvnc_fb_failure;
|
||||||
|
}
|
||||||
|
|
||||||
|
nvnc_set_userdata(self->nvnc_fb, self, NULL);
|
||||||
|
|
||||||
pixman_region_init(&self->damage);
|
pixman_region_init(&self->damage);
|
||||||
|
|
||||||
close(fd);
|
close(fd);
|
||||||
return self;
|
return self;
|
||||||
|
|
||||||
|
nvnc_fb_failure:
|
||||||
|
wl_buffer_destroy(self->wl_buffer);
|
||||||
shm_failure:
|
shm_failure:
|
||||||
pool_failure:
|
pool_failure:
|
||||||
munmap(self->pixels, self->size);
|
|
||||||
mmap_failure:
|
mmap_failure:
|
||||||
close(fd);
|
close(fd);
|
||||||
failure:
|
failure:
|
||||||
|
@ -148,8 +159,17 @@ static struct wv_buffer* wv_buffer_create_dmabuf(int width, int height,
|
||||||
if (!self->wl_buffer)
|
if (!self->wl_buffer)
|
||||||
goto buffer_failure;
|
goto buffer_failure;
|
||||||
|
|
||||||
|
self->nvnc_fb = nvnc_fb_from_gbm_bo(self->bo);
|
||||||
|
if (!self->nvnc_fb) {
|
||||||
|
goto nvnc_fb_failure;
|
||||||
|
}
|
||||||
|
|
||||||
|
nvnc_set_userdata(self->nvnc_fb, self, NULL);
|
||||||
|
|
||||||
return self;
|
return self;
|
||||||
|
|
||||||
|
nvnc_fb_failure:
|
||||||
|
wl_buffer_destroy(self->wl_buffer);
|
||||||
buffer_failure:
|
buffer_failure:
|
||||||
fd_failure:
|
fd_failure:
|
||||||
zwp_linux_buffer_params_v1_destroy(params);
|
zwp_linux_buffer_params_v1_destroy(params);
|
||||||
|
@ -180,6 +200,7 @@ struct wv_buffer* wv_buffer_create(enum wv_buffer_type type, int width,
|
||||||
|
|
||||||
static void wv_buffer_destroy_shm(struct wv_buffer* self)
|
static void wv_buffer_destroy_shm(struct wv_buffer* self)
|
||||||
{
|
{
|
||||||
|
nvnc_fb_unref(self->nvnc_fb);
|
||||||
wl_buffer_destroy(self->wl_buffer);
|
wl_buffer_destroy(self->wl_buffer);
|
||||||
munmap(self->pixels, self->size);
|
munmap(self->pixels, self->size);
|
||||||
free(self);
|
free(self);
|
||||||
|
@ -188,6 +209,7 @@ static void wv_buffer_destroy_shm(struct wv_buffer* self)
|
||||||
#ifdef ENABLE_SCREENCOPY_DMABUF
|
#ifdef ENABLE_SCREENCOPY_DMABUF
|
||||||
static void wv_buffer_destroy_dmabuf(struct wv_buffer* self)
|
static void wv_buffer_destroy_dmabuf(struct wv_buffer* self)
|
||||||
{
|
{
|
||||||
|
nvnc_fb_unref(self->nvnc_fb);
|
||||||
wl_buffer_destroy(self->wl_buffer);
|
wl_buffer_destroy(self->wl_buffer);
|
||||||
gbm_bo_destroy(self->bo);
|
gbm_bo_destroy(self->bo);
|
||||||
free(self);
|
free(self);
|
||||||
|
@ -197,7 +219,6 @@ static void wv_buffer_destroy_dmabuf(struct wv_buffer* self)
|
||||||
void wv_buffer_destroy(struct wv_buffer* self)
|
void wv_buffer_destroy(struct wv_buffer* self)
|
||||||
{
|
{
|
||||||
pixman_region_fini(&self->damage);
|
pixman_region_fini(&self->damage);
|
||||||
wv_buffer_unmap(self);
|
|
||||||
|
|
||||||
switch (self->type) {
|
switch (self->type) {
|
||||||
case WV_BUFFER_SHM:
|
case WV_BUFFER_SHM:
|
||||||
|
@ -214,64 +235,6 @@ void wv_buffer_destroy(struct wv_buffer* self)
|
||||||
abort();
|
abort();
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef ENABLE_SCREENCOPY_DMABUF
|
|
||||||
static int wv_buffer_map_dmabuf(struct wv_buffer* self)
|
|
||||||
{
|
|
||||||
if (self->bo_map_handle)
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
uint32_t stride = 0;
|
|
||||||
self->pixels = gbm_bo_map(self->bo, 0, 0, self->width, self->height,
|
|
||||||
GBM_BO_TRANSFER_READ, &stride, &self->bo_map_handle);
|
|
||||||
self->stride = stride;
|
|
||||||
if (self->pixels)
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
self->bo_map_handle = NULL;
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
int wv_buffer_map(struct wv_buffer* self)
|
|
||||||
{
|
|
||||||
switch (self->type) {
|
|
||||||
case WV_BUFFER_SHM:
|
|
||||||
return 0;
|
|
||||||
#ifdef ENABLE_SCREENCOPY_DMABUF
|
|
||||||
case WV_BUFFER_DMABUF:
|
|
||||||
return wv_buffer_map_dmabuf(self);
|
|
||||||
#endif
|
|
||||||
case WV_BUFFER_UNSPEC:;
|
|
||||||
}
|
|
||||||
|
|
||||||
abort();
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifdef ENABLE_SCREENCOPY_DMABUF
|
|
||||||
static void wv_buffer_unmap_dmabuf(struct wv_buffer* self)
|
|
||||||
{
|
|
||||||
if (self->bo_map_handle)
|
|
||||||
gbm_bo_unmap(self->bo, self->bo_map_handle);
|
|
||||||
self->bo_map_handle = NULL;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
void wv_buffer_unmap(struct wv_buffer* self)
|
|
||||||
{
|
|
||||||
switch (self->type) {
|
|
||||||
case WV_BUFFER_SHM:
|
|
||||||
return;
|
|
||||||
#ifdef ENABLE_SCREENCOPY_DMABUF
|
|
||||||
case WV_BUFFER_DMABUF:
|
|
||||||
return wv_buffer_unmap_dmabuf(self);
|
|
||||||
#endif
|
|
||||||
case WV_BUFFER_UNSPEC:;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
abort();
|
|
||||||
}
|
|
||||||
|
|
||||||
void wv_buffer_damage_rect(struct wv_buffer* self, int x, int y, int width,
|
void wv_buffer_damage_rect(struct wv_buffer* self, int x, int y, int width,
|
||||||
int height)
|
int height)
|
||||||
{
|
{
|
||||||
|
@ -365,9 +328,16 @@ static bool wv_buffer_pool_match_buffer(struct wv_buffer_pool* pool,
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void wv_buffer_pool__on_release(struct nvnc_fb* fb, void* context)
|
||||||
|
{
|
||||||
|
struct wv_buffer* buffer = nvnc_get_userdata(fb);
|
||||||
|
struct wv_buffer_pool* pool = context;
|
||||||
|
|
||||||
|
wv_buffer_pool_release(pool, buffer);
|
||||||
|
}
|
||||||
|
|
||||||
struct wv_buffer* wv_buffer_pool_acquire(struct wv_buffer_pool* pool)
|
struct wv_buffer* wv_buffer_pool_acquire(struct wv_buffer_pool* pool)
|
||||||
{
|
{
|
||||||
|
|
||||||
struct wv_buffer* buffer = TAILQ_FIRST(&pool->queue);
|
struct wv_buffer* buffer = TAILQ_FIRST(&pool->queue);
|
||||||
if (buffer) {
|
if (buffer) {
|
||||||
assert(wv_buffer_pool_match_buffer(pool, buffer));
|
assert(wv_buffer_pool_match_buffer(pool, buffer));
|
||||||
|
@ -375,15 +345,19 @@ struct wv_buffer* wv_buffer_pool_acquire(struct wv_buffer_pool* pool)
|
||||||
return buffer;
|
return buffer;
|
||||||
}
|
}
|
||||||
|
|
||||||
return wv_buffer_create(pool->type, pool->width, pool->height,
|
buffer = wv_buffer_create(pool->type, pool->width, pool->height,
|
||||||
pool->stride, pool->format);
|
pool->stride, pool->format);
|
||||||
|
if (buffer)
|
||||||
|
nvnc_fb_set_release_fn(buffer->nvnc_fb,
|
||||||
|
wv_buffer_pool__on_release, pool);
|
||||||
|
|
||||||
|
return buffer;
|
||||||
}
|
}
|
||||||
|
|
||||||
void wv_buffer_pool_release(struct wv_buffer_pool* pool,
|
void wv_buffer_pool_release(struct wv_buffer_pool* pool,
|
||||||
struct wv_buffer* buffer)
|
struct wv_buffer* buffer)
|
||||||
{
|
{
|
||||||
wv_buffer_damage_clear(buffer);
|
wv_buffer_damage_clear(buffer);
|
||||||
wv_buffer_unmap(buffer);
|
|
||||||
|
|
||||||
if (wv_buffer_pool_match_buffer(pool, buffer)) {
|
if (wv_buffer_pool_match_buffer(pool, buffer)) {
|
||||||
TAILQ_INSERT_TAIL(&pool->queue, buffer, link);
|
TAILQ_INSERT_TAIL(&pool->queue, buffer, link);
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2020 Andri Yngvason
|
* Copyright (c) 2020 - 2021 Andri Yngvason
|
||||||
*
|
*
|
||||||
* Permission to use, copy, modify, and/or distribute this software for any
|
* Permission to use, copy, modify, and/or distribute this software for any
|
||||||
* purpose with or without fee is hereby granted, provided that the above
|
* purpose with or without fee is hereby granted, provided that the above
|
||||||
|
@ -44,6 +44,16 @@ int damage_refinery_init(struct damage_refinery* self, uint32_t width,
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int damage_refinery_resize(struct damage_refinery* self, uint32_t width,
|
||||||
|
uint32_t height)
|
||||||
|
{
|
||||||
|
if (width == self->width && height == self->height)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
damage_refinery_destroy(self);
|
||||||
|
return damage_refinery_init(self, width, height);
|
||||||
|
}
|
||||||
|
|
||||||
void damage_refinery_destroy(struct damage_refinery* self)
|
void damage_refinery_destroy(struct damage_refinery* self)
|
||||||
{
|
{
|
||||||
free(self->hashes);
|
free(self->hashes);
|
||||||
|
|
129
src/main.c
129
src/main.c
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2019 - 2020 Andri Yngvason
|
* Copyright (c) 2019 - 2021 Andri Yngvason
|
||||||
*
|
*
|
||||||
* Permission to use, copy, modify, and/or distribute this software for any
|
* Permission to use, copy, modify, and/or distribute this software for any
|
||||||
* purpose with or without fee is hereby granted, provided that the above
|
* purpose with or without fee is hereby granted, provided that the above
|
||||||
|
@ -49,7 +49,6 @@
|
||||||
#include "keyboard.h"
|
#include "keyboard.h"
|
||||||
#include "seat.h"
|
#include "seat.h"
|
||||||
#include "cfg.h"
|
#include "cfg.h"
|
||||||
#include "pixman-renderer.h"
|
|
||||||
#include "transform-util.h"
|
#include "transform-util.h"
|
||||||
#include "damage-refinery.h"
|
#include "damage-refinery.h"
|
||||||
#include "usdt.h"
|
#include "usdt.h"
|
||||||
|
@ -68,13 +67,6 @@
|
||||||
|
|
||||||
#define MAYBE_UNUSED __attribute__((unused))
|
#define MAYBE_UNUSED __attribute__((unused))
|
||||||
|
|
||||||
struct fb_side_data {
|
|
||||||
struct pixman_region16 damage;
|
|
||||||
LIST_ENTRY(fb_side_data) link;
|
|
||||||
};
|
|
||||||
|
|
||||||
LIST_HEAD(fb_side_data_list, fb_side_data);
|
|
||||||
|
|
||||||
struct wayvnc {
|
struct wayvnc {
|
||||||
bool do_exit;
|
bool do_exit;
|
||||||
|
|
||||||
|
@ -103,8 +95,6 @@ struct wayvnc {
|
||||||
|
|
||||||
struct nvnc* nvnc;
|
struct nvnc* nvnc;
|
||||||
struct nvnc_display* nvnc_display;
|
struct nvnc_display* nvnc_display;
|
||||||
struct nvnc_fb_pool* fb_pool;
|
|
||||||
struct fb_side_data_list fb_side_data_list;
|
|
||||||
|
|
||||||
struct damage_refinery damage_refinery;
|
struct damage_refinery damage_refinery;
|
||||||
|
|
||||||
|
@ -559,37 +549,6 @@ int wayvnc_start_capture_immediate(struct wayvnc* self)
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void fb_side_data_destroy(void* userdata)
|
|
||||||
{
|
|
||||||
struct fb_side_data* fb_side_data = userdata;
|
|
||||||
LIST_REMOVE(fb_side_data, link);
|
|
||||||
pixman_region_fini(&fb_side_data->damage);
|
|
||||||
free(fb_side_data);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void wv_damage_all_buffers(struct wayvnc* self,
|
|
||||||
struct pixman_region16* region)
|
|
||||||
{
|
|
||||||
struct fb_side_data *item;
|
|
||||||
LIST_FOREACH(item, &self->fb_side_data_list, link)
|
|
||||||
pixman_region_union(&item->damage, &item->damage, region);
|
|
||||||
}
|
|
||||||
|
|
||||||
void wayvnc_render_to_fb(struct wayvnc* self, struct nvnc_fb* fb)
|
|
||||||
{
|
|
||||||
DTRACE_PROBE(wayvnc, render_start);
|
|
||||||
|
|
||||||
struct fb_side_data* fb_side_data = nvnc_get_userdata(fb);
|
|
||||||
assert(fb_side_data);
|
|
||||||
|
|
||||||
enum wl_output_transform transform = self->selected_output->transform;
|
|
||||||
wv_pixman_render(fb, self->screencopy.back, transform,
|
|
||||||
&fb_side_data->damage);
|
|
||||||
pixman_region_clear(&fb_side_data->damage);
|
|
||||||
|
|
||||||
DTRACE_PROBE(wayvnc, render_end);
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO: Handle transform change too
|
// TODO: Handle transform change too
|
||||||
void on_output_dimension_change(struct output* output)
|
void on_output_dimension_change(struct output* output)
|
||||||
{
|
{
|
||||||
|
@ -621,73 +580,40 @@ static uint32_t calculate_region_area(struct pixman_region16* region)
|
||||||
|
|
||||||
void wayvnc_process_frame(struct wayvnc* self)
|
void wayvnc_process_frame(struct wayvnc* self)
|
||||||
{
|
{
|
||||||
uint32_t width = output_get_transformed_width(self->selected_output);
|
struct wv_buffer* buffer = self->screencopy.back;
|
||||||
uint32_t height = output_get_transformed_height(self->selected_output);
|
self->screencopy.back = NULL;
|
||||||
uint32_t format = self->screencopy.back->format;
|
|
||||||
|
|
||||||
if ((int)self->selected_output->width != self->screencopy.back->width
|
|
||||||
|| (int)self->selected_output->height != self->screencopy.back->height) {
|
|
||||||
log_debug("Frame dimensions don't match output. Recapturing frame...\n");
|
|
||||||
wayvnc_start_capture_immediate(self);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool dimensions_changed =
|
|
||||||
nvnc_fb_pool_resize(self->fb_pool, width, height, format,
|
|
||||||
width);
|
|
||||||
if (dimensions_changed) {
|
|
||||||
damage_refinery_destroy(&self->damage_refinery);
|
|
||||||
damage_refinery_init(&self->damage_refinery,
|
|
||||||
self->screencopy.back->width,
|
|
||||||
self->screencopy.back->height);
|
|
||||||
}
|
|
||||||
|
|
||||||
struct nvnc_fb *fb = nvnc_fb_pool_acquire(self->fb_pool);
|
|
||||||
if (!fb) {
|
|
||||||
log_error("Failed to acquire a vnc buffer\n");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
struct fb_side_data* fb_side_data = nvnc_get_userdata(fb);
|
|
||||||
if (!fb_side_data) {
|
|
||||||
fb_side_data = calloc(1, sizeof(*fb_side_data));
|
|
||||||
assert(fb_side_data);
|
|
||||||
|
|
||||||
/* This is a new buffer, so the whole surface is damaged. */
|
|
||||||
pixman_region_init_rect(&fb_side_data->damage, 0, 0, width,
|
|
||||||
height);
|
|
||||||
|
|
||||||
nvnc_set_userdata(fb, fb_side_data, fb_side_data_destroy);
|
|
||||||
LIST_INSERT_HEAD(&self->fb_side_data_list, fb_side_data, link);
|
|
||||||
}
|
|
||||||
|
|
||||||
self->n_frames_captured++;
|
self->n_frames_captured++;
|
||||||
self->damage_area_sum +=
|
self->damage_area_sum +=
|
||||||
calculate_region_area(&self->screencopy.back->damage);
|
calculate_region_area(&buffer->damage);
|
||||||
|
|
||||||
|
uint32_t width = buffer->width;
|
||||||
|
uint32_t height = buffer->height;
|
||||||
|
|
||||||
|
damage_refinery_resize(&self->damage_refinery, width, height);
|
||||||
|
|
||||||
DTRACE_PROBE(wayvnc, refine_damage_start);
|
DTRACE_PROBE(wayvnc, refine_damage_start);
|
||||||
|
struct pixman_region16 refined;
|
||||||
struct pixman_region16 txdamage, refined;
|
|
||||||
pixman_region_init(&txdamage);
|
|
||||||
pixman_region_init(&refined);
|
pixman_region_init(&refined);
|
||||||
damage_refine(&self->damage_refinery, &refined,
|
damage_refine(&self->damage_refinery, &refined, &buffer->damage,
|
||||||
&self->screencopy.back->damage,
|
buffer);
|
||||||
self->screencopy.back);
|
DTRACE_PROBE(wayvnc, refine_damage_end);
|
||||||
|
|
||||||
|
struct pixman_region16 txdamage;
|
||||||
|
pixman_region_init(&txdamage);
|
||||||
wv_region_transform(&txdamage, &refined,
|
wv_region_transform(&txdamage, &refined,
|
||||||
self->selected_output->transform,
|
self->selected_output->transform,
|
||||||
self->selected_output->width,
|
self->selected_output->width,
|
||||||
self->selected_output->height);
|
self->selected_output->height);
|
||||||
|
|
||||||
wv_damage_all_buffers(self, &txdamage);
|
|
||||||
wayvnc_render_to_fb(self, fb);
|
|
||||||
nvnc_display_set_buffer(self->nvnc_display, fb);
|
|
||||||
nvnc_fb_unref(fb);
|
|
||||||
nvnc_display_damage_region(self->nvnc_display, &txdamage);
|
|
||||||
|
|
||||||
pixman_region_fini(&refined);
|
pixman_region_fini(&refined);
|
||||||
pixman_region_fini(&txdamage);
|
|
||||||
|
|
||||||
DTRACE_PROBE(wayvnc, refine_damage_end);
|
nvnc_fb_set_transform(buffer->nvnc_fb,
|
||||||
|
(enum nvnc_transform)self->selected_output->transform);
|
||||||
|
|
||||||
|
nvnc_display_feed_buffer(self->nvnc_display, buffer->nvnc_fb,
|
||||||
|
&txdamage);
|
||||||
|
|
||||||
|
pixman_region_fini(&txdamage);
|
||||||
|
|
||||||
wayvnc_start_capture(self);
|
wayvnc_start_capture(self);
|
||||||
}
|
}
|
||||||
|
@ -1011,12 +937,6 @@ int main(int argc, char* argv[])
|
||||||
if (init_nvnc(&self, address, port, use_unix_socket) < 0)
|
if (init_nvnc(&self, address, port, use_unix_socket) < 0)
|
||||||
goto nvnc_failure;
|
goto nvnc_failure;
|
||||||
|
|
||||||
self.fb_pool = nvnc_fb_pool_new(0, 0, 0, 0);
|
|
||||||
if (!self.fb_pool)
|
|
||||||
goto buffer_pool_failure;
|
|
||||||
|
|
||||||
LIST_INIT(&self.fb_side_data_list);
|
|
||||||
|
|
||||||
if (self.screencopy.manager)
|
if (self.screencopy.manager)
|
||||||
screencopy_init(&self.screencopy);
|
screencopy_init(&self.screencopy);
|
||||||
|
|
||||||
|
@ -1049,7 +969,6 @@ int main(int argc, char* argv[])
|
||||||
|
|
||||||
damage_refinery_destroy(&self.damage_refinery);
|
damage_refinery_destroy(&self.damage_refinery);
|
||||||
|
|
||||||
nvnc_fb_pool_unref(self.fb_pool);
|
|
||||||
nvnc_display_unref(self.nvnc_display);
|
nvnc_display_unref(self.nvnc_display);
|
||||||
nvnc_close(self.nvnc);
|
nvnc_close(self.nvnc);
|
||||||
if (zwp_linux_dmabuf)
|
if (zwp_linux_dmabuf)
|
||||||
|
@ -1070,8 +989,6 @@ int main(int argc, char* argv[])
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
capture_failure:
|
capture_failure:
|
||||||
nvnc_fb_pool_unref(self.fb_pool);
|
|
||||||
buffer_pool_failure:
|
|
||||||
nvnc_display_unref(self.nvnc_display);
|
nvnc_display_unref(self.nvnc_display);
|
||||||
nvnc_close(self.nvnc);
|
nvnc_close(self.nvnc);
|
||||||
nvnc_failure:
|
nvnc_failure:
|
||||||
|
|
|
@ -1,75 +0,0 @@
|
||||||
/*
|
|
||||||
* 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 <stdlib.h>
|
|
||||||
#include <pixman.h>
|
|
||||||
#include <wayland-client.h>
|
|
||||||
#include <neatvnc.h>
|
|
||||||
#include <assert.h>
|
|
||||||
|
|
||||||
#include "buffer.h"
|
|
||||||
#include "pixels.h"
|
|
||||||
#include "transform-util.h"
|
|
||||||
|
|
||||||
void wv_pixman_render(struct nvnc_fb* dst, const struct wv_buffer* src,
|
|
||||||
enum wl_output_transform transform,
|
|
||||||
struct pixman_region16* damage)
|
|
||||||
{
|
|
||||||
uint32_t* dst_pixels = nvnc_fb_get_addr(dst);
|
|
||||||
uint32_t dst_width = nvnc_fb_get_width(dst);
|
|
||||||
uint32_t dst_height = nvnc_fb_get_height(dst);
|
|
||||||
bool ok __attribute__((unused));
|
|
||||||
|
|
||||||
// TODO: Check that both buffers have the same dimensions after applying
|
|
||||||
// transform
|
|
||||||
|
|
||||||
pixman_format_code_t dst_fmt = 0;
|
|
||||||
ok = fourcc_to_pixman_fmt(&dst_fmt, nvnc_fb_get_fourcc_format(dst));
|
|
||||||
assert(ok);
|
|
||||||
|
|
||||||
pixman_image_t* dstimg = pixman_image_create_bits_no_clear(
|
|
||||||
dst_fmt, dst_width, dst_height, dst_pixels,
|
|
||||||
4 * dst_width);
|
|
||||||
|
|
||||||
intptr_t src_offset = src->y_inverted ?
|
|
||||||
src->stride * (src->height - 1) : 0;
|
|
||||||
void* src_pixels = (void*)((intptr_t)src->pixels + src_offset);
|
|
||||||
int src_stride = src->y_inverted ? -src->stride : src->stride;
|
|
||||||
|
|
||||||
pixman_format_code_t src_fmt = 0;
|
|
||||||
ok = fourcc_to_pixman_fmt(&src_fmt, src->format);
|
|
||||||
assert(ok);
|
|
||||||
|
|
||||||
pixman_image_t* srcimg = pixman_image_create_bits_no_clear(
|
|
||||||
src_fmt, src->width, src->height, src_pixels,
|
|
||||||
src_stride);
|
|
||||||
|
|
||||||
pixman_transform_t pxform;
|
|
||||||
wv_pixman_transform_from_wl_output_transform(&pxform, transform,
|
|
||||||
src->width, src->height);
|
|
||||||
|
|
||||||
pixman_image_set_transform(srcimg, &pxform);
|
|
||||||
pixman_image_set_clip_region(dstimg, damage);
|
|
||||||
|
|
||||||
pixman_image_composite(PIXMAN_OP_OVER, srcimg, NULL, dstimg,
|
|
||||||
0, 0,
|
|
||||||
0, 0,
|
|
||||||
0, 0,
|
|
||||||
dst_width, dst_height);
|
|
||||||
|
|
||||||
pixman_image_unref(srcimg);
|
|
||||||
pixman_image_unref(dstimg);
|
|
||||||
}
|
|
|
@ -176,8 +176,6 @@ static void screencopy_ready(void* data,
|
||||||
self->back = self->front;
|
self->back = self->front;
|
||||||
self->front = NULL;
|
self->front = NULL;
|
||||||
|
|
||||||
wv_buffer_map(self->back);
|
|
||||||
|
|
||||||
self->status = SCREENCOPY_DONE;
|
self->status = SCREENCOPY_DONE;
|
||||||
self->on_done(self);
|
self->on_done(self);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue