Create pixman renderer
parent
47a8dc8040
commit
49a2d578d9
|
@ -0,0 +1,11 @@
|
||||||
|
#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);
|
|
@ -71,6 +71,8 @@ sources = [
|
||||||
'src/intset.c',
|
'src/intset.c',
|
||||||
'src/damage.c',
|
'src/damage.c',
|
||||||
'src/buffer.c',
|
'src/buffer.c',
|
||||||
|
'src/pixels.c',
|
||||||
|
'src/pixman-renderer.c',
|
||||||
]
|
]
|
||||||
|
|
||||||
dependencies = [
|
dependencies = [
|
||||||
|
|
42
src/main.c
42
src/main.c
|
@ -52,6 +52,7 @@
|
||||||
#include "seat.h"
|
#include "seat.h"
|
||||||
#include "cfg.h"
|
#include "cfg.h"
|
||||||
#include "damage.h"
|
#include "damage.h"
|
||||||
|
#include "pixman-renderer.h"
|
||||||
|
|
||||||
#define DEFAULT_ADDRESS "127.0.0.1"
|
#define DEFAULT_ADDRESS "127.0.0.1"
|
||||||
#define DEFAULT_PORT 5900
|
#define DEFAULT_PORT 5900
|
||||||
|
@ -483,45 +484,10 @@ static void on_render(struct nvnc_display* display, struct nvnc_fb* fb)
|
||||||
if (!self->screencopy_backend.back)
|
if (!self->screencopy_backend.back)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
uint32_t* addr = nvnc_fb_get_addr(fb);
|
enum wl_output_transform transform = self->selected_output->transform;
|
||||||
uint32_t width = nvnc_fb_get_width(fb);
|
wv_pixman_render(fb, self->screencopy_backend.back, transform,
|
||||||
uint32_t height = nvnc_fb_get_height(fb);
|
&self->current_damage);
|
||||||
|
|
||||||
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,
|
||||||
|
|
|
@ -0,0 +1,162 @@
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <pixman.h>
|
||||||
|
#include <wayland-client.h>
|
||||||
|
#include <neatvnc.h>
|
||||||
|
|
||||||
|
#include "buffer.h"
|
||||||
|
#include "pixels.h"
|
||||||
|
|
||||||
|
void pixman_transform_from_wl_output_transform(pixman_transform_t* dst,
|
||||||
|
enum wl_output_transform src, int width, int height)
|
||||||
|
{
|
||||||
|
#define F1 pixman_fixed_1
|
||||||
|
switch (src) {
|
||||||
|
case WL_OUTPUT_TRANSFORM_NORMAL:
|
||||||
|
{
|
||||||
|
pixman_transform_t t = {{
|
||||||
|
{ F1, 0, 0 },
|
||||||
|
{ 0, F1, 0 },
|
||||||
|
{ 0, 0, F1 },
|
||||||
|
}};
|
||||||
|
*dst = t;
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
case WL_OUTPUT_TRANSFORM_90:
|
||||||
|
{
|
||||||
|
pixman_transform_t t = {{
|
||||||
|
{ 0, F1, 0 },
|
||||||
|
{ -F1, 0, height * F1 },
|
||||||
|
{ 0, 0, F1 },
|
||||||
|
}};
|
||||||
|
*dst = t;
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
case WL_OUTPUT_TRANSFORM_180:
|
||||||
|
{
|
||||||
|
pixman_transform_t t = {{
|
||||||
|
{ -F1, 0, width * F1 },
|
||||||
|
{ 0, -F1, height * F1 },
|
||||||
|
{ 0, 0, F1 },
|
||||||
|
}};
|
||||||
|
*dst = t;
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
case WL_OUTPUT_TRANSFORM_270:
|
||||||
|
{
|
||||||
|
pixman_transform_t t = {{
|
||||||
|
{ 0, -F1, width * F1 },
|
||||||
|
{ F1, 0, 0 },
|
||||||
|
{ 0, 0, F1 },
|
||||||
|
}};
|
||||||
|
*dst = t;
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
case WL_OUTPUT_TRANSFORM_FLIPPED:
|
||||||
|
{
|
||||||
|
pixman_transform_t t = {{
|
||||||
|
{ -F1, 0, width * F1 },
|
||||||
|
{ 0, F1, 0 },
|
||||||
|
{ 0, 0, F1 },
|
||||||
|
}};
|
||||||
|
*dst = t;
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
case WL_OUTPUT_TRANSFORM_FLIPPED_90:
|
||||||
|
{
|
||||||
|
pixman_transform_t t = {{
|
||||||
|
{ 0, F1, 0 },
|
||||||
|
{ F1, 0, 0 },
|
||||||
|
{ 0, 0, F1 },
|
||||||
|
}};
|
||||||
|
*dst = t;
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
case WL_OUTPUT_TRANSFORM_FLIPPED_180:
|
||||||
|
{
|
||||||
|
pixman_transform_t t = {{
|
||||||
|
{ F1, 0, 0 },
|
||||||
|
{ 0, -F1, height * F1 },
|
||||||
|
{ 0, 0, F1 },
|
||||||
|
}};
|
||||||
|
*dst = t;
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
case WL_OUTPUT_TRANSFORM_FLIPPED_270:
|
||||||
|
{
|
||||||
|
pixman_transform_t t = {{
|
||||||
|
{ 0, -F1, width * F1 },
|
||||||
|
{ -F1, 0, height * F1 },
|
||||||
|
{ 0, 0, F1 },
|
||||||
|
}};
|
||||||
|
*dst = t;
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
#undef F1
|
||||||
|
|
||||||
|
abort();
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Borrowed these from wlroots */
|
||||||
|
enum wl_output_transform wv_output_transform_invert(
|
||||||
|
enum wl_output_transform tr) {
|
||||||
|
if ((tr & WL_OUTPUT_TRANSFORM_90) && !(tr & WL_OUTPUT_TRANSFORM_FLIPPED)) {
|
||||||
|
tr ^= WL_OUTPUT_TRANSFORM_180;
|
||||||
|
}
|
||||||
|
return tr;
|
||||||
|
}
|
||||||
|
|
||||||
|
enum wl_output_transform wv_output_transform_compose(
|
||||||
|
enum wl_output_transform tr_a, enum wl_output_transform tr_b) {
|
||||||
|
uint32_t flipped = (tr_a ^ tr_b) & WL_OUTPUT_TRANSFORM_FLIPPED;
|
||||||
|
uint32_t rotation_mask = WL_OUTPUT_TRANSFORM_90 | WL_OUTPUT_TRANSFORM_180;
|
||||||
|
uint32_t rotated;
|
||||||
|
if (tr_b & WL_OUTPUT_TRANSFORM_FLIPPED) {
|
||||||
|
// When a rotation of k degrees is followed by a flip, the
|
||||||
|
// equivalent transform is a flip followed by a rotation of
|
||||||
|
// -k degrees.
|
||||||
|
rotated = (tr_b - tr_a) & rotation_mask;
|
||||||
|
} else {
|
||||||
|
rotated = (tr_a + tr_b) & rotation_mask;
|
||||||
|
}
|
||||||
|
return flipped | rotated;
|
||||||
|
}
|
||||||
|
|
||||||
|
void wv_pixman_render(struct nvnc_fb* dst, const struct wv_buffer* src,
|
||||||
|
enum wl_output_transform transform,
|
||||||
|
struct pixman_region16* damage) {
|
||||||
|
uint32_t* addr = nvnc_fb_get_addr(dst);
|
||||||
|
uint32_t width = nvnc_fb_get_width(dst);
|
||||||
|
uint32_t height = nvnc_fb_get_height(dst);
|
||||||
|
|
||||||
|
// TODO: Check that both buffers have the same dimensions
|
||||||
|
|
||||||
|
pixman_image_t* dstimg = pixman_image_create_bits_no_clear(
|
||||||
|
PIXMAN_x8b8g8r8, width, height, addr, 4 * width);
|
||||||
|
|
||||||
|
pixman_format_code_t src_fmt = 0;
|
||||||
|
fourcc_to_pixman_fmt(&src_fmt, src->format);
|
||||||
|
|
||||||
|
pixman_image_t* srcimg = pixman_image_create_bits_no_clear(
|
||||||
|
src_fmt, width, height, src->pixels, src->stride);
|
||||||
|
|
||||||
|
if (src->y_inverted)
|
||||||
|
transform = wv_output_transform_compose(
|
||||||
|
WL_OUTPUT_TRANSFORM_FLIPPED_180, transform);
|
||||||
|
|
||||||
|
pixman_transform_t pxform;
|
||||||
|
pixman_transform_from_wl_output_transform(&pxform, transform, width,
|
||||||
|
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,
|
||||||
|
width, height);
|
||||||
|
|
||||||
|
pixman_image_unref(srcimg);
|
||||||
|
pixman_image_unref(dstimg);
|
||||||
|
}
|
Loading…
Reference in New Issue