@ -61,6 +61,13 @@ copy_bgra_yflip(uint8_t *dst, uint8_t *src, int height, int stride)
}
}
static void
copy_bgra ( uint8_t * dst , uint8_t * src , int height , int stride )
{
/* TODO: optimize this out */
memcpy ( dst , src , height * stride ) ;
}
static void
copy_row_swap_RB ( void * vdst , void * vsrc , int bytes )
{
@ -91,6 +98,19 @@ copy_rgba_yflip(uint8_t *dst, uint8_t *src, int height, int stride)
}
}
static void
copy_rgba ( uint8_t * dst , uint8_t * src , int height , int stride )
{
uint8_t * end ;
end = dst + height * stride ;
while ( dst < end ) {
copy_row_swap_RB ( dst , src , stride ) ;
dst + = stride ;
src + = stride ;
}
}
static void
screenshooter_frame_notify ( struct wl_listener * listener , void * data )
{
@ -98,12 +118,13 @@ screenshooter_frame_notify(struct wl_listener *listener, void *data)
container_of ( listener ,
struct screenshooter_frame_listener , listener ) ;
struct weston_output * output = data ;
struct weston_compositor * compositor = output - > compositor ;
int32_t stride ;
uint8_t * pixels , * d , * s ;
output - > disable_planes - - ;
wl_list_remove ( & listener - > link ) ;
stride = l - > buffer - > width * ( PIXMAN_FORMAT_BPP ( output - > compositor - > read_format ) / 8 ) ;
stride = l - > buffer - > width * ( PIXMAN_FORMAT_BPP ( compositor - > read_format ) / 8 ) ;
pixels = malloc ( stride * l - > buffer - > height ) ;
if ( pixels = = NULL ) {
@ -112,8 +133,8 @@ screenshooter_frame_notify(struct wl_listener *listener, void *data)
return ;
}
output - > compositor - > renderer - > read_pixels ( output ,
output - > compositor - > read_format , pixels ,
compositor - > renderer - > read_pixels ( output ,
compositor - > read_format , pixels ,
0 , 0 , output - > current - > width ,
output - > current - > height ) ;
@ -122,14 +143,20 @@ screenshooter_frame_notify(struct wl_listener *listener, void *data)
d = wl_shm_buffer_get_data ( l - > buffer ) ;
s = pixels + stride * ( l - > buffer - > height - 1 ) ;
switch ( output - > compositor - > read_format ) {
switch ( compositor - > read_format ) {
case PIXMAN_a8r8g8b8 :
case PIXMAN_x8r8g8b8 :
copy_bgra_yflip ( d , s , output - > current - > height , stride ) ;
if ( compositor - > capabilities & WESTON_CAP_CAPTURE_YFLIP )
copy_bgra_yflip ( d , s , output - > current - > height , stride ) ;
else
copy_bgra ( d , pixels , output - > current - > height , stride ) ;
break ;
case PIXMAN_x8b8g8r8 :
case PIXMAN_a8b8g8r8 :
copy_rgba_yflip ( d , s , output - > current - > height , stride ) ;
if ( compositor - > capabilities & WESTON_CAP_CAPTURE_YFLIP )
copy_rgba_yflip ( d , s , output - > current - > height , stride ) ;
else
copy_rgba ( d , pixels , output - > current - > height , stride ) ;
break ;
default :
break ;
@ -218,6 +245,7 @@ screenshooter_binding(struct weston_seat *seat, uint32_t time, uint32_t key,
struct weston_recorder {
struct weston_output * output ;
uint32_t * frame , * rect ;
uint32_t * tmpbuf ;
uint32_t total ;
int fd ;
struct wl_listener frame_listener ;
@ -260,7 +288,7 @@ transform_rect(struct weston_output *output, pixman_box32_t *r)
{
pixman_box32_t s = * r ;
switch ( output - > transform ) {
switch ( output - > transform ) {
case WL_OUTPUT_TRANSFORM_FLIPPED :
case WL_OUTPUT_TRANSFORM_FLIPPED_90 :
case WL_OUTPUT_TRANSFORM_FLIPPED_180 :
@ -272,7 +300,7 @@ transform_rect(struct weston_output *output, pixman_box32_t *r)
break ;
}
switch ( output - > transform ) {
switch ( output - > transform ) {
case WL_OUTPUT_TRANSFORM_NORMAL :
case WL_OUTPUT_TRANSFORM_FLIPPED :
r - > x1 = s . x1 ;
@ -310,6 +338,7 @@ weston_recorder_frame_notify(struct wl_listener *listener, void *data)
struct weston_recorder * recorder =
container_of ( listener , struct weston_recorder , frame_listener ) ;
struct weston_output * output = data ;
struct weston_compositor * compositor = output - > compositor ;
uint32_t msecs = output - > frame_time ;
pixman_box32_t * r ;
pixman_region32_t damage ;
@ -320,6 +349,15 @@ weston_recorder_frame_notify(struct wl_listener *listener, void *data)
uint32_t nrects ;
} header ;
struct iovec v [ 2 ] ;
int do_yflip ;
int y_orig ;
uint32_t * outbuf ;
do_yflip = ! ! ( compositor - > capabilities & WESTON_CAP_CAPTURE_YFLIP ) ;
if ( do_yflip )
outbuf = recorder - > rect ;
else
outbuf = recorder - > tmpbuf ;
pixman_region32_init ( & damage ) ;
pixman_region32_intersect ( & damage , & output - > region ,
@ -344,17 +382,26 @@ weston_recorder_frame_notify(struct wl_listener *listener, void *data)
for ( i = 0 ; i < n ; i + + ) {
width = r [ i ] . x2 - r [ i ] . x1 ;
height = r [ i ] . y2 - r [ i ] . y1 ;
output - > compositor - > renderer - > read_pixels ( output ,
output - > compositor - > read_format , recorder - > rect ,
r [ i ] . x1 , output - > current - > height - r [ i ] . y2 ,
width , height ) ;
if ( do_yflip )
y_orig = output - > current - > height - r [ i ] . y2 ;
else
y_orig = r [ i ] . y1 ;
compositor - > renderer - > read_pixels ( output ,
compositor - > read_format , recorder - > rect ,
r [ i ] . x1 , y_orig , width , height ) ;
s = recorder - > rect ;
p = recorder - > rect ;
p = outbuf ;
run = prev = 0 ; /* quiet gcc */
for ( j = 0 ; j < height ; j + + ) {
d = recorder - > frame +
stride * ( r [ i ] . y2 - j - 1 ) + r [ i ] . x1 ;
if ( do_yflip )
y_orig = r [ i ] . y2 - j - 1 ;
else
y_orig = r [ i ] . y1 + j ;
d = recorder - > frame + stride * y_orig + r [ i ] . x1 ;
for ( k = 0 ; k < width ; k + + ) {
next = * s + + ;
delta = component_delta ( next , * d ) ;
@ -372,15 +419,14 @@ weston_recorder_frame_notify(struct wl_listener *listener, void *data)
p = output_run ( p , prev , run ) ;
recorder - > total + = write ( recorder - > fd ,
recorder - > rect ,
( p - recorder - > rect ) * 4 ) ;
outbuf , ( p - outbuf ) * 4 ) ;
#if 0
fprintf ( stderr ,
" %dx%d at %d,%d rle from %d to %d bytes (%f) total %dM \n " ,
width , height , r [ i ] . x1 , r [ i ] . y1 ,
width * height * 4 , ( int ) ( p - recorder - > rect ) * 4 ,
( float ) ( p - recorder - > rect ) / ( width * height ) ,
width * height * 4 , ( int ) ( p - outbuf ) * 4 ,
( float ) ( p - outbuf ) / ( width * height ) ,
recorder - > total / 1024 / 1024 ) ;
# endif
}
@ -391,9 +437,13 @@ weston_recorder_frame_notify(struct wl_listener *listener, void *data)
static void
weston_recorder_create ( struct weston_output * output , const char * filename )
{
struct weston_compositor * compositor = output - > compositor ;
struct weston_recorder * recorder ;
int stride , size ;
struct { uint32_t magic , format , width , height ; } header ;
int do_yflip ;
do_yflip = ! ! ( compositor - > capabilities & WESTON_CAP_CAPTURE_YFLIP ) ;
recorder = malloc ( sizeof * recorder ) ;
@ -406,9 +456,14 @@ weston_recorder_create(struct weston_output *output, const char *filename)
recorder - > output = output ;
memset ( recorder - > frame , 0 , size ) ;
if ( do_yflip )
recorder - > tmpbuf = NULL ;
else
recorder - > tmpbuf = malloc ( size ) ;
header . magic = WCAP_HEADER_MAGIC ;
switch ( output - > compositor - > read_format ) {
switch ( compositor - > read_format ) {
case PIXMAN_a8r8g8b8 :
header . format = WCAP_FORMAT_XRGB8888 ;
break ;
@ -445,6 +500,7 @@ weston_recorder_destroy(struct weston_recorder *recorder)
{
wl_list_remove ( & recorder - > frame_listener . link ) ;
close ( recorder - > fd ) ;
free ( recorder - > tmpbuf ) ;
free ( recorder - > frame ) ;
free ( recorder - > rect ) ;
recorder - > output - > disable_planes - - ;