Render using pixman
parent
4fb472f611
commit
a6e1ba25ea
|
@ -21,6 +21,7 @@
|
||||||
#include "wlr-screencopy-unstable-v1.h"
|
#include "wlr-screencopy-unstable-v1.h"
|
||||||
#include "frame-capture.h"
|
#include "frame-capture.h"
|
||||||
#include "smooth.h"
|
#include "smooth.h"
|
||||||
|
#include "buffer.h"
|
||||||
|
|
||||||
struct zwlr_screencopy_manager_v1;
|
struct zwlr_screencopy_manager_v1;
|
||||||
struct zwlr_screencopy_frame_v1;
|
struct zwlr_screencopy_frame_v1;
|
||||||
|
@ -40,11 +41,9 @@ enum screencopy_status {
|
||||||
struct screencopy {
|
struct screencopy {
|
||||||
struct frame_capture frame_capture;
|
struct frame_capture frame_capture;
|
||||||
|
|
||||||
struct wl_shm* wl_shm;
|
struct wv_buffer_pool* pool;
|
||||||
struct wl_buffer* buffer;
|
struct wv_buffer* front;
|
||||||
|
struct wv_buffer* back;
|
||||||
void* pixels;
|
|
||||||
size_t bufsize;
|
|
||||||
|
|
||||||
struct zwlr_screencopy_manager_v1* manager;
|
struct zwlr_screencopy_manager_v1* manager;
|
||||||
struct zwlr_screencopy_frame_v1* frame;
|
struct zwlr_screencopy_frame_v1* frame;
|
||||||
|
|
|
@ -70,6 +70,7 @@ sources = [
|
||||||
'src/cfg.c',
|
'src/cfg.c',
|
||||||
'src/intset.c',
|
'src/intset.c',
|
||||||
'src/damage.c',
|
'src/damage.c',
|
||||||
|
'src/buffer.c',
|
||||||
]
|
]
|
||||||
|
|
||||||
dependencies = [
|
dependencies = [
|
||||||
|
|
66
src/main.c
66
src/main.c
|
@ -106,6 +106,8 @@ void wayvnc_exit(struct wayvnc* self);
|
||||||
void on_capture_done(struct frame_capture* capture);
|
void on_capture_done(struct frame_capture* capture);
|
||||||
static void on_render(struct nvnc_display* display, struct nvnc_fb* fb);
|
static void on_render(struct nvnc_display* display, struct nvnc_fb* fb);
|
||||||
|
|
||||||
|
struct wl_shm* wl_shm = NULL;
|
||||||
|
|
||||||
static enum frame_capture_backend_type
|
static enum frame_capture_backend_type
|
||||||
frame_capture_backend_from_string(const char* str)
|
frame_capture_backend_from_string(const char* str)
|
||||||
{
|
{
|
||||||
|
@ -147,8 +149,7 @@ static void registry_add(void* data, struct wl_registry* registry,
|
||||||
}
|
}
|
||||||
|
|
||||||
if (strcmp(interface, wl_shm_interface.name) == 0) {
|
if (strcmp(interface, wl_shm_interface.name) == 0) {
|
||||||
self->screencopy_backend.wl_shm
|
wl_shm = wl_registry_bind(registry, id, &wl_shm_interface, 1);
|
||||||
= wl_registry_bind(registry, id, &wl_shm_interface, 1);
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -241,7 +242,7 @@ void wayvnc_destroy(struct wayvnc* self)
|
||||||
|
|
||||||
zxdg_output_manager_v1_destroy(self->xdg_output_manager);
|
zxdg_output_manager_v1_destroy(self->xdg_output_manager);
|
||||||
|
|
||||||
wl_shm_destroy(self->screencopy_backend.wl_shm);
|
wl_shm_destroy(wl_shm);
|
||||||
|
|
||||||
zwp_virtual_keyboard_v1_destroy(self->keyboard_backend.virtual_keyboard);
|
zwp_virtual_keyboard_v1_destroy(self->keyboard_backend.virtual_keyboard);
|
||||||
zwp_virtual_keyboard_manager_v1_destroy(self->keyboard_manager);
|
zwp_virtual_keyboard_manager_v1_destroy(self->keyboard_manager);
|
||||||
|
@ -479,16 +480,48 @@ static void on_render(struct nvnc_display* display, struct nvnc_fb* fb)
|
||||||
struct nvnc* nvnc = nvnc_display_get_server(display);
|
struct nvnc* nvnc = nvnc_display_get_server(display);
|
||||||
struct wayvnc* self = nvnc_get_userdata(nvnc);
|
struct wayvnc* self = nvnc_get_userdata(nvnc);
|
||||||
|
|
||||||
struct pixman_box16* ext = pixman_region_extents(&self->current_damage);
|
if (!self->screencopy_backend.back)
|
||||||
uint32_t y = ext->y1;
|
return;
|
||||||
uint32_t damage_height = ext->y2 - ext->y1;
|
|
||||||
|
|
||||||
uint32_t* addr = nvnc_fb_get_addr(fb);
|
uint32_t* addr = nvnc_fb_get_addr(fb);
|
||||||
uint32_t width = nvnc_fb_get_width(fb);
|
uint32_t width = nvnc_fb_get_width(fb);
|
||||||
|
uint32_t height = nvnc_fb_get_height(fb);
|
||||||
|
|
||||||
renderer_read_frame(&self->renderer, addr + y * width, y, damage_height);
|
pixman_image_t* dstimg = pixman_image_create_bits_no_clear(
|
||||||
|
PIXMAN_x8b8g8r8, width, height, addr, 4 * width);
|
||||||
|
|
||||||
|
pixman_image_t* srcimg = self->screencopy_backend.back->image;
|
||||||
|
|
||||||
|
#define F1 pixman_fixed_1
|
||||||
|
pixman_transform_t y_invert = {{
|
||||||
|
{ F1, 0, 0 },
|
||||||
|
{ 0, -F1, height * F1 },
|
||||||
|
{ 0, 0, F1},
|
||||||
|
}};
|
||||||
|
#undef F1
|
||||||
|
|
||||||
|
pixman_transform_t identity;
|
||||||
|
pixman_transform_init_identity(&identity);
|
||||||
|
|
||||||
|
if (self->screencopy_backend.back->y_inverted)
|
||||||
|
pixman_image_set_transform(srcimg, &y_invert);
|
||||||
|
else
|
||||||
|
pixman_image_set_transform(srcimg, &identity);
|
||||||
|
|
||||||
|
pixman_image_set_clip_region(srcimg, &self->current_damage);
|
||||||
|
|
||||||
|
pixman_image_composite(PIXMAN_OP_OVER, srcimg, NULL, dstimg,
|
||||||
|
0, 0,
|
||||||
|
0, 0,
|
||||||
|
0, 0,
|
||||||
|
width, height);
|
||||||
|
|
||||||
|
|
||||||
|
pixman_image_unref(dstimg);
|
||||||
pixman_region_clear(&self->current_damage);
|
pixman_region_clear(&self->current_damage);
|
||||||
|
|
||||||
|
// XXX: This releases the buffer for now
|
||||||
|
frame_capture_render(self->capture_backend, &self->renderer, fb);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void wayvnc_damage_region(struct wayvnc* self,
|
static void wayvnc_damage_region(struct wayvnc* self,
|
||||||
|
@ -523,13 +556,13 @@ static void on_damage_check_done(struct pixman_region16* damage, void* userdata)
|
||||||
|
|
||||||
void wayvnc_process_frame(struct wayvnc* self)
|
void wayvnc_process_frame(struct wayvnc* self)
|
||||||
{
|
{
|
||||||
uint32_t format = fourcc_from_gl_format(self->renderer.read_format);
|
// uint32_t format = fourcc_from_gl_format(self->renderer.read_format);
|
||||||
uint32_t width = output_get_transformed_width(self->selected_output);
|
uint32_t width = output_get_transformed_width(self->selected_output);
|
||||||
uint32_t height = output_get_transformed_height(self->selected_output);
|
uint32_t height = output_get_transformed_height(self->selected_output);
|
||||||
bool is_first_frame = false;
|
bool is_first_frame = false;
|
||||||
|
|
||||||
if (!self->buffer) {
|
if (!self->buffer) {
|
||||||
self->buffer = nvnc_fb_new(width, height, format);
|
self->buffer = nvnc_fb_new(width, height, DRM_FORMAT_XBGR8888);
|
||||||
nvnc_display_set_buffer(self->nvnc_display, self->buffer);
|
nvnc_display_set_buffer(self->nvnc_display, self->buffer);
|
||||||
is_first_frame = true;
|
is_first_frame = true;
|
||||||
} else {
|
} else {
|
||||||
|
@ -538,11 +571,9 @@ void wayvnc_process_frame(struct wayvnc* self)
|
||||||
assert(height == nvnc_fb_get_height(self->buffer));
|
assert(height == nvnc_fb_get_height(self->buffer));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
struct nvnc_fb* fb = self->buffer;
|
struct nvnc_fb* fb = self->buffer;
|
||||||
|
|
||||||
// TODO: Fix constness on fb in this function
|
|
||||||
frame_capture_render(self->capture_backend, &self->renderer, fb);
|
|
||||||
|
|
||||||
if (!is_first_frame) {
|
if (!is_first_frame) {
|
||||||
uint32_t hint_x = self->capture_backend->damage_hint.x;
|
uint32_t hint_x = self->capture_backend->damage_hint.x;
|
||||||
uint32_t hint_y = self->capture_backend->damage_hint.y;
|
uint32_t hint_y = self->capture_backend->damage_hint.y;
|
||||||
|
@ -572,8 +603,17 @@ void wayvnc_process_frame(struct wayvnc* self)
|
||||||
on_damage_check_done, self);
|
on_damage_check_done, self);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
wayvnc_damage_whole(self);
|
int damx = self->capture_backend->damage_hint.x;
|
||||||
|
int damy = self->capture_backend->damage_hint.y;
|
||||||
|
int damw = self->capture_backend->damage_hint.width;
|
||||||
|
int damh = self->capture_backend->damage_hint.height;
|
||||||
|
|
||||||
|
struct pixman_region16 damage;
|
||||||
|
pixman_region_init_rect(&damage, damx, damy, damw, damh);
|
||||||
|
wayvnc_damage_region(self, &damage);
|
||||||
|
pixman_region_fini(&damage);
|
||||||
|
|
||||||
if (wayvnc_start_capture(self, 0) < 0) {
|
if (wayvnc_start_capture(self, 0) < 0) {
|
||||||
log_error("Failed to start capture. Exiting...\n");
|
log_error("Failed to start capture. Exiting...\n");
|
||||||
|
|
|
@ -24,6 +24,8 @@
|
||||||
#include <libdrm/drm_fourcc.h>
|
#include <libdrm/drm_fourcc.h>
|
||||||
#include <aml.h>
|
#include <aml.h>
|
||||||
|
|
||||||
|
#include "wlr-screencopy-unstable-v1.h"
|
||||||
|
#include "buffer.h"
|
||||||
#include "frame-capture.h"
|
#include "frame-capture.h"
|
||||||
#include "shm.h"
|
#include "shm.h"
|
||||||
#include "screencopy.h"
|
#include "screencopy.h"
|
||||||
|
@ -44,48 +46,6 @@ static uint32_t fourcc_from_wl_shm(enum wl_shm_format in)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static int screencopy_buffer_init(struct screencopy* self,
|
|
||||||
enum wl_shm_format format, uint32_t width,
|
|
||||||
uint32_t height, uint32_t stride)
|
|
||||||
{
|
|
||||||
if (self->buffer)
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
size_t size = stride * height;
|
|
||||||
|
|
||||||
int fd = shm_alloc_fd(size);
|
|
||||||
if (fd < 0)
|
|
||||||
return -1;
|
|
||||||
|
|
||||||
void* addr = mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
|
|
||||||
if (!addr)
|
|
||||||
goto mmap_failure;
|
|
||||||
|
|
||||||
struct wl_shm_pool* pool = wl_shm_create_pool(self->wl_shm, fd, size);
|
|
||||||
if (!pool)
|
|
||||||
goto shm_failure;
|
|
||||||
|
|
||||||
struct wl_buffer* buffer =
|
|
||||||
wl_shm_pool_create_buffer(pool, 0, width, height, stride,
|
|
||||||
format);
|
|
||||||
wl_shm_pool_destroy(pool);
|
|
||||||
if (!buffer)
|
|
||||||
goto shm_failure;
|
|
||||||
|
|
||||||
self->buffer = buffer;
|
|
||||||
self->pixels = addr;
|
|
||||||
self->bufsize = size;
|
|
||||||
|
|
||||||
close(fd);
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
shm_failure:
|
|
||||||
munmap(addr, size);
|
|
||||||
mmap_failure:
|
|
||||||
close(fd);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void screencopy_stop(struct frame_capture* fc)
|
static void screencopy_stop(struct frame_capture* fc)
|
||||||
{
|
{
|
||||||
struct screencopy* self = (void*)fc;
|
struct screencopy* self = (void*)fc;
|
||||||
|
@ -107,34 +67,41 @@ static void screencopy_buffer(void* data,
|
||||||
{
|
{
|
||||||
struct screencopy* self = data;
|
struct screencopy* self = data;
|
||||||
|
|
||||||
if (screencopy_buffer_init(self, format, width, height, stride) < 0) {
|
uint32_t fourcc = fourcc_from_wl_shm(format);
|
||||||
|
wv_buffer_pool_resize(self->pool, width, height, stride, fourcc);
|
||||||
|
|
||||||
|
struct wv_buffer* buffer = wv_buffer_pool_acquire(self->pool);
|
||||||
|
if (!buffer) {
|
||||||
self->frame_capture.status = CAPTURE_FATAL;
|
self->frame_capture.status = CAPTURE_FATAL;
|
||||||
screencopy_stop(&self->frame_capture);
|
screencopy_stop(&self->frame_capture);
|
||||||
self->frame_capture.on_done(&self->frame_capture);
|
self->frame_capture.on_done(&self->frame_capture);
|
||||||
}
|
}
|
||||||
|
|
||||||
self->frame_capture.frame_info.fourcc_format =
|
buffer->y_inverted = true;
|
||||||
fourcc_from_wl_shm(format);
|
|
||||||
|
assert(!self->front);
|
||||||
|
self->front = buffer;
|
||||||
|
|
||||||
|
self->frame_capture.frame_info.fourcc_format = fourcc;
|
||||||
self->frame_capture.frame_info.width = width;
|
self->frame_capture.frame_info.width = width;
|
||||||
self->frame_capture.frame_info.height = height;
|
self->frame_capture.frame_info.height = height;
|
||||||
self->frame_capture.frame_info.stride = stride;
|
self->frame_capture.frame_info.stride = stride;
|
||||||
|
|
||||||
if (self->is_immediate_copy)
|
if (self->is_immediate_copy)
|
||||||
zwlr_screencopy_frame_v1_copy(self->frame, self->buffer);
|
zwlr_screencopy_frame_v1_copy(self->frame, buffer->wl_buffer);
|
||||||
else
|
else
|
||||||
zwlr_screencopy_frame_v1_copy_with_damage(self->frame,
|
zwlr_screencopy_frame_v1_copy_with_damage(self->frame,
|
||||||
self->buffer);
|
buffer->wl_buffer);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void screencopy_flags(void* data,
|
static void screencopy_flags(void* data,
|
||||||
struct zwlr_screencopy_frame_v1* frame,
|
struct zwlr_screencopy_frame_v1* frame,
|
||||||
uint32_t flags)
|
uint32_t flags)
|
||||||
{
|
{
|
||||||
(void)data;
|
struct screencopy* self = data;
|
||||||
(void)frame;
|
(void)frame;
|
||||||
(void)flags;
|
|
||||||
|
|
||||||
/* TODO. Assume y-invert for now */
|
// self->buffer->y_inverted = !!(flags & ZWLR_SCREENCOPY_FRAME_V1_FLAGS_Y_INVERT);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void screencopy_ready(void* data,
|
static void screencopy_ready(void* data,
|
||||||
|
@ -165,6 +132,11 @@ static void screencopy_ready(void* data,
|
||||||
self->frame_capture.frame_info.height;
|
self->frame_capture.frame_info.height;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (self->back)
|
||||||
|
wv_buffer_pool_release(self->pool, self->back);
|
||||||
|
self->back = self->front;
|
||||||
|
self->front = NULL;
|
||||||
|
|
||||||
self->frame_capture.status = CAPTURE_DONE;
|
self->frame_capture.status = CAPTURE_DONE;
|
||||||
self->frame_capture.on_done(&self->frame_capture);
|
self->frame_capture.on_done(&self->frame_capture);
|
||||||
}
|
}
|
||||||
|
@ -260,18 +232,21 @@ static int screencopy_start(struct frame_capture* fc,
|
||||||
static void screencopy_render(struct frame_capture* fc,
|
static void screencopy_render(struct frame_capture* fc,
|
||||||
struct renderer* renderer, struct nvnc_fb* fb)
|
struct renderer* renderer, struct nvnc_fb* fb)
|
||||||
{
|
{
|
||||||
struct screencopy* self = (void*)fc;
|
/*
|
||||||
|
|
||||||
uint32_t width = fc->frame_info.width;
|
uint32_t width = fc->frame_info.width;
|
||||||
uint32_t height = fc->frame_info.height;
|
uint32_t height = fc->frame_info.height;
|
||||||
uint32_t stride = fc->frame_info.stride;
|
uint32_t stride = fc->frame_info.stride;
|
||||||
uint32_t format = fc->frame_info.fourcc_format;
|
uint32_t format = fc->frame_info.fourcc_format;
|
||||||
|
|
||||||
render_framebuffer(renderer, self->pixels, format, width, height, stride);
|
render_framebuffer(renderer, self->pixels, format, width, height, stride);
|
||||||
|
*/
|
||||||
}
|
}
|
||||||
|
|
||||||
void screencopy_init(struct screencopy* self)
|
void screencopy_init(struct screencopy* self)
|
||||||
{
|
{
|
||||||
|
self->pool = wv_buffer_pool_create(0, 0, 0, 0);
|
||||||
|
assert(self->pool);
|
||||||
|
|
||||||
self->timer = aml_timer_new(0, screencopy__poll, self, NULL);
|
self->timer = aml_timer_new(0, screencopy__poll, self, NULL);
|
||||||
assert(self->timer);
|
assert(self->timer);
|
||||||
|
|
||||||
|
@ -287,6 +262,10 @@ void screencopy_destroy(struct screencopy* self)
|
||||||
aml_stop(aml_get_default(), self->timer);
|
aml_stop(aml_get_default(), self->timer);
|
||||||
aml_unref(self->timer);
|
aml_unref(self->timer);
|
||||||
|
|
||||||
if (self->buffer)
|
if (self->back)
|
||||||
wl_buffer_destroy(self->buffer);
|
wv_buffer_pool_release(self->pool, self->back);
|
||||||
|
if (self->front)
|
||||||
|
wv_buffer_pool_release(self->pool, self->front);
|
||||||
|
|
||||||
|
wv_buffer_pool_destroy(self->pool);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue