@ -31,7 +31,9 @@
# include <unistd.h>
# include <errno.h>
# include <sys/mman.h>
# include <cairo.h>
# include "zalloc.h"
# include "shared/os-compatibility.h"
# include "weston-test-client-helper.h"
@ -979,3 +981,159 @@ check_surfaces_match_in_clip(const struct surface *a, const struct surface *b, c
return true ;
}
/** write_surface_as_png()
*
* Writes out a given weston test surface to disk as a PNG image
* using the provided filename ( with path ) .
*
* @ returns true if successfully saved file ; false otherwise .
*/
bool
write_surface_as_png ( const struct surface * weston_surface , const char * fname )
{
cairo_surface_t * cairo_surface ;
cairo_status_t status ;
int bpp = 4 ; /* Assume ARGB */
int stride = bpp * weston_surface - > width ;
cairo_surface = cairo_image_surface_create_for_data ( weston_surface - > data ,
CAIRO_FORMAT_ARGB32 ,
weston_surface - > width ,
weston_surface - > height ,
stride ) ;
printf ( " Writing PNG to disk \n " ) ;
status = cairo_surface_write_to_png ( cairo_surface , fname ) ;
if ( status ! = CAIRO_STATUS_SUCCESS ) {
printf ( " Failed to save screenshot: %s \n " ,
cairo_status_to_string ( status ) ) ;
return false ;
}
cairo_surface_destroy ( cairo_surface ) ;
return true ;
}
/** load_surface_from_png()
*
* Reads a PNG image from disk using the given filename ( and path )
* and returns as a freshly allocated weston test surface .
*
* @ returns weston test surface with image , which should be free ' d
* when no longer used ; or , NULL in case of error .
*/
struct surface *
load_surface_from_png ( const char * fname )
{
struct surface * reference ;
cairo_surface_t * reference_cairo_surface ;
cairo_status_t status ;
size_t source_data_size ;
int bpp ;
int stride ;
reference_cairo_surface = cairo_image_surface_create_from_png ( fname ) ;
status = cairo_surface_status ( reference_cairo_surface ) ;
if ( status ! = CAIRO_STATUS_SUCCESS ) {
printf ( " Could not open %s: %s \n " , fname , cairo_status_to_string ( status ) ) ;
cairo_surface_destroy ( reference_cairo_surface ) ;
return NULL ;
}
/* Disguise the cairo surface in a weston test surface */
reference = zalloc ( sizeof * reference ) ;
if ( reference = = NULL ) {
perror ( " zalloc reference " ) ;
cairo_surface_destroy ( reference_cairo_surface ) ;
return NULL ;
}
reference - > width = cairo_image_surface_get_width ( reference_cairo_surface ) ;
reference - > height = cairo_image_surface_get_height ( reference_cairo_surface ) ;
stride = cairo_image_surface_get_stride ( reference_cairo_surface ) ;
source_data_size = stride * reference - > height ;
/* Check that the file's stride matches our assumption */
bpp = 4 ;
if ( stride ! = bpp * reference - > width ) {
printf ( " Mismatched stride for screenshot reference image %s \n " , fname ) ;
cairo_surface_destroy ( reference_cairo_surface ) ;
free ( reference ) ;
return NULL ;
}
/* Allocate new buffer for our weston reference, and copy the data from
the cairo surface so we can destroy it */
reference - > data = zalloc ( source_data_size ) ;
if ( reference - > data = = NULL ) {
perror ( " zalloc reference data " ) ;
cairo_surface_destroy ( reference_cairo_surface ) ;
free ( reference ) ;
return NULL ;
}
memcpy ( reference - > data ,
cairo_image_surface_get_data ( reference_cairo_surface ) ,
source_data_size ) ;
cairo_surface_destroy ( reference_cairo_surface ) ;
return reference ;
}
/** create_screenshot_surface()
*
* Allocates and initializes a weston test surface for use in
* storing a screenshot of the client ' s output . Establishes a
* shm backed wl_buffer for retrieving screenshot image data
* from the server , sized to match the client ' s output display .
*
* @ returns stack allocated surface image , which should be
* free ' d when done using it .
*/
struct surface *
create_screenshot_surface ( struct client * client )
{
struct surface * screenshot ;
screenshot = zalloc ( sizeof * screenshot ) ;
if ( screenshot = = NULL )
return NULL ;
screenshot - > wl_buffer = create_shm_buffer ( client ,
client - > output - > width ,
client - > output - > height ,
& screenshot - > data ) ;
screenshot - > height = client - > output - > height ;
screenshot - > width = client - > output - > width ;
return screenshot ;
}
/** capture_screenshot_of_output()
*
* Requests a screenshot from the server of the output that the
* client appears on . The image data returned from the server
* can be accessed from the screenshot surface ' s data member .
*
* @ returns a new surface object , which should be free ' d when no
* longer needed .
*/
struct surface *
capture_screenshot_of_output ( struct client * client )
{
struct surface * screenshot ;
/* Create a surface to hold the screenshot */
screenshot = create_screenshot_surface ( client ) ;
client - > test - > buffer_copy_done = 0 ;
weston_test_capture_screenshot ( client - > test - > weston_test ,
client - > output - > wl_output ,
screenshot - > wl_buffer ) ;
while ( client - > test - > buffer_copy_done = = 0 )
if ( wl_display_dispatch ( client - > wl_display ) < 0 )
break ;
/* FIXME: Document somewhere the orientation the screenshot is taken
* and how the clip coords are interpreted , in case of scaling / transform .
* If we ' re using read_pixels ( ) just make sure it is documented somewhere .
* Protocol docs in the XML , comparison function docs in Doxygen style .
*/
return screenshot ;
}