forked from AuroraMiddleware/gtk
2ff74eb667
GTK will not up front know how to correctly calculate a size, since it will not be able to reliably predict the constraints that may exist where it will be mapped. Thus, to handle this, calculate the size of the toplevel by having GDK emitting a signal called 'compute-size' that will contain information needed for computing a toplevel window size. This signal may be emitted at any time, e.g. during gdk_toplevel_present(), or spontaneously if constraints change. This also drops the max size from the toplevel layout, while moving the min size from the toplevel layout struct to the struct passed via the signal, This needs changes to a test case where we make sure we process GDK_CONFIGURE etc, which means we also needs to show the window and process all pending events in the test-focus-chain test case.
178 lines
5.1 KiB
C
178 lines
5.1 KiB
C
#include <gtk/gtk.h>
|
|
|
|
static gboolean benchmark = FALSE;
|
|
static gboolean dump_variant = FALSE;
|
|
static gboolean fallback = FALSE;
|
|
static int runs = 1;
|
|
|
|
static GOptionEntry options[] = {
|
|
{ "benchmark", 'b', 0, G_OPTION_ARG_NONE, &benchmark, "Time operations", NULL },
|
|
{ "dump-variant", 'd', 0, G_OPTION_ARG_NONE, &dump_variant, "Dump GVariant structure", NULL },
|
|
{ "fallback", '\0', 0, G_OPTION_ARG_NONE, &fallback, "Draw node without a renderer", NULL },
|
|
{ "runs", 'r', 0, G_OPTION_ARG_INT, &runs, "Render the test N times", "N" },
|
|
{ NULL }
|
|
};
|
|
|
|
static void
|
|
deserialize_error_func (const GtkCssSection *section,
|
|
const GError *error,
|
|
gpointer user_data)
|
|
{
|
|
char *section_str = gtk_css_section_to_string (section);
|
|
|
|
g_warning ("Error at %s: %s", section_str, error->message);
|
|
|
|
g_free (section_str);
|
|
}
|
|
|
|
|
|
int
|
|
main(int argc, char **argv)
|
|
{
|
|
cairo_surface_t *surface;
|
|
GskRenderNode *node;
|
|
GError *error = NULL;
|
|
GBytes *bytes;
|
|
gint64 start, end;
|
|
char *contents;
|
|
gsize len;
|
|
int run;
|
|
GOptionContext *context;
|
|
|
|
context = g_option_context_new ("NODE-FILE PNG-FILE");
|
|
g_option_context_add_main_entries (context, options, NULL);
|
|
if (!g_option_context_parse (context, &argc, &argv, &error))
|
|
{
|
|
g_printerr ("Option parsing failed: %s\n", error->message);
|
|
return 1;
|
|
}
|
|
|
|
gtk_init ();
|
|
|
|
if (runs < 1)
|
|
{
|
|
g_printerr ("Number of runs given with -r/--runs must be at least 1 and not %d.\n", runs);
|
|
return 1;
|
|
}
|
|
if (!(argc == 3 || (argc == 2 && (dump_variant || benchmark))))
|
|
{
|
|
g_printerr ("Usage: %s [OPTIONS] NODE-FILE PNG-FILE\n", argv[0]);
|
|
return 1;
|
|
}
|
|
|
|
if (!g_file_get_contents (argv[1], &contents, &len, &error))
|
|
{
|
|
g_printerr ("Could not open node file: %s\n", error->message);
|
|
return 1;
|
|
}
|
|
|
|
bytes = g_bytes_new_take (contents, len);
|
|
if (dump_variant)
|
|
{
|
|
GVariant *variant = g_variant_new_from_bytes (G_VARIANT_TYPE ("(suuv)"), bytes, FALSE);
|
|
char *s;
|
|
|
|
s = g_variant_print (variant, FALSE);
|
|
g_print ("%s\n", s);
|
|
g_free (s);
|
|
g_variant_unref (variant);
|
|
}
|
|
|
|
start = g_get_monotonic_time ();
|
|
node = gsk_render_node_deserialize (bytes, deserialize_error_func, NULL);
|
|
end = g_get_monotonic_time ();
|
|
if (benchmark)
|
|
{
|
|
char *bytes_string = g_format_size (g_bytes_get_size (bytes));
|
|
g_print ("Loaded %s in %.4gs\n", bytes_string, (double) (end - start) / G_USEC_PER_SEC);
|
|
g_free (bytes_string);
|
|
}
|
|
g_bytes_unref (bytes);
|
|
|
|
if (node == NULL)
|
|
{
|
|
return 1;
|
|
}
|
|
|
|
if (fallback)
|
|
{
|
|
graphene_rect_t bounds;
|
|
cairo_t *cr;
|
|
|
|
gsk_render_node_get_bounds (node, &bounds);
|
|
surface = cairo_image_surface_create (CAIRO_FORMAT_ARGB32, ceil (bounds.size.width), ceil (bounds.size.height));
|
|
cr = cairo_create (surface);
|
|
|
|
cairo_translate (cr, - bounds.origin.x, - bounds.origin.y);
|
|
for (run = 0; run < runs; run++)
|
|
{
|
|
if (run > 0)
|
|
{
|
|
cairo_save (cr);
|
|
cairo_set_operator (cr, CAIRO_OPERATOR_CLEAR);
|
|
cairo_paint (cr);
|
|
cairo_restore (cr);
|
|
}
|
|
start = g_get_monotonic_time ();
|
|
gsk_render_node_draw (node, cr);
|
|
end = g_get_monotonic_time ();
|
|
if (benchmark)
|
|
g_print ("Run %d: Rendered fallback in %.4gs\n", run, (double) (end - start) / G_USEC_PER_SEC);
|
|
}
|
|
|
|
cairo_destroy (cr);
|
|
}
|
|
else
|
|
{
|
|
GskRenderer *renderer;
|
|
GdkSurface *window;
|
|
GdkTexture *texture = NULL;
|
|
|
|
window = gdk_surface_new_toplevel (gdk_display_get_default());
|
|
renderer = gsk_renderer_new_for_surface (window);
|
|
|
|
for (run = 0; run < runs; run++)
|
|
{
|
|
if (run > 0)
|
|
g_object_unref (texture);
|
|
start = g_get_monotonic_time ();
|
|
texture = gsk_renderer_render_texture (renderer, node, NULL);
|
|
end = g_get_monotonic_time ();
|
|
if (benchmark)
|
|
g_print ("Run %u: Rendered using %s in %.4gs\n", run, G_OBJECT_TYPE_NAME (renderer), (double) (end - start) / G_USEC_PER_SEC);
|
|
}
|
|
|
|
surface = cairo_image_surface_create (CAIRO_FORMAT_ARGB32,
|
|
gdk_texture_get_width (texture),
|
|
gdk_texture_get_height (texture));
|
|
gdk_texture_download (texture,
|
|
cairo_image_surface_get_data (surface),
|
|
cairo_image_surface_get_stride (surface));
|
|
cairo_surface_mark_dirty (surface);
|
|
gsk_renderer_unrealize (renderer);
|
|
g_object_unref (texture);
|
|
g_object_unref (window);
|
|
g_object_unref (renderer);
|
|
}
|
|
|
|
gsk_render_node_unref (node);
|
|
|
|
if (argc > 2)
|
|
{
|
|
cairo_status_t status;
|
|
|
|
status = cairo_surface_write_to_png (surface, argv[2]);
|
|
|
|
if (status != CAIRO_STATUS_SUCCESS)
|
|
{
|
|
cairo_surface_destroy (surface);
|
|
g_print ("Failed to save PNG file: %s\n", cairo_status_to_string (status));
|
|
return 1;
|
|
}
|
|
}
|
|
|
|
cairo_surface_destroy (surface);
|
|
|
|
return 0;
|
|
}
|