Create pixman renderer

pixman-rendering
Andri Yngvason 2020-06-21 11:54:46 +00:00
parent 47a8dc8040
commit 49a2d578d9
4 changed files with 179 additions and 38 deletions

View File

@ -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);

View File

@ -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 = [

View File

@ -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,

View File

@ -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);
}