gtk/gsk/gskbroadwayrenderer.c
2017-11-23 10:48:29 +01:00

179 lines
5.0 KiB
C

#include "config.h"
#include "gskbroadwayrendererprivate.h"
#include "broadway/gdkprivate-broadway.h"
#include "gskdebugprivate.h"
#include "gskrendererprivate.h"
#include "gskrendernodeprivate.h"
#include "gdk/gdktextureprivate.h"
struct _GskBroadwayRenderer
{
GskRenderer parent_instance;
};
struct _GskBroadwayRendererClass
{
GskRendererClass parent_class;
};
G_DEFINE_TYPE (GskBroadwayRenderer, gsk_broadway_renderer, GSK_TYPE_RENDERER)
static gboolean
gsk_broadway_renderer_realize (GskRenderer *self,
GdkWindow *window,
GError **error)
{
return TRUE;
}
static void
gsk_broadway_renderer_unrealize (GskRenderer *self)
{
}
static GdkDrawingContext *
gsk_broadway_renderer_begin_draw_frame (GskRenderer *renderer,
const cairo_region_t *update_area)
{
cairo_region_t *region;
GdkDrawingContext *result;
cairo_rectangle_int_t whole_window;
GdkWindow *window;
window = gsk_renderer_get_window (renderer);
whole_window = (cairo_rectangle_int_t) {
0, 0,
gdk_window_get_width (window),
gdk_window_get_height (window)
};
region = cairo_region_create_rectangle (&whole_window);
result = gdk_window_begin_draw_frame (window, NULL, region);
cairo_region_destroy (region);
return result;
}
static GdkTexture *
gsk_broadway_renderer_render_texture (GskRenderer *self,
GskRenderNode *root,
const graphene_rect_t *viewport)
{
GdkTexture *texture;
cairo_surface_t *surface;
cairo_t *cr;
surface = cairo_image_surface_create (CAIRO_FORMAT_ARGB32, ceil (viewport->size.width), ceil (viewport->size.height));
cr = cairo_create (surface);
cairo_translate (cr, - viewport->origin.x, - viewport->origin.y);
gsk_render_node_draw (root, cr);
cairo_destroy (cr);
texture = gdk_texture_new_for_surface (surface);
cairo_surface_destroy (surface);
return texture;
}
static void
add_uint32 (GArray *nodes, guint32 v)
{
g_array_append_val (nodes, v);
}
static void
gsk_broadway_renderer_add_node (GskRenderer *self,
GArray *nodes,
GPtrArray *node_textures,
GskRenderNode *node)
{
GdkDisplay *display = gsk_renderer_get_display (self);
switch (gsk_render_node_get_node_type (node))
{
case GSK_NOT_A_RENDER_NODE:
g_assert_not_reached ();
return;
case GSK_CONTAINER_NODE:
{
guint i;
add_uint32 (nodes, BROADWAY_NODE_CONTAINER);
add_uint32 (nodes, gsk_container_node_get_n_children (node));
for (i = 0; i < gsk_container_node_get_n_children (node); i++)
gsk_broadway_renderer_add_node (self, nodes, node_textures,
gsk_container_node_get_child (node, i));
}
return;
default:
{
int x = floorf (node->bounds.origin.x);
int y = floorf (node->bounds.origin.y);
int width = ceil (node->bounds.origin.x + node->bounds.size.width) - x;
int height = ceil (node->bounds.origin.y + node->bounds.size.height) - y;
cairo_surface_t *surface;
GdkTexture *texture;
guint32 texture_id;
cairo_t *cr;
surface = cairo_image_surface_create (CAIRO_FORMAT_ARGB32, width, height);
cr = cairo_create (surface);
cairo_translate (cr, -x, -y);
gsk_render_node_draw (node, cr);
cairo_destroy (cr);
texture = gdk_texture_new_for_surface (surface);
g_ptr_array_add (node_textures, texture); /* Transfers ownership to node_textures */
texture_id = gdk_broadway_display_ensure_texture (display, texture);
add_uint32 (nodes, BROADWAY_NODE_TEXTURE);
add_uint32 (nodes, x);
add_uint32 (nodes, y);
add_uint32 (nodes, width);
add_uint32 (nodes, height);
add_uint32 (nodes, texture_id);
}
return;
}
}
static void
gsk_broadway_renderer_render (GskRenderer *self,
GskRenderNode *root)
{
GdkWindow *window = gsk_renderer_get_window (self);
GArray *nodes = g_array_new (FALSE, FALSE, sizeof(guint32));
GPtrArray *node_textures = g_ptr_array_new_with_free_func (g_object_unref);
gsk_broadway_renderer_add_node (self, nodes, node_textures, root);
gdk_broadway_window_set_nodes (window, nodes, node_textures);
g_array_unref (nodes);
g_ptr_array_unref (node_textures);
}
static void
gsk_broadway_renderer_class_init (GskBroadwayRendererClass *klass)
{
GskRendererClass *renderer_class = GSK_RENDERER_CLASS (klass);
renderer_class->begin_draw_frame = gsk_broadway_renderer_begin_draw_frame;
renderer_class->realize = gsk_broadway_renderer_realize;
renderer_class->unrealize = gsk_broadway_renderer_unrealize;
renderer_class->render = gsk_broadway_renderer_render;
renderer_class->render_texture = gsk_broadway_renderer_render_texture;
}
static void
gsk_broadway_renderer_init (GskBroadwayRenderer *self)
{
}